Skip to content

Commit

Permalink
Flush fdb entries when port/LAG is operational down (sonic-net#14)
Browse files Browse the repository at this point in the history
* Flush fdb entries when port/LAG is operational down

Signed-off-by: Zhenggen Xu <zxu@linkedin.com>

* Added vs-test cases, fixed one bug and addressed review feedback

Signed-off-by: Zhenggen Xu <zxu@linkedin.com>
  • Loading branch information
zhenggen-xu authored and Vasant Patil committed Jun 6, 2020
1 parent 4cc1d1f commit 66cf33f
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 4 deletions.
3 changes: 2 additions & 1 deletion orchagent/fdborch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();)
{
Expand Down
34 changes: 34 additions & 0 deletions orchagent/portsorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
{
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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<sai_attribute_t> 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);
}
}
1 change: 1 addition & 0 deletions orchagent/portsorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ class PortsOrch : public Orch, public Subject
vector<uint32_t> &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 */

66 changes: 63 additions & 3 deletions tests/test_fdb_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from swsscommon import swsscommon
from distutils.version import StrictVersion

<<<<<<< HEAD

class TestFdbUpdate(object):
def create_entry(self, tbl, key, pairs):
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -240,17 +242,17 @@ 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")
dvs.set_interface_status("Ethernet68", "down")
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
Expand All @@ -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")

0 comments on commit 66cf33f

Please sign in to comment.