From 7fc0f738408e8bf896d494f940670e795349e7ec Mon Sep 17 00:00:00 2001 From: Lior Avramov <73036155+liorghub@users.noreply.github.com> Date: Wed, 25 May 2022 11:17:50 +0300 Subject: [PATCH] Update netlink messages handler (#2233) - What I did Ignore netlink DELLINK messages if port has master, this is applicable to the case where port was part of VLAN bridge or LAG. - Why I did it Netlink messages handler in portsyncd was ignoring all messages that had master. Therefore we ignored messages on interfaces that belong to LAG (not only interfaces belong to bridge as intended). The result was "netdev_oper_status" down in PORT_TABLE in state DB for port which is part of LAG although it is actually up. - How I verified it Check "netdev_oper_status" in PORT_TABLE in state DB for port which is part of LAG. --- portsyncd/linksync.cpp | 7 +++-- tests/test_portchannel.py | 57 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 4 deletions(-) diff --git a/portsyncd/linksync.cpp b/portsyncd/linksync.cpp index d3beeee632..fc28411613 100644 --- a/portsyncd/linksync.cpp +++ b/portsyncd/linksync.cpp @@ -205,10 +205,9 @@ void LinkSync::onMsg(int nlmsg_type, struct nl_object *obj) return; } - /* If netlink for this port has master, we ignore that for now - * This could be the case where the port was removed from VLAN bridge - */ - if (master) + /* Ignore DELLINK message if port has master, this is applicable to + * the case where port was part of VLAN bridge or LAG */ + if (master && nlmsg_type == RTM_DELLINK) { return; } diff --git a/tests/test_portchannel.py b/tests/test_portchannel.py index ee612ec46d..3e24b6a340 100644 --- a/tests/test_portchannel.py +++ b/tests/test_portchannel.py @@ -382,6 +382,63 @@ def test_Portchannel_tpid(self, dvs, testlog): tbl._del("PortChannel0002") time.sleep(1) + def test_portchannel_member_netdev_oper_status(self, dvs, testlog): + config_db = swsscommon.DBConnector(swsscommon.CONFIG_DB, dvs.redis_sock, 0) + state_db = swsscommon.DBConnector(swsscommon.STATE_DB, dvs.redis_sock, 0) + app_db = swsscommon.DBConnector(swsscommon.APPL_DB, dvs.redis_sock, 0) + + # create port-channel + tbl = swsscommon.Table(config_db, "PORTCHANNEL") + fvs = swsscommon.FieldValuePairs([("admin_status", "up"),("mtu", "9100"),("oper_status", "up")]) + tbl.set("PortChannel111", fvs) + + # set port-channel oper status + tbl = swsscommon.ProducerStateTable(app_db, "LAG_TABLE") + fvs = swsscommon.FieldValuePairs([("admin_status", "up"),("mtu", "9100"),("oper_status", "up")]) + tbl.set("PortChannel111", fvs) + + # add members to port-channel + tbl = swsscommon.Table(config_db, "PORTCHANNEL_MEMBER") + fvs = swsscommon.FieldValuePairs([("NULL", "NULL")]) + tbl.set("PortChannel111|Ethernet0", fvs) + tbl.set("PortChannel111|Ethernet4", fvs) + + # wait for port-channel netdev creation + time.sleep(1) + + # set netdev oper status + (exitcode, _) = dvs.runcmd("ip link set up dev Ethernet0") + assert exitcode == 0, "ip link set failed" + + (exitcode, _) = dvs.runcmd("ip link set up dev Ethernet4") + assert exitcode == 0, "ip link set failed" + + (exitcode, _) = dvs.runcmd("ip link set dev PortChannel111 carrier on") + assert exitcode == 0, "ip link set failed" + + # verify port-channel members netdev oper status + tbl = swsscommon.Table(state_db, "PORT_TABLE") + status, fvs = tbl.get("Ethernet0") + assert status is True + fvs = dict(fvs) + assert fvs['netdev_oper_status'] == 'up' + + status, fvs = tbl.get("Ethernet4") + assert status is True + fvs = dict(fvs) + assert fvs['netdev_oper_status'] == 'up' + + # remove port-channel members + tbl = swsscommon.Table(config_db, "PORTCHANNEL_MEMBER") + tbl._del("PortChannel111|Ethernet0") + tbl._del("PortChannel111|Ethernet4") + + # remove port-channel + tbl = swsscommon.Table(config_db, "PORTCHANNEL") + tbl._del("PortChannel111") + + # wait for port-channel deletion + time.sleep(1) # Add Dummy always-pass test at end as workaroud # for issue when Flaky fail on final test it invokes module tear-down before retrying