- reading notes of SONiC host VLAN related topics
vlan basics
- vlan: virtual LAN
- a native bridge/switch is one broadcast domain, VLAN is used to separate one broadcast domain into multiple broadcast domains.
VID
: a bridge/switch port can have one or moreVID
s assigned to it. aVID
(VLAN ID) is an integer with default value as 1.- only packets that has tag number equal to one of the VIDs of the port is allowed to pass(both ingress/egress)
- a port can have multiple
VID
s: a trunk port
PVID
:PVID
(Port VLAN ID)- ingress packets(untagged) will be tagged with
PVID
- egress packets with VLAN tag same as
PVID
of the port will be untagged
- ingress packets(untagged) will be tagged with
- trunk port: have multiple
VID
s, allows traffic from various VLANs traveling across switches.
SONiC host vlan
- a typical VLAN setup in T0 topology
root@vlab-06:~# show vlan config
Name VID Member Mode
-------- ----- ---------- --------
Vlan1000 1000 Ethernet4 untagged
Vlan1000 1000 Ethernet8 untagged
Vlan1000 1000 Ethernet12 untagged
Vlan1000 1000 Ethernet16 untagged
Vlan1000 1000 Ethernet20 untagged
Vlan1000 1000 Ethernet24 untagged
Vlan1000 1000 Ethernet28 untagged
Vlan1000 1000 Ethernet32 untagged
Vlan1000 1000 Ethernet36 untagged
Vlan1000 1000 Ethernet40 untagged
Vlan1000 1000 Ethernet44 untagged
Vlan1000 1000 Ethernet48 untagged
Vlan1000 1000 Ethernet52 untagged
Vlan1000 1000 Ethernet56 untagged
Vlan1000 1000 Ethernet60 untagged
Vlan1000 1000 Ethernet64 untagged
Vlan1000 1000 Ethernet68 untagged
Vlan1000 1000 Ethernet72 untagged
Vlan1000 1000 Ethernet76 untagged
Vlan1000 1000 Ethernet80 untagged
Vlan1000 1000 Ethernet84 untagged
Vlan1000 1000 Ethernet88 untagged
Vlan1000 1000 Ethernet92 untagged
Vlan1000 1000 Ethernet96 untagged
- the host VLAN setup
- the host VLAN is configured with Linux command
bridge
by thevlanmgr
: https://github.com/Azure/sonic-swss/blob/master/cfgmgr/vlanmgr.h
- the host VLAN is configured with Linux command
root@vlab-06:~# bridge vlan show
port vlan ids
docker0 1 PVID Egress Untagged
Ethernet24 1000 PVID Egress Untagged
Ethernet28 1000 PVID Egress Untagged
Ethernet36 1000 PVID Egress Untagged
Ethernet32 1000 PVID Egress Untagged
Ethernet40 1000 PVID Egress Untagged
Ethernet44 1000 PVID Egress Untagged
Ethernet4 1000 PVID Egress Untagged
Ethernet8 1000 PVID Egress Untagged
Ethernet12 1000 PVID Egress Untagged
Ethernet20 1000 PVID Egress Untagged
Ethernet16 1000 PVID Egress Untagged
Ethernet52 1000 PVID Egress Untagged
Ethernet48 1000 PVID Egress Untagged
Ethernet56 1000 PVID Egress Untagged
Ethernet60 1000 PVID Egress Untagged
Ethernet68 1000 PVID Egress Untagged
Ethernet64 1000 PVID Egress Untagged
Ethernet72 1000 PVID Egress Untagged
Ethernet76 1000 PVID Egress Untagged
Ethernet84 1000 PVID Egress Untagged
Ethernet80 1000 PVID Egress Untagged
Ethernet88 1000 PVID Egress Untagged
Ethernet92 1000 PVID Egress Untagged
Ethernet96 1000 PVID Egress Untagged
Bridge 1000
dummy 1 PVID Egress Untagged
add vlan bridge
- VLAN bridge
BRIDGE
is configured in the constructor ofVlanMgr
VlanMgr::VlanMgr(DBConnector *cfgDb, DBConnector *appDb, DBConnector *stateDb, const vector<string> &tableNames) :
Orch(cfgDb, tableNames),
m_cfgVlanTable(cfgDb, CFG_VLAN_TABLE_NAME),
m_cfgVlanMemberTable(cfgDb, CFG_VLAN_MEMBER_TABLE_NAME),
m_statePortTable(stateDb, STATE_PORT_TABLE_NAME),
m_stateLagTable(stateDb, STATE_LAG_TABLE_NAME),
m_stateVlanTable(stateDb, STATE_VLAN_TABLE_NAME),
m_stateVlanMemberTable(stateDb, STATE_VLAN_MEMBER_TABLE_NAME),
m_appVlanTableProducer(appDb, APP_VLAN_TABLE_NAME),
m_appVlanMemberTableProducer(appDb, APP_VLAN_MEMBER_TABLE_NAME),
replayDone(false)
{
...
const std::string cmds = std::string("")
+ BASH_CMD + " -c \""
+ IP_CMD + " link del " + DOT1Q_BRIDGE_NAME + " 2>/dev/null; "
+ IP_CMD + " link add " + DOT1Q_BRIDGE_NAME + " up type bridge && "
+ IP_CMD + " link set " + DOT1Q_BRIDGE_NAME + " mtu " + DEFAULT_MTU_STR + " && "
+ IP_CMD + " link set " + DOT1Q_BRIDGE_NAME + " address " + gMacAddress.to_string() + " && "
+ BRIDGE_CMD + " vlan del vid " + DEFAULT_VLAN_ID + " dev " + DOT1Q_BRIDGE_NAME + " self; "
+ IP_CMD + " link del dev dummy 2>/dev/null; "
+ IP_CMD + " link add dummy type dummy && "
+ IP_CMD + " link set dummy master " + DOT1Q_BRIDGE_NAME + "\"";
std::string res;
EXEC_WITH_ERROR_THROW(cmds, res);
// The generated command is:
// /bin/echo 1 > /sys/class/net/Bridge/bridge/vlan_filtering
const std::string echo_cmd = std::string("")
+ ECHO_CMD + " 1 > /sys/class/net/" + DOT1Q_BRIDGE_NAME + "/bridge/vlan_filtering";
int ret = swss::exec(echo_cmd, res);
/* echo will fail in virtual switch since /sys directory is read-only.
* need to use ip command to setup the vlan_filtering which is not available in debian 8.
* Once we move sonic to debian 9, we can use IP command by default
* ip command available in Debian 9 to create a bridge with a vlan filtering:
* /sbin/ip link add Bridge up type bridge vlan_filtering 1 */
if (ret != 0)
{
const std::string echo_cmd_backup = std::string("")
+ IP_CMD + " link set " + DOT1Q_BRIDGE_NAME + " type bridge vlan_filtering 1";
EXEC_WITH_ERROR_THROW(echo_cmd_backup, res);
}
}
- the
bridge
setting has two modes:self
: link setting is configured on specified physical devicemaster
: link setting is configured on the bridge(enslaved master)
- the bridge
BRIDGE
hasvlan_filtering == 1
- when disabled, the bridge will not consider the VLAN tag when handling packets
- a dummy interface is created and enslaved to bridge
BRIDGE
- FIXME: why create a dummy here?
add host vlan interface
bool VlanMgr::addHostVlan(int vlan_id)
{
SWSS_LOG_ENTER();
// The command should be generated as:
// /bin/bash -c "/sbin/bridge vlan add vid dev Bridge self &&
// /sbin/ip link add link Bridge up name Vlan address type vlan id "
const std::string cmds = std::string("")
+ BASH_CMD + " -c \""
+ BRIDGE_CMD + " vlan add vid " + std::to_string(vlan_id) + " dev " + DOT1Q_BRIDGE_NAME + " self && "
+ IP_CMD + " link add link " + DOT1Q_BRIDGE_NAME
+ " up"
+ " name " + VLAN_PREFIX + std::to_string(vlan_id)
+ " address " + gMacAddress.to_string()
+ " type vlan id " + std::to_string(vlan_id) + "\"";
std::string res;
EXEC_WITH_ERROR_THROW(cmds, res);
return true;
}
- Assume
vlan_id
is 1000 addHostVlan
- adds vlan 1000 to the bridge
Bridge
- create a vlan id 1000 sub interface called
Vlan1000
of bridgeBridge
- adds vlan 1000 to the bridge
add host vlan member
bool VlanMgr::addHostVlanMember(int vlan_id, const string &port_alias, const string& tagging_mode)
{
SWSS_LOG_ENTER();
std::string tagging_cmd;
if (tagging_mode == "untagged" || tagging_mode == "priority_tagged")
{
tagging_cmd = "pvid untagged";
}
// The command should be generated as:
// /bin/bash -c "/sbin/ip link set master Bridge &&
// /sbin/bridge vlan del vid 1 dev &&
// /sbin/bridge vlan add vid dev "
ostringstream cmds, inner;
inner << IP_CMD " link set " << shellquote(port_alias) << " master " DOT1Q_BRIDGE_NAME " && "
BRIDGE_CMD " vlan del vid " DEFAULT_VLAN_ID " dev " << shellquote(port_alias) << " && "
BRIDGE_CMD " vlan add vid " + std::to_string(vlan_id) + " dev " << shellquote(port_alias) << " " + tagging_cmd;
cmds << BASH_CMD " -c " << shellquote(inner.str());
std::string res;
EXEC_WITH_ERROR_THROW(cmds.str(), res);
return true;
}
addhostVlanMember
- add the port to the bridge
Bridge
- remove the default vid 1
- add the vid 1000 to the port
- add the port to the bridge
bridge vlan add
pvid
: the vlan specified is to be considered aPVID
at ingress, any untagged frames will be assigned to this vlanuntagged
: the vlan specified is to be considered as untagged on egress
some trials with command bridge
root@lolv-vm-02:~# ip netns add vlan_ns
root@lolv-vm-02:~# ip netns exec vlan_ns /bin/bash
root@lolv-vm-02:~# ip link add vlan_bridge up type bridge
root@lolv-vm-02:~# bridge vlan
port vlan ids
vlan_bridge 1 PVID Egress Untagged
root@lolv-vm-02:~# ip link add ext_intf1 type veth peer name int_intf1
root@lolv-vm-02:~# ip link add ext_intf0 type veth peer name int_intf0
root@lolv-vm-02:~# ip link add ext_intf2 type veth peer name int_intf2
root@lolv-vm-02:~# bridge vlan add vid 1000 dev vlan_bridge self
root@lolv-vm-02:~# bridge vlan
port vlan ids
vlan_bridge 1 PVID Egress Untagged
1000
root@lolv-vm-02:~# bridge vlan del vid 1 dev vlan_bridge self
root@lolv-vm-02:~# bridge vlan
port vlan ids
vlan_bridge 1000
root@lolv-vm-02:~# ip link set int_intf0 master vlan_bridge
root@lolv-vm-02:~# bridge vlan add vid 1000 dev int_intf0
root@lolv-vm-02:~# ip link set int_intf1 master vlan_bridge
root@lolv-vm-02:~# bridge vlan add vid 1000 dev int_intf1 pvid
root@lolv-vm-02:~# ip link set int_intf2 master vlan_bridge
root@lolv-vm-02:~# bridge vlan add vid 1000 dev int_intf2 pvid untagged
root@lolv-vm-02:~# bridge vlan
port vlan ids
vlan_bridge 1000
int_intf0 1 PVID Egress Untagged
1000
int_intf1 1 Egress Untagged
1000 PVID
int_intf2 1 Egress Untagged
1000 PVID Egress Untagged
root@lolv-vm-02:~# brctl show
bridge name bridge id STP enabled interfaces
vlan_bridge 8000.36b3066690b0 no int_intf0
int_intf1
int_intf2
- the
bridge
command is used for VLAN filtering - any ether device added by
bridge vlan add
has a default vid as 1 with bothPVID
anduntagged
- from the example above, when bridge
vlan_bridge
is created, it has a default vid as 1 withPVID
anduntagged
- this means, without assign user vid to the bridge
vlan_bridge
, any packets enters the bridge will be tagged with the default vid 1, any packets leaving the bridge will have the vlan tag(1) stripped, and this process is transparent to the user as there is no vlan configured on the bridge.
- from the example above, when bridge
- NOTE:
PVID
is used to ingress packets, if a port hasPVID
on for avid
, it means any untagged packet entering the port will be passed to the VLAN specified byvid
.untagged
is used to egress packets, when a packet is leaving a VLAN through a port, if the port hasuntagged
on, the vlan tag of the packet will be stripped.- a port can have multiple
vid
s withuntagged
, but can only have onevid
asPVID
references
- https://github.com/Azure/sonic-mgmt/blob/master/docs/testplan/VLAN-trunk-test-plan.md
- https://documentation.meraki.com/General_Administration/Tools_and_Troubleshooting/Fundamentals_of_802.1Q_VLAN_Tagging#:~:text=VLAN%20enabled%20ports%20are%20generally,for%20only%20a%20single%20VLAN.
- http://forums.dlink.com/index.php?topic=41342.0
- https://man7.org/linux/man-pages/man8/bridge.8.html
- https://linux-blog.anracom.com/tag/vlan-aware-bridge/