Skip to content
24 changes: 11 additions & 13 deletions orchagent/fdborch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ bool FdbOrch::storeFdbEntryState(const FdbUpdate& update)

if (!m_portsOrch->getPort(entry.bv_id, vlan))
{
SWSS_LOG_NOTICE("FdbOrch notification: Failed to locate \
vlan port from bv_id 0x%" PRIx64, entry.bv_id);
SWSS_LOG_NOTICE("FdbOrch notification: Failed to locate "
"vlan port from bv_id 0x%" PRIx64, entry.bv_id);
return false;
}

Expand Down Expand Up @@ -163,8 +163,8 @@ void FdbOrch::update(sai_fdb_event_t type,
update.type = "dynamic";
Port vlan;

SWSS_LOG_INFO("FDB event:%d, MAC: %s , BVID: 0x%" PRIx64 " , \
bridge port ID: 0x%" PRIx64 ".",
SWSS_LOG_INFO("FDB event:%d, MAC: %s , BVID: 0x%" PRIx64 " , "
"bridge port ID: 0x%" PRIx64 ".",
type, update.entry.mac.to_string().c_str(),
entry->bv_id, bridge_port_id);

Expand Down Expand Up @@ -362,8 +362,8 @@ void FdbOrch::update(sai_fdb_event_t type,
}
case SAI_FDB_EVENT_FLUSHED:

SWSS_LOG_INFO("FDB Flush event received: [ %s , 0x%" PRIx64 " ], \
bridge port ID: 0x%" PRIx64 ".",
SWSS_LOG_INFO("FDB Flush event received: [ %s , 0x%" PRIx64 " ], "
"bridge port ID: 0x%" PRIx64 ".",
update.entry.mac.to_string().c_str(), entry->bv_id,
bridge_port_id);

Expand All @@ -373,8 +373,8 @@ void FdbOrch::update(sai_fdb_event_t type,

if (!m_portsOrch->getPort(entry->bv_id, vlan))
{
SWSS_LOG_NOTICE("FdbOrch notification: Failed to locate vlan\
port from bv_id 0x%" PRIx64, entry->bv_id);
SWSS_LOG_NOTICE("FdbOrch notification: Failed to locate vlan "
"port from bv_id 0x%" PRIx64, entry->bv_id);
return;
}
vlanName = "Vlan" + to_string(vlan.m_vlan_info.vlan_id);
Expand Down Expand Up @@ -439,7 +439,6 @@ void FdbOrch::update(sai_fdb_event_t type,
SWSS_LOG_ERROR("Unsupported FDB Flush: [ %s , %s ] = { port: - }",
update.entry.mac.to_string().c_str(),
vlanName.c_str());

}
else
{
Expand Down Expand Up @@ -647,6 +646,7 @@ void FdbOrch::doTask(Consumer& consumer)
port = tunnel_orch->getTunnelPortName(remote_ip);
}

entry.port_name = port;

FdbData fdbData;
fdbData.bridge_port_id = SAI_NULL_OBJECT_ID;
Expand All @@ -666,7 +666,6 @@ void FdbOrch::doTask(Consumer& consumer)
it = consumer.m_toSync.erase(it);
else
it++;

}
else
{
Expand Down Expand Up @@ -881,8 +880,8 @@ void FdbOrch::notifyObserversFDBFlush(Port &port, sai_object_id_t& bvid)
if ((itr->first.port_name == port.m_alias) &&
(itr->first.bv_id == bvid))
{
SWSS_LOG_INFO("Adding MAC learnt on [ port:%s , bvid:0x%" PRIx64 "]\
to ARP flush", port.m_alias.c_str(), bvid);
SWSS_LOG_INFO("Adding MAC learnt on [ port:%s , bvid:0x%" PRIx64 "] "
"to ARP flush", port.m_alias.c_str(), bvid);
FdbEntry entry;
entry.mac = itr->first.mac;
entry.bv_id = itr->first.bv_id;
Expand Down Expand Up @@ -920,7 +919,6 @@ void FdbOrch::updatePortOperState(const PortOperStateUpdate& update)
}
notifyObserversFDBFlush(p, vlan.m_vlan_info.vlan_oid);
}

}
return;
}
Expand Down
1 change: 1 addition & 0 deletions orchagent/mirrororch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,7 @@ bool MirrorOrch::getNeighborInfo(const string& name, MirrorEntry& session)
!m_neighOrch->getNeighborEntry(session.nexthopInfo.nexthop,
session.neighborInfo.neighbor, session.neighborInfo.mac)))
{
session.neighborInfo.mac = MacAddress();
return false;
}

Expand Down
74 changes: 70 additions & 4 deletions tests/test_mirror.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ def setup_db(self, dvs):
self.cdb = swsscommon.DBConnector(4, dvs.redis_sock, 0)
self.sdb = swsscommon.DBConnector(6, dvs.redis_sock, 0)

def set_port_oper_status(self, dvs, port_name, status):
if port_name.startswith("Ethernet"):
srv_idx = int(port_name[len("Ethernet"):]) // 4
dvs.servers[srv_idx].runcmd("ip link set dev eth0 " + status)
elif port_name.startswith("PortChannel"):
dvs.runcmd("bash -c 'echo " + ("1" if status == "up" else "0") + \
" > /sys/class/net/" + port_name + "/carrier'")
time.sleep(1)

def set_interface_status(self, dvs, interface, admin_status):
if interface.startswith("PortChannel"):
tbl_name = "PORTCHANNEL"
Expand All @@ -26,11 +35,13 @@ def set_interface_status(self, dvs, interface, admin_status):
tbl.set(interface, fvs)
time.sleep(1)

# when using FRR, route cannot be inserted if the neighbor is not
# connected. thus it is mandatory to force the interface up manually
if interface.startswith("PortChannel"):
dvs.runcmd("bash -c 'echo " + ("1" if admin_status == "up" else "0") +\
" > /sys/class/net/" + interface + "/carrier'")
# when using FRR, route cannot be inserted if the neighbor is not
# connected. thus it is mandatory to force the interface up manually
self.set_port_oper_status(dvs, interface, admin_status)
elif interface.startswith("Ethernet"):
self.set_port_oper_status(dvs, interface, "down")
self.set_port_oper_status(dvs, interface, "up")

def add_ip_address(self, interface, ip):
if interface.startswith("PortChannel"):
Expand Down Expand Up @@ -239,6 +250,11 @@ def remove_fdb(self, vlan, mac):
tbl._del("Vlan" + vlan + ":" + mac)
time.sleep(1)

def flush_fdb(self, op, data):
ntf = swsscommon.NotificationProducer(self.adb, "FLUSHFDBREQUEST")
fvs = swsscommon.FieldValuePairs()
ntf.send(op, data, fvs)
time.sleep(1)

# Ignore testcase in Debian Jessie
# TODO: Remove this skip if Jessie support is no longer needed
Expand Down Expand Up @@ -328,6 +344,56 @@ def test_MirrorToVlanAddRemove(self, dvs, testlog):
else:
assert False

# test port oper status down that triggers fdb flush on port, which further triggers neighbor flush
self.set_port_oper_status(dvs, "Ethernet4", "down")
assert self.get_mirror_session_state(session)["status"] == "inactive"
tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION")
assert len(tbl.getKeys()) == 0
# Allow time for neighor flush to occur
time.sleep(1)

# restore port oper status up
self.set_port_oper_status(dvs, "Ethernet4", "up")

# restore fdb entry to ethernet 4
self.create_fdb("6", "66-66-66-66-66-66", "Ethernet4")
assert self.get_mirror_session_state(session)["status"] == "inactive"
tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION")
assert len(tbl.getKeys()) == 0

# restore neighbor to vlan 6
self.add_neighbor("Vlan6", "6.6.6.6", "66:66:66:66:66:66")
assert self.get_mirror_session_state(session)["status"] == "active"
tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION")
assert len(tbl.getKeys()) == 1

# test fdb flush all from appl db
self.flush_fdb("ALL", "ALL")
assert self.get_mirror_session_state(session)["status"] == "inactive"
tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION")
assert len(tbl.getKeys()) == 0

# restore fdb entry to ethernet 4
self.create_fdb("6", "66-66-66-66-66-66", "Ethernet4")
assert self.get_mirror_session_state(session)["status"] == "active"
tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION")
assert len(tbl.getKeys()) == 1

# test fdb flush port from appl db
self.flush_fdb("PORT", "Ethernet4")
assert self.get_mirror_session_state(session)["status"] == "inactive"
tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION")
assert len(tbl.getKeys()) == 0

# restore fdb entry to ethernet 4
self.create_fdb("6", "66-66-66-66-66-66", "Ethernet4")
assert self.get_mirror_session_state(session)["status"] == "active"
tbl = swsscommon.Table(self.adb, "ASIC_STATE:SAI_OBJECT_TYPE_MIRROR_SESSION")
assert len(tbl.getKeys()) == 1

# test fdb flush vlan from appl db, the corresponding flush event from asic db not yet handled
# test fdb flush {vlan, port} from appl db, the corresponding flush event from asic db not yet handled

# remove fdb entry
self.remove_fdb("6", "66-66-66-66-66-66")
assert self.get_mirror_session_state(session)["status"] == "inactive"
Expand Down