diff --git a/orchagent/fdborch.cpp b/orchagent/fdborch.cpp index 9a54ba98f1..7a37acaa6d 100644 --- a/orchagent/fdborch.cpp +++ b/orchagent/fdborch.cpp @@ -159,7 +159,8 @@ void FdbOrch::update(sai_fdb_event_t type, const sai_fdb_entry_t* entry, sai_obj break; case SAI_FDB_EVENT_FLUSHED: - if (bridge_port_id == SAI_NULL_OBJECT_ID && entry->bv_id == SAI_NULL_OBJECT_ID) + if ((bridge_port_id == SAI_NULL_OBJECT_ID && entry->bv_id == SAI_NULL_OBJECT_ID) + || (bridge_port_id && entry->bv_id == SAI_NULL_OBJECT_ID)) { for (auto itr = m_entries.begin(); itr != m_entries.end();) { diff --git a/orchagent/portsorch.cpp b/orchagent/portsorch.cpp index 0cc91af725..12601d8573 100755 --- a/orchagent/portsorch.cpp +++ b/orchagent/portsorch.cpp @@ -35,6 +35,7 @@ extern sai_hostif_api_t* sai_hostif_api; extern sai_acl_api_t* sai_acl_api; extern sai_queue_api_t *sai_queue_api; extern sai_object_id_t gSwitchId; +extern sai_fdb_api_t *sai_fdb_api; extern IntfsOrch *gIntfsOrch; extern NeighOrch *gNeighOrch; extern CrmOrch *gCrmOrch; @@ -2566,6 +2567,13 @@ void PortsOrch::doLagTask(Consumer &consumer) if (fvValue(i) == "down") { gNeighOrch->ifChangeInformNextHop(alias, false); + Port lag; + if (getPort(alias, lag)) + { + SWSS_LOG_NOTICE("Flushing FDB entries for %s with bridge port id: %" PRIx64 + " as it is DOWN", alias.c_str(), lag.m_bridge_port_id); + flushFDBEntries(lag.m_bridge_port_id); + } } else { @@ -3799,6 +3807,13 @@ void PortsOrch::doTask(NotificationConsumer &consumer) updatePortOperStatus(port, status); + if (status == SAI_PORT_OPER_STATUS_DOWN) + { + SWSS_LOG_NOTICE("Flushing FDB entries for %s with bridge port id: %" PRIx64 + " as it is DOWN", port.m_alias.c_str(), port.m_bridge_port_id); + flushFDBEntries(port.m_bridge_port_id); + } + /* update m_portList */ m_portList[port.m_alias] = port; } @@ -3983,3 +3998,22 @@ void PortsOrch::getPortSerdesVal(const std::string& val_str, lane_values.push_back(lane_val); } } + +void PortsOrch::flushFDBEntries(sai_object_id_t bridge_port_id) +{ + sai_attribute_t attr; + vector attrs; + sai_status_t rv; + + SWSS_LOG_INFO("Flushing the port with bridge port id: %" PRIx64, bridge_port_id); + + attr.id = SAI_FDB_FLUSH_ATTR_BRIDGE_PORT_ID; + attr.value.oid = bridge_port_id; + attrs.push_back(attr); + rv = sai_fdb_api->flush_fdb_entries(gSwitchId, (uint32_t)attrs.size(), attrs.data()); + + if (rv != SAI_STATUS_SUCCESS) + { + SWSS_LOG_ERROR("Flush fdb by bridge port id: %" PRIx64 "failed: %d", bridge_port_id, rv); + } +} diff --git a/orchagent/portsorch.h b/orchagent/portsorch.h index 34d7dfd8bf..f5a16e0b01 100755 --- a/orchagent/portsorch.h +++ b/orchagent/portsorch.h @@ -234,6 +234,7 @@ class PortsOrch : public Orch, public Subject vector &serdes_val); bool getSaiAclBindPointType(Port::Type type, sai_acl_bind_point_type_t &sai_acl_bind_type); + void flushFDBEntries(sai_object_id_t bridge_port_id); }; #endif /* SWSS_PORTSORCH_H */ diff --git a/tests/test_fdb_update.py b/tests/test_fdb_update.py index 7d6fdc153c..7c16e91a6e 100644 --- a/tests/test_fdb_update.py +++ b/tests/test_fdb_update.py @@ -7,6 +7,7 @@ from swsscommon import swsscommon from distutils.version import StrictVersion +<<<<<<< HEAD class TestFdbUpdate(object): def create_entry(self, tbl, key, pairs): @@ -200,6 +201,7 @@ def test_FDBLearnedAndUpdated(self, dvs, testlog): dvs.servers[16].runcmd("ifconfig eth0 hw ether 00:00:00:00:00:11") dvs.servers[16].runcmd("ifconfig eth0 6.6.6.6/24 up") dvs.servers[16].runcmd("ip route add default via 6.6.6.1") + dvs.servers[17].runcmd("ifconfig eth0 hw ether 00:00:00:00:17:11") dvs.servers[17].runcmd("ifconfig eth0 6.6.6.7/24 up") dvs.servers[17].runcmd("ip route add default via 6.6.6.1") time.sleep(2) @@ -240,9 +242,10 @@ def test_FDBLearnedAndUpdated(self, dvs, testlog): # restore the default value of the servers dvs.servers[16].runcmd("ip route del default via 6.6.6.1") - dvs.servers[16].runcmd("ifconfig eth0 0") + dvs.servers[16].runcmd("ifconfig eth0 0 down") dvs.servers[17].runcmd("ip route del default via 6.6.6.1") - dvs.servers[17].runcmd("ifconfig eth0 0") + dvs.servers[17].runcmd("ifconfig eth0 0 down") + dvs.servers[18].runcmd("ifconfig eth0 0 down") # bring down port dvs.set_interface_status("Ethernet64", "down") @@ -250,7 +253,6 @@ def test_FDBLearnedAndUpdated(self, dvs, testlog): dvs.set_interface_status("Ethernet72", "down") # remove vlan ip - key = "Vlan6" + "|" + "6.6.6.1/24" self.remove_entry_tbl(dvs.cdb, "VLAN_INTERFACE", key) # bring down vlan @@ -264,3 +266,61 @@ def test_FDBLearnedAndUpdated(self, dvs, testlog): # clear fdb dvs.runcmd("sonic-clear fdb all") + + def test_FDBLearnedAndFlushed(dvs, testlog): + dvs.setup_db() + + dvs.runcmd("sonic-clear fdb all") + + VLAN = "9" + VLAN_NAME = "Vlan9" + PORT = "Ethernet80" + server = 20 + server_mac = "00:00:00:00:20:11" + + # create vlan; create vlan member + dvs.create_vlan(VLAN) + dvs.create_vlan_member(VLAN, PORT) + time.sleep(2) + + # Get mapping between interface name and its bridge port_id + iface_2_bridge_port_id = dvs.get_map_iface_bridge_port_id(dvs.adb) + + # bring up vlan and member + dvs.set_interface_status(VLAN_NAME, "up") + dvs.add_ip_address(VLAN_NAME, "7.7.7.1/24") + dvs.set_interface_status(PORT, "up") + + dvs.servers[server].runcmd("ifconfig eth0 hw ether {}".format(server_mac)) + dvs.servers[server].runcmd("ifconfig eth0 7.7.7.7/24 up") + + # get neighbor and arp entry + rc = dvs.servers[server].runcmd("ping -c 1 7.7.7.1") + assert rc == 0 + time.sleep(2) + + # check that the FDB entries were inserted into ASIC DB + mac = get_mac_by_bridge_id(dvs, iface_2_bridge_port_id[PORT]) + assert server_mac in mac + + # bring down port + dvs.servers[server].runcmd("ip link set down dev eth0") == 0 + #dvs.set_interface_status(PORT, "down") + time.sleep(2) + + # fdb should be flushed + mac = get_mac_by_bridge_id(dvs, iface_2_bridge_port_id[PORT]) + assert not mac + + # remove vlan ip + dvs.remove_ip_address(VLAN_NAME, "7.7.7.1/24") + + # bring down vlan + dvs.set_interface_status(VLAN_NAME, "down") + + # remove vlan member; remove vlan + dvs.remove_vlan_member(VLAN, PORT) + dvs.remove_vlan(VLAN) + + # restore the default value of the servers + dvs.servers[server].runcmd("ifconfig eth0 0 down")