Lab 28 – SDN 2: zone VLAN e QinQ
Dipendenze
Sezione intitolata “Dipendenze”- Lab precedenti:
- Rete fisica: le porte dei nodi verso la rete sono un trunk che lascia passare qualsiasi tag. In produzione, sugli switch, si configurano come trunk con le VLAN ammesse.
- Nodi:
desopve01,desopve02,desopve03. - Template:
cephfs:vztmpl/debian-13-standard_13.6-1_amd64.tar.zst. - Credenziali:
root/<password-lab>→ Appendice B.
Obiettivi
Sezione intitolata “Obiettivi”- Creare reti VLAN come VNet dell’SDN invece che con il tag sulla scheda del guest.
- Usare Dry-Run per vedere quali file l’SDN cambierà prima di applicare.
- Capire il QinQ: una VLAN di servizio che contiene le VLAN dei clienti, con ethertype 802.1Q o 802.1ad.
- Verificare con
tcpdumpi tag che passano davvero tra i nodi e il problema dell’MTU.
Come funziona
Sezione intitolata “Come funziona”Zona VLAN
Sezione intitolata “Zona VLAN”Nel lab 20 il tag si scriveva sulla scheda del guest (tag=10). Con una zona VLAN il tag lo decide la VNet: si crea una VNet vnv30 con tag 30 e chi crea la VM sceglie vnv30 come bridge, senza sapere nulla di VLAN. Sui nodi la VNet diventa un bridge Linux che ha come porta vmbr1.30, la sottointerfaccia VLAN del bridge esistente. Con le VNet si possono anche dare permessi per singola rete (lab 44).
Zona QinQ
Sezione intitolata “Zona QinQ”Il QinQ impila due tag:
- il tag esterno, la service VLAN, è uno per zona: separa per esempio due clienti o due ambienti;
- il tag interno, la customer VLAN, è quello della VNet.
Due zone QinQ possono usare entrambe la VLAN 10 senza vedersi, perché viaggiano in service VLAN diverse.
| Zona | Frame sul trunk tra i nodi |
|---|---|
| VLAN, VNet tag 30 | MAC · 802.1Q 30 · IPv4 |
| QinQ, service VLAN 300 (802.1q) | MAC · 802.1Q 300 · 802.1Q 10 · IPv4 |
| QinQ, service VLAN 301 (802.1ad) | MAC · 802.1ad 301 (ethertype 0x88a8) · 802.1Q 10 · IPv4 |
Il protocollo della service VLAN è 802.1q per default; 802.1ad è quello previsto dallo standard per il tag esterno e va scelto se gli switch lo richiedono.
MTU: ogni tag aggiunge 4 byte al frame. Con due tag un pacchetto IP di 1500 byte produce un frame di 1526 byte (1522 senza FCS, come li conta tcpdump), contro i 1518 di un frame senza tag e i 1522 di un frame con un solo tag 802.1Q. La documentazione di Proxmox VE indica di ridurre l’MTU delle VNet QinQ a 1496 se la rete fisica ha MTU 1500, oppure di alzare l’MTU della rete fisica.
Procedura
Sezione intitolata “Procedura”1. Zona e VNet VLAN
Sezione intitolata “1. Zona e VNet VLAN”-
Datacenter → SDN → Zones → Add → VLAN. ID
vlanz, Bridgevmbr1:
-
VNets → Create: Name
vnv30, Zonevlanz, Tag30:
2. Dry-Run prima di applicare
Sezione intitolata “2. Dry-Run prima di applicare”-
Nella pagina SDN premi Dry-Run: per ogni nodo mostra le differenze tra i file attuali e quelli che Apply scriverà.

Due cose da notare:
- in Interfaces Config compare il nuovo bridge
vnv30con portavmbr1.30; - in FRR Config il Dry-Run mostra il
frr.confche l’SDN genera al posto di quello di default. Il file sul nodo viene scritto davvero quando servono un controller o una fabric (lab 30-31): da quel momento FRR lo gestisce l’SDN, e chi usa FRR a mano per altro deve farlo dall’SDN.
- in Interfaces Config compare il nuovo bridge
-
Applica, anche da riga di comando, e verifica lo stato:
root@desopve01 pvesh set /cluster/sdnOutput UPID:desopve01:00027B63:0023AE2B:6AF22680:reloadnetworkall::root@pam:root@desopve01 ip -d link show vmbr1.30 | grep -v link/etherOutput 73: vmbr1.30@vmbr1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master vnv30 state UP mode DEFAULT group default qlen 1000vlan protocol 802.1Q id 30 <REORDER_HDR>
3. Guest su nodi diversi nella VLAN 30
Sezione intitolata “3. Guest su nodi diversi nella VLAN 30”-
Un container su
desopve01e uno sudesopve03, con indirizzo statico. La VNet non ha subnet: è una rete di livello 2, e un eventuale gateway è un router sulla VLAN, comerouter01del lab 26.root@desopve01 pct create 281 cephfs:vztmpl/debian-13-standard_13.6-1_amd64.tar.zst --hostname vlan30-ct1 \--unprivileged 1 --features nesting=1 --cores 1 --memory 512 --rootfs rbd-vm:4 \--net0 name=eth0,bridge=vnv30,ip=10.30.30.11/24 --passwordpct start 281root@desopve03 pct create 282 cephfs:vztmpl/debian-13-standard_13.6-1_amd64.tar.zst --hostname vlan30-ct2 \--unprivileged 1 --features nesting=1 --cores 1 --memory 512 --rootfs rbd-vm:4 \--net0 name=eth0,bridge=vnv30,ip=10.30.30.12/24 --passwordpct start 282 -
I due container si vedono, e sul bond il traffico ha il tag 30. La cattura va avviata prima del ping, in un secondo terminale; in questo e nei lab successivi il
tcpdumpcompare dopo il comando che genera il traffico solo per leggere l’output nell’ordine giusto:root@desopve01 tcpdump -lnei bond0 -c2 "vlan 30 and icmp" # secondo terminale, prima del pingpct exec 281 -- ping -c3 -W1 10.30.30.12Output 3 packets transmitted, 3 received, 0% packet loss, time 2016msOutput 16:26:01.301288 bc:24:11:53:8e:d8 > bc:24:11:ed:d7:ff, ethertype 802.1Q (0x8100), length 102: vlan 30, p 0, ethertype IPv4 (0x0800), 10.30.30.11 > 10.30.30.12: ICMP echo request, id 326, seq 1, length 6416:26:01.301592 bc:24:11:ed:d7:ff > bc:24:11:53:8e:d8, ethertype 802.1Q (0x8100), length 102: vlan 30, p 0, ethertype IPv4 (0x0800), 10.30.30.12 > 10.30.30.11: ICMP echo reply, id 326, seq 1, length 64Finita la prova i due container si spengono: restano pronti per la migrazione del Lab 48.
root@desopve01 pct shutdown 281root@desopve03 pct shutdown 282
4. Zona QinQ con service VLAN 802.1q
Sezione intitolata “4. Zona QinQ con service VLAN 802.1q”-
Zones → Add → QinQ. ID
qinqz, Bridgevmbr1, Service VLAN300, Service VLAN Protocol802.1q:
-
La VNet (VLAN cliente 10) e l’Apply, da riga di comando:
root@desopve01 pvesh create /cluster/sdn/vnets --vnet vnq10 --zone qinqz --tag 10pvesh set /cluster/sdn -
Cosa genera l’SDN su ogni nodo: un bridge VLAN-aware per la zona (
z_qinqz), collegato avmbr1.300(la service VLAN), e dentro di esso la VLAN clientez_qinqz.10, porta della VNet:# estratto di /etc/network/interfaces.d/sdn su desopve01auto vmbr1.300iface vmbr1.300vlan-protocol 802.1qauto z_qinqziface z_qinqzbridge-stp offbridge-ports vmbr1.300 ln_qinqzbridge-fd 0bridge-vlan-aware yesbridge-vids 2-4094auto vnq10iface vnq10bridge_ports z_qinqz.10bridge_stp offbridge_fd 0root@desopve01 ip -d link show | grep -A2 -E "vmbr1.300|z_qinqz|qinqz" | grep -E "^[0-9]+:|vlan protocol" | head -10Output 76: vmbr1.300@vmbr1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master z_qinqz state UP mode DEFAULT group default qlen 1000vlan protocol 802.1Q id 300 <REORDER_HDR>77: ln_qinqz@pr_qinqz: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master z_qinqz state UP mode DEFAULT group default qlen 100078: pr_qinqz@ln_qinqz: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 100079: z_qinqz: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 100080: z_qinqz.10@z_qinqz: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master vnq10 state UP mode DEFAULT group default qlen 1000vlan protocol 802.1Q id 10 <REORDER_HDR>La coppia
vethln_qinqz/pr_qinqzcollega il bridge della zona: è un dettaglio interno dell’implementazione. -
Due container (CT 283 su
desopve01, CT 284 sudesopve03, indirizzi 10.31.10.11 e .12) suvnq10, creati come quelli della VLAN 30:root@desopve01 pct create 283 cephfs:vztmpl/debian-13-standard_13.6-1_amd64.tar.zst --hostname qinq-ct1 \--unprivileged 1 --features nesting=1 --cores 1 --memory 512 --rootfs rbd-vm:4 \--net0 name=eth0,bridge=vnq10,ip=10.31.10.11/24 --passwordpct start 283root@desopve03 pct create 284 cephfs:vztmpl/debian-13-standard_13.6-1_amd64.tar.zst --hostname qinq-ct2 \--unprivileged 1 --features nesting=1 --cores 1 --memory 512 --rootfs rbd-vm:4 \--net0 name=eth0,bridge=vnq10,ip=10.31.10.12/24 --passwordpct start 284Il ping passa e sul bond i frame hanno due tag, 300 fuori e 10 dentro:
root@desopve01 pct exec 283 -- ping -c3 -W1 10.31.10.12Output 3 packets transmitted, 3 received, 0% packet loss, time 2002msroot@desopve01 tcpdump -lnei bond0 -c2 "vlan 300 and vlan 10 and icmp"Output 21:04:57.411769 bc:24:11:af:71:cf > bc:24:11:7c:50:ed, ethertype 802.1Q (0x8100), length 106: vlan 300, p 0, ethertype 802.1Q (0x8100), vlan 10, p 0, ethertype IPv4 (0x0800), 10.31.10.11 > 10.31.10.12: ICMP echo request, id 342, seq 2, length 6421:04:57.413112 bc:24:11:7c:50:ed > bc:24:11:af:71:cf, ethertype 802.1Q (0x8100), length 106: vlan 300, p 0, ethertype 802.1Q (0x8100), vlan 10, p 0, ethertype IPv4 (0x0800), 10.31.10.12 > 10.31.10.11: ICMP echo reply, id 342, seq 2, length 64 -
MTU. La scheda del container ha MTU 1500: l’SDN non l’ha ridotta da solo. Con il bit don’t fragment si prova un pacchetto IP di 1500 e uno di 1496 byte:
root@desopve01 pct exec 283 -- ip link show eth0 | grep -o "mtu [0-9]*"Output mtu 1500root@desopve01 pct exec 283 -- ping -c3 -W1 -M do -s 1472 10.31.10.12Output 3 packets transmitted, 3 received, 0% packet loss, time 2081msroot@desopve01 pct exec 283 -- ping -c3 -W1 -M do -s 1468 10.31.10.12Output 3 packets transmitted, 3 received, 0% packet loss, time 2060msNel laboratorio passano entrambi: la rete tra i nodi accetta frame ben più grandi (nel Lab 21 pacchetti fino a 8938 byte). Su uno switch che scarta i frame oltre i 1518 byte il primo andrebbe perso senza alcun errore visibile, il caso peggiore da diagnosticare. Prima di usare il QinQ in produzione si verifica l’MTU di tutto il percorso (lab 34), oppure si imposta l’MTU della zona a 1496.
5. Service VLAN 802.1ad
Sezione intitolata “5. Service VLAN 802.1ad”-
Una seconda zona QinQ con service VLAN 301 e protocollo
802.1ad, con la sua VNet. Prima di applicare, il Dry-Run mostra che suvmbr1si aggiunge solo la sottointerfaccia della service VLAN (vmbr1.301convlan-protocol 802.1ad): il bridgevmbr1e le sue VLAN 802.1Q non vengono toccati.root@desopve01 pvesh create /cluster/sdn/zones --type qinq --zone qinqad --bridge vmbr1 --tag 301 --vlan-protocol 802.1adpvesh create /cluster/sdn/vnets --vnet vnqad10 --zone qinqad --tag 10
-
Dopo l’Apply il bridge resta 802.1Q (
0x8100) e la service VLAN è 802.1ad:root@desopve01 pvesh set /cluster/sdncat /sys/class/net/vmbr1/bridge/vlan_protocolOutput 0x8100root@desopve01 ip -d link show vmbr1.301 | grep -o "vlan protocol [^ ]* id [0-9]*"Output vlan protocol 802.1ad id 301 -
I due container passano sulla VNet
vnqad10(stesso MAC e indirizzo) e il tag esterno ora ha ethertype0x88a8:root@desopve01 pct set 283 --net0 name=eth0,bridge=vnqad10,hwaddr=BC:24:11:AF:71:CF,ip=10.31.10.11/24root@desopve03 pct set 284 --net0 name=eth0,bridge=vnqad10,hwaddr=BC:24:11:7C:50:ED,ip=10.31.10.12/24root@desopve01 pct exec 283 -- ping -c3 -W1 10.31.10.12Output 3 packets transmitted, 3 received, 0% packet loss, time 2061msroot@desopve01 tcpdump -lnei bond0 -c2 "ether proto 0x88a8"Output 21:06:55.911301 bc:24:11:af:71:cf > bc:24:11:7c:50:ed, ethertype 802.1Q-QinQ (0x88a8), length 106: vlan 301, p 0, ethertype 802.1Q (0x8100), vlan 10, p 0, ethertype IPv4 (0x0800), 10.31.10.11 > 10.31.10.12: ICMP echo request, id 346, seq 1, length 6421:06:56.948753 bc:24:11:af:71:cf > bc:24:11:7c:50:ed, ethertype 802.1Q-QinQ (0x88a8), length 106: vlan 301, p 0, ethertype 802.1Q (0x8100), vlan 10, p 0, ethertype IPv4 (0x0800), 10.31.10.11 > 10.31.10.12: ICMP echo request, id 346, seq 2, length 64 -
Il resto della rete non ha risentito della nuova zona: VLAN 10 dei container, rete di migrazione e Ceph funzionano.
root@desopve01 pct exec 121 -- ping -c2 -W1 10.10.10.122Output 2 packets transmitted, 2 received, 0% packet loss, time 1002msroot@desopve01 ping -c2 -W1 10.100.10.22Output 2 packets transmitted, 2 received, 0% packet loss, time 1058msroot@desopve01 ceph healthOutput HEALTH_OK
6. Il quadro delle VNet e la pulizia
Sezione intitolata “6. Il quadro delle VNet e la pulizia”-
Le VNet create in questo lab e nel precedente:

-
Le zone QinQ servivano solo come prova: si eliminano i container, le VNet e le zone, poi si applica. Le zone si eliminano solo dopo le loro VNet.
root@desopve01 pct stop 283 && pct destroy 283 --purgeroot@desopve03 pct stop 284 && pct destroy 284 --purgeroot@desopve01 for v in vnqad10 vnq10; do pvesh delete /cluster/sdn/vnets/$v; donefor z in qinqad qinqz; do pvesh delete /cluster/sdn/zones/$z; donepvesh set /cluster/sdnip link show vmbr1.300Output Device "vmbr1.300" does not exist.
Verifica e test
Sezione intitolata “Verifica e test”| Prova | Risultato |
|---|---|
VNet VLAN 30 tra desopve01 e desopve03 |
0% di perdita, un tag 802.1Q 30 sul bond |
| Dry-Run | mostra il nuovo bridge e la sostituzione di frr.conf |
| QinQ 802.1q, service VLAN 300 | 0% di perdita, due tag 802.1Q (300 e 10) |
| QinQ, pacchetto IP di 1500 byte (frame di 1522) | passa nel laboratorio; su uno switch che non accetta il doppio tag andrebbe perso |
| QinQ 802.1ad, service VLAN 301 | 0% di perdita, tag esterno 0x88a8 |
| VLAN dei guest, migrazione e Ceph dopo le zone QinQ | invariati |
Stato finale del lab
Sezione intitolata “Stato finale del lab”- SDN:
- zona
simple1con VNetvnsimp1(lab 27), invariata; - zona
vlanz(VLAN suvmbr1) con VNetvnv30, tag 30, senza subnet; - zone QinQ
qinqzeqinqadeliminate.
- zona
- Container nella VLAN 30, spenti, senza avvio automatico, disco su
rbd-vm:- CT 281
vlan30-ct1sudesopve01, 10.30.30.11/24; - CT 282
vlan30-ct2sudesopve03, 10.30.30.12/24.
- CT 281
- CT 283 e 284 eliminati.
vmbr1resta VLAN-aware 802.1Q;/etc/frr/frr.confè ancora quello del pacchetto: l’SDN lo scrive con il controller EVPN e la fabric dei lab 30-31.
Cosa hai imparato
Sezione intitolata “Cosa hai imparato”- Con una zona VLAN il tag lo decide la VNet: i guest scelgono una rete per nome, il bridge esistente porta il traffico.
- Dry-Run mostra per ogni nodo le modifiche ai file di rete e a FRR prima di applicarle.
- Il QinQ incapsula le VLAN dei clienti in una service VLAN per zona; la service VLAN può essere 802.1Q o 802.1ad.
- Il doppio tag allunga il frame di 8 byte: con MTU 1500 sulla rete fisica le VNet QinQ vanno a 1496, oppure si alza l’MTU del percorso.
- Le zone si eliminano dopo le loro VNet, e anche la rimozione diventa effettiva solo con Apply.