Gesetzt wird der Defaultwert in der Funktion br_init_port in br.c, die den Port initialisiert. Dazu wurde eine Funktion set_port_vlan_id geschrieben, die auch später verwendet werden kann, um einen Port einem VLAN zuzuweisen.
771 static void set_port_vlan_id(int port_no, unsigned int vlan_id)
772 {
773 port_info[port_no].vlan_id = vlan_id;
774 }
Für den Fall, daß der Frame vom host stack empfangen wird und dieser noch keinem VLAN zugeordnet ist, wird diesem in der Funktion br_tx_frame explizit ein VLAN zugeordnet. Sinnvollerweise ist der Switch selbst Bestandteil aller VLAN's. Das führt zu der Frage, wie der Switch durch die Zuordnung nur einer VLAN ID mehreren VLAN's angehören kann. Offensichtlich besteht zwischen dem Objekt Port bzw. MAC-Adresse und dem Objekt VLAN eine n:n Beziehung. Ein Port (oder eine MAC-Adresse) kann einem oder mehreren VLAN's zugeordnet sein. Umgekehrt enthält ein VLAN einen oder mehrere Ports (oder MAC-Adressen). Um den rechnerischen Aufwand bei der Prüfung einer verketteten Liste von Objekten zu umgehen, wird an dieser Stelle eine binäre UND-Verknüpfung von Integerwerten angewandt. Somit ergeben sich 32 unterschiedliche VLAN's. Liegt ein Port bspw. in VLAN 1 und VLAN 2, so bekommt er die VLAN ID 3. Die Funktion check_vlan_id verdeutlicht dies:
1712 static int check_vlan_id(struct fdb *s, struct fdb *f)
1713 {
[...]
1736 if ((s->vlan_id & f->vlan_id) == 0)
1737 return(FALSE);
1738 return (TRUE);
1729 }
Die Struktur fdb stellt den Datentyp dar, der als Knoten im AVL-Baum gespeichert ist. Verglichen werden hier die VLAN ID's von Quell- und Zieladresse. Bei Übereinstimmung liefert der Code true zurück, ansonsten false.
Analog dazu werden in br_forward die Portzuordnungen verglichen:
1650 /*
1651 * Sending
1652 * only if: source-port != destination-port
1653 * port.state == Forwarding
1654 * source.address.vlan_id == dest.address.vlan_id
1655 * source.port.vlan_id == dest.port.vlan_id
1656 */
1657 if (f->port!=port && port_info[f->port].state == Forwarding
1658 &&
1659 check_vlan_id(s, f)
1660 &&
1661 ((port_info[f->port].vlan_id & port_info[port].vlan_id) != 0) )
1662 {
[...]
1701 }
Bei Erfolg wird der Frame an den entsprechenden Port geforwardet, bei Mißerfolg durch die Funktion br_dev_drop vernichtet.
Das Setzen der VLAN ID's ist ungleich aufwendiger. Die Funktion br_ioctl interagiert mittels I/O Aufrufen zwischen dem Konfigurationsprogramm und dem Kernel. Sie erwartet als Eingabe einen Parameter vom Typ Integer. Die Aufschlüsselung zwischen Integerwert und dem zugehörigen Define ist in br.h beschrieben. Für die VLAN-Zuordnung sind zwei neue Defines hinzugekommen: BRCMD_VLAN_CONFIG mit Wert 16 und BRCMD_MAC_VLAN mit Wert 17. Erhält der Kernel nun einen ioctl, dann ruft er die entsprechende Routine auf: set_port_vlan_id, um die Port-VLAN-Zuordnung zu realisieren und set_mac_vlan_id für die MAC-Adressen-VLAN Zuordnung. Als Argumente werden jeweils Strukturen vom Typ br_cf übergeben, die in br.h folgendermaßen deklariert wird:
212 struct br_cf {
213 unsigned int cmd;
214 unsigned int arg1;
215 unsigned int arg2;
216 unsigned char ula[6];
217 };
cmd ist das schon angesprochene Kommando, arg1 und arg2 können Zahlenwerte aufnehmen, bspw. die Portnummer. Interessant ist lediglich das 6 Byte große Array. Dieses wird nur für die Aufnahme der MAC-Adresse in hexadezimaler Form benötigt, der gesamte Kernelcode arbeitet mit diesem Array, so daß hier nicht davon abgewichen werden soll. Die Funktion set_port_vlan_id wurde weiter oben schon beschrieben.
Die Implementierung der Zuordnung von MAC-Adresse zu einem oder mehreren VLAN's wird im folgenden beschrieben. Zunächst wird die switchinterne Tabelle, die die Information über die Zuordnung von Port- zu MAC-Adressen beinhaltet, von der Tabelle für die MAC-Adressen zu VLAN Zuordnung getrennt. Der Einfachheit halber wurde dazu der vorhandene Code br_tree.c kopiert und in sw_tree.c umbenannt. Im Code selber wurden sämtliche Funktionen umbenannt. Aus addr_cmp wurde so sw_addr_cmp u.s.w. Weiterhin wurde die Struktur fdb aus br.h nach swdb kopiert und dessen Zeiger mit dem Präfix sw_ versehen. Damit entstand eine neue Tabelle für die Zuordnung von MAC-Adressen zu VLAN's in Form eines AVL-Baums.
Das Setzen der VLAN ID geschieht wieder durch einen Funktionsaufruf in br_ioctl.
1904 case BRCMD_MAC_VLAN:
1905 set_mac_vlan_id(bcf.arg1, &bcf.ula[0]);
1906 break;
Der Funktion set_mac_vlan_id werden als Parameter die VLAN ID und die MAC-Adresse übergeben. Die Funktion selber sieht folgendermaßen aus:
776 static int set_mac_vlan_id(unsigned int vlan_id, unsigned char *ula)
777 {
778 struct swdb *s, *m = NULL;
779
780 s = (struct swdb *)kmalloc(sizeof(struct swdb), GFP_ATOMIC);
781 if (!s) {
782 printk(KERN_DEBUG "br_learn: unable to malloc swdb\n");
783 return(-1);
784 }
785
786 m = sw_avl_find_addr(ula);
787 if (m) {
788 s->port = m->port;
789 }
790 else { /* unknown MAC-address */
791 printk(KERN_DEBUG "set_mac_vlan_id: unknown mac address\n");
792 return(-2);
793 }
794
795 memcpy(s->ula, ula, 6); /* specified mac address */
796 s->timer = CURRENT_TIME;
797 s->flags = FDB_ENT_VALID;
798
799 s->vlan_id = vlan_id; /* specified vlan_id */
800
801 if (sw_avl_insert(s) == 0) { /* update */
802 kfree(s);
803 return(0);
804 }
805 else { /* unknown MAC-address */
806 printk(KERN_DEBUG "set_mac_vlan_id: unknown mac address\n");
807 kfree(s);
808 return(-2);
809 }
810 }
Die Variablen s und m sind Zeiger auf eine Variable der Struktur swbd. Zunächst wird Speicherplatz für die Struktur allokiert und mit s eine Referenz darauf angelegt. Sollte der Speicher korrekt allokiert worden sein, prüft der Aufruf von sw_avl_find_addr(ula), ob die übergebene MAC-Adresse in der Switchtabelle schon bekannt ist und übergibt den zugehörigen Port an die durch den Zeiger s referenzierte Struktur. Danach werden die Felder ula, timer, flags und vlan_id gefüllt. Die Variable ula beinhaltet die übergebene MAC-Adresse, vlan_id die Zugehörigkeit zu den gewünschten VLAN's. Durch das Setzen von timer auf die aktuelle Zeit verlängert sich der timestap des aktuellen Eintrages. flags zeigt an, daß es sich um einen gültigen Eintrag handelt. Als nächstes wird durch Aufruf der Funktion sw_avl_insert(s) der betreffende Eintrag im AVL-Baum durch die neuen Werte überschrieben und danach der Speicherplatz wieder freigegeben.
Die Initialisierung einer neuen MAC-Adresse mit einem Default-VLAN Wert geschieht in der Funktion br_learn nach einem ähnlichem Schema:
1472 m = sw_avl_find_addr(skb->mac.ethernet->h_source);
1473 if (m) {
1474 s->vlan_id = m->vlan_id;
1475 }
1476 else { /* set default vlan_id */
1477 s->vlan_id = DEFAULT_VLAN_ID;
1478 }
Hierbei wird zunächst überprüft, ob zu der neu hinzugekommenen MAC-Adresse schon eine VLAN-Zuordnung besteht. Wenn dem so ist, wird diese Zuordnung beibehalten, ansonsten die neue DTE mit dem Defaultwert versehen. Grund für diese Abfrage ist, daß die Funktion br_learn sowohl dann aufgerufen wird, wenn der Status des betreffenden Ports auf Learning steht, als auch dann, wenn Frames geforwarded werden sollen. Bei jedem Frame, den der Switch weiterforwarded, wird der timestamp der betreffenden DTE an dieser Stelle erneuert. Übergeben wird der Funktion br_learn jedoch nur ein Konstrukt des Typs sk_buff, das keinen Eintrag für VLAN's vorsieht. Der Erweiterung von sk_buff um VLAN's steht entgegen, daß diese Struktur in weiten Bereichen des Netzcodes innerhalb des Kernels als temporärer Puffer eingesetzt wird. Daher sind die Folgen einer Änderung von sk_buff unvorhersehbar.