Skip to content

Commit

Permalink
Disable FDB aging before planned warm restart (sonic-net#634)
Browse files Browse the repository at this point in the history
  • Loading branch information
qiluo-msft authored Oct 1, 2018
1 parent de4a2da commit 94fbcd9
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 5 deletions.
5 changes: 5 additions & 0 deletions orchagent/orchdaemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -363,12 +363,17 @@ void OrchDaemon::start()
// Should sleep here or continue handling timers and etc.??
if (!gSwitchOrch->checkRestartNoFreeze())
{
// Disable FDB aging
gSwitchOrch->setAgingFDB(0);

// Disable FDB learning on all bridge ports
for (auto& pair: gPortsOrch->getAllPorts())
{
auto& port = pair.second;
gPortsOrch->setBridgePortLearningFDB(port, SAI_BRIDGE_PORT_FDB_LEARNING_MODE_DISABLE);
}

// Flush sairedis's redis pipeline
flush();

SWSS_LOG_WARN("Orchagent is frozen for warm restart!");
Expand Down
15 changes: 15 additions & 0 deletions orchagent/switchorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,3 +176,18 @@ void SwitchOrch::restartCheckReply(const string &op, const string &data, std::ve
restartRequestReply.send(op, data, values);
checkRestartReadyDone();
}

bool SwitchOrch::setAgingFDB(uint32_t sec)
{
sai_attribute_t attr;
attr.id = SAI_SWITCH_ATTR_FDB_AGING_TIME;
attr.value.u32 = sec;
auto status = sai_switch_api->set_switch_attribute(gSwitchId, &attr);
if (status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_ERROR("Failed to set switch %lx fdb_aging_time attribute: %d", gSwitchId, status);
return false;
}
SWSS_LOG_NOTICE("Set switch %lx fdb_aging_time %u sec", gSwitchId, sec);
return true;
}
1 change: 1 addition & 0 deletions orchagent/switchorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class SwitchOrch : public Orch
bool skipPendingTaskCheck() { return m_warmRestartCheck.skipPendingTaskCheck; }
void checkRestartReadyDone() { m_warmRestartCheck.checkRestartReadyState = false; }
void restartCheckReply(const string &op, const string &data, std::vector<FieldValueTuple> &values);
bool setAgingFDB(uint32_t sec);
private:
void doTask(Consumer &consumer);

Expand Down
50 changes: 50 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,56 @@ def is_table_entry_exists(self, db, table, keyregex, attributes):
extra_info.append("Desired key regex %s was not found" % str(keyregex))
return False, extra_info

def all_table_entry_has(self, db, table, keyregex, attributes):
tbl = swsscommon.Table(db, table)
keys = tbl.getKeys()
extra_info = []

if len(keys) == 0:
extra_info.append("keyregex %s not found" % keyregex)
return False, extra_info

for key in keys:
if re.match(keyregex, key) is None:
continue

status, fvs = tbl.get(key)
assert status, "Error reading from table %s" % table

d_attributes = dict(attributes)
for k, v in fvs:
if k in d_attributes and d_attributes[k] == v:
del d_attributes[k]

if len(d_attributes) != 0:
extra_info.append("Desired attributes %s were not found for key %s" % (str(d_attributes), key))
return False, extra_info

return True, extra_info

def all_table_entry_has_no(self, db, table, keyregex, attributes_list):
tbl = swsscommon.Table(db, table)
keys = tbl.getKeys()
extra_info = []

if len(keys) == 0:
extra_info.append("keyregex %s not found" % keyregex)
return False, extra_info

for key in keys:
if re.match(keyregex, key) is None:
continue

status, fvs = tbl.get(key)
assert status, "Error reading from table %s" % table

for k, v in fvs:
if k in attributes_list:
extra_info.append("Unexpected attribute %s was found for key %s" % (k, key))
return False, extra_info

return True, extra_info

def is_fdb_entry_exists(self, db, table, key_values, attributes):
tbl = swsscommon.Table(db, table)
keys = tbl.getKeys()
Expand Down
21 changes: 16 additions & 5 deletions tests/test_fdb_warm.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ def test_fdb_notifications(dvs):
[("SAI_BRIDGE_PORT_ATTR_FDB_LEARNING_MODE", "SAI_BRIDGE_PORT_FDB_LEARNING_MODE_HW")])
assert ok, str(extra)

# check fdb aging attr
ok, extra = dvs.all_table_entry_has_no(dvs.adb, 'ASIC_STATE:SAI_OBJECT_TYPE_SWITCH',
".*",
["SAI_SWITCH_ATTR_FDB_AGING_TIME"])

# bring up vlan and member
dvs.set_interface_status("Vlan6", "up")
dvs.add_ip_address("Vlan6", "6.6.6.1/24")
Expand Down Expand Up @@ -122,13 +127,14 @@ def test_fdb_notifications(dvs):
dvs.stop_swss()

# check FDB learning mode
ok, extra = dvs.is_table_entry_exists(dvs.adb, 'ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT',
iface_2_bridge_port_id["Ethernet64"],
ok, extra = dvs.all_table_entry_has(dvs.adb, 'ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT',
".*",
[("SAI_BRIDGE_PORT_ATTR_FDB_LEARNING_MODE", "SAI_BRIDGE_PORT_FDB_LEARNING_MODE_DISABLE")])
assert ok, str(extra)
ok, extra = dvs.is_table_entry_exists(dvs.adb, 'ASIC_STATE:SAI_OBJECT_TYPE_BRIDGE_PORT',
iface_2_bridge_port_id["Ethernet68"],
[("SAI_BRIDGE_PORT_ATTR_FDB_LEARNING_MODE", "SAI_BRIDGE_PORT_FDB_LEARNING_MODE_DISABLE")])
# check FDB aging time
ok, extra = dvs.all_table_entry_has(dvs.adb, 'ASIC_STATE:SAI_OBJECT_TYPE_SWITCH',
".*",
[("SAI_SWITCH_ATTR_FDB_AGING_TIME", "0")])
assert ok, str(extra)

dvs.start_swss()
Expand Down Expand Up @@ -168,6 +174,11 @@ def test_fdb_notifications(dvs):
counter_restarted = dvs.getCrmCounterValue('STATS', 'crm_stats_fdb_entry_used')
assert counter_inserted == counter_restarted

# check fdb aging attr
ok, extra = dvs.all_table_entry_has_no(dvs.adb, 'ASIC_STATE:SAI_OBJECT_TYPE_SWITCH',
".*",
["SAI_SWITCH_ATTR_FDB_AGING_TIME"])

finally:
# enable warm restart
dvs.runcmd("config warm_restart enable swss")
Expand Down

0 comments on commit 94fbcd9

Please sign in to comment.