Skip to content

Commit

Permalink
[crm] Add support for snat, dnat and ipmc crm resources (#1511)
Browse files Browse the repository at this point in the history
What I did
Added support for snat, dnat and ipmc resources under CRM module.

Why I did it
New feature NAT adds new resources snat_enty and dnat_entry that needs to be monitored. ipmc_entry tracks IP multicast resources used by switch.

Associated PRs
sonic-net/sonic-utilities/pull/1258
sonic-net/sonic-buildimage#6012

Signed-off-by: Prabhu Sreenivasan <prabhu.sreenivasan@broadcom.com>
  • Loading branch information
PrabhuSreenivasan authored Dec 29, 2020
1 parent 7fc3888 commit a43f6be
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 15 deletions.
11 changes: 10 additions & 1 deletion doc/Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,16 @@ group name and IP ranges in **BGP_PEER_RANGE** table.
"ipv4_neighbor_low_threshold": "70",
"acl_group_threshold_type": "percentage",
"ipv4_nexthop_high_threshold": "85",
"ipv6_route_threshold_type": "percentage"
"ipv6_route_threshold_type": "percentage",
"snat_entry_threshold_type": "percentage",
"snat_entry_high_threshold": "85",
"snat_entry_low_threshold": "70",
"dnat_entry_threshold_type": "percentage",
"dnat_entry_high_threshold": "85",
"dnat_entry_low_threshold": "70",
"ipmc_entry_threshold_type": "percentage",
"ipmc_entry_high_threshold": "85",
"ipmc_entry_low_threshold": "70"
}
}
}
Expand Down
71 changes: 57 additions & 14 deletions orchagent/crmorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ const map<CrmResourceType, string> crmResTypeNameMap =
{ CrmResourceType::CRM_ACL_GROUP, "ACL_GROUP" },
{ CrmResourceType::CRM_ACL_ENTRY, "ACL_ENTRY" },
{ CrmResourceType::CRM_ACL_COUNTER, "ACL_COUNTER" },
{ CrmResourceType::CRM_FDB_ENTRY, "FDB_ENTRY" }
{ CrmResourceType::CRM_FDB_ENTRY, "FDB_ENTRY" },
{ CrmResourceType::CRM_IPMC_ENTRY, "IPMC_ENTRY" },
{ CrmResourceType::CRM_SNAT_ENTRY, "SNAT_ENTRY" },
{ CrmResourceType::CRM_DNAT_ENTRY, "DNAT_ENTRY" }
};

const map<CrmResourceType, uint32_t> crmResSaiAvailAttrMap =
Expand All @@ -54,7 +57,10 @@ const map<CrmResourceType, uint32_t> crmResSaiAvailAttrMap =
{ CrmResourceType::CRM_ACL_GROUP, SAI_SWITCH_ATTR_AVAILABLE_ACL_TABLE_GROUP },
{ CrmResourceType::CRM_ACL_ENTRY, SAI_ACL_TABLE_ATTR_AVAILABLE_ACL_ENTRY },
{ CrmResourceType::CRM_ACL_COUNTER, SAI_ACL_TABLE_ATTR_AVAILABLE_ACL_COUNTER },
{ CrmResourceType::CRM_FDB_ENTRY, SAI_SWITCH_ATTR_AVAILABLE_FDB_ENTRY }
{ CrmResourceType::CRM_FDB_ENTRY, SAI_SWITCH_ATTR_AVAILABLE_FDB_ENTRY },
{ CrmResourceType::CRM_IPMC_ENTRY, SAI_SWITCH_ATTR_AVAILABLE_IPMC_ENTRY},
{ CrmResourceType::CRM_SNAT_ENTRY, SAI_SWITCH_ATTR_AVAILABLE_SNAT_ENTRY },
{ CrmResourceType::CRM_DNAT_ENTRY, SAI_SWITCH_ATTR_AVAILABLE_DNAT_ENTRY }
};

const map<string, CrmResourceType> crmThreshTypeResMap =
Expand All @@ -71,7 +77,10 @@ const map<string, CrmResourceType> crmThreshTypeResMap =
{ "acl_group_threshold_type", CrmResourceType::CRM_ACL_GROUP },
{ "acl_entry_threshold_type", CrmResourceType::CRM_ACL_ENTRY },
{ "acl_counter_threshold_type", CrmResourceType::CRM_ACL_COUNTER },
{ "fdb_entry_threshold_type", CrmResourceType::CRM_FDB_ENTRY }
{ "fdb_entry_threshold_type", CrmResourceType::CRM_FDB_ENTRY },
{ "ipmc_entry_threshold_type", CrmResourceType::CRM_IPMC_ENTRY },
{ "snat_entry_threshold_type", CrmResourceType::CRM_SNAT_ENTRY },
{ "dnat_entry_threshold_type", CrmResourceType::CRM_DNAT_ENTRY }
};

const map<string, CrmResourceType> crmThreshLowResMap =
Expand All @@ -89,6 +98,9 @@ const map<string, CrmResourceType> crmThreshLowResMap =
{"acl_entry_low_threshold", CrmResourceType::CRM_ACL_ENTRY },
{"acl_counter_low_threshold", CrmResourceType::CRM_ACL_COUNTER },
{"fdb_entry_low_threshold", CrmResourceType::CRM_FDB_ENTRY },
{"ipmc_entry_low_threshold", CrmResourceType::CRM_IPMC_ENTRY },
{"snat_entry_low_threshold", CrmResourceType::CRM_SNAT_ENTRY },
{"dnat_entry_low_threshold", CrmResourceType::CRM_DNAT_ENTRY }
};

const map<string, CrmResourceType> crmThreshHighResMap =
Expand All @@ -105,7 +117,10 @@ const map<string, CrmResourceType> crmThreshHighResMap =
{"acl_group_high_threshold", CrmResourceType::CRM_ACL_GROUP },
{"acl_entry_high_threshold", CrmResourceType::CRM_ACL_ENTRY },
{"acl_counter_high_threshold", CrmResourceType::CRM_ACL_COUNTER },
{"fdb_entry_high_threshold", CrmResourceType::CRM_FDB_ENTRY }
{"fdb_entry_high_threshold", CrmResourceType::CRM_FDB_ENTRY },
{"ipmc_entry_high_threshold", CrmResourceType::CRM_IPMC_ENTRY },
{"snat_entry_high_threshold", CrmResourceType::CRM_SNAT_ENTRY },
{"dnat_entry_high_threshold", CrmResourceType::CRM_DNAT_ENTRY }
};

const map<string, CrmThresholdType> crmThreshTypeMap =
Expand All @@ -129,7 +144,10 @@ const map<string, CrmResourceType> crmAvailCntsTableMap =
{ "crm_stats_acl_group_available", CrmResourceType::CRM_ACL_GROUP },
{ "crm_stats_acl_entry_available", CrmResourceType::CRM_ACL_ENTRY },
{ "crm_stats_acl_counter_available", CrmResourceType::CRM_ACL_COUNTER },
{ "crm_stats_fdb_entry_available", CrmResourceType::CRM_FDB_ENTRY }
{ "crm_stats_fdb_entry_available", CrmResourceType::CRM_FDB_ENTRY },
{ "crm_stats_ipmc_entry_available", CrmResourceType::CRM_IPMC_ENTRY },
{ "crm_stats_snat_entry_available", CrmResourceType::CRM_SNAT_ENTRY },
{ "crm_stats_dnat_entry_available", CrmResourceType::CRM_DNAT_ENTRY }
};

const map<string, CrmResourceType> crmUsedCntsTableMap =
Expand All @@ -146,7 +164,10 @@ const map<string, CrmResourceType> crmUsedCntsTableMap =
{ "crm_stats_acl_group_used", CrmResourceType::CRM_ACL_GROUP },
{ "crm_stats_acl_entry_used", CrmResourceType::CRM_ACL_ENTRY },
{ "crm_stats_acl_counter_used", CrmResourceType::CRM_ACL_COUNTER },
{ "crm_stats_fdb_entry_used", CrmResourceType::CRM_FDB_ENTRY }
{ "crm_stats_fdb_entry_used", CrmResourceType::CRM_FDB_ENTRY },
{ "crm_stats_ipmc_entry_used", CrmResourceType::CRM_IPMC_ENTRY },
{ "crm_stats_snat_entry_used", CrmResourceType::CRM_SNAT_ENTRY },
{ "crm_stats_dnat_entry_used", CrmResourceType::CRM_DNAT_ENTRY }
};

CrmOrch::CrmOrch(DBConnector *db, string tableName):
Expand Down Expand Up @@ -429,10 +450,18 @@ void CrmOrch::getResAvailableCounters()
case SAI_SWITCH_ATTR_AVAILABLE_NEXT_HOP_GROUP_MEMBER_ENTRY:
case SAI_SWITCH_ATTR_AVAILABLE_NEXT_HOP_GROUP_ENTRY:
case SAI_SWITCH_ATTR_AVAILABLE_FDB_ENTRY:
case SAI_SWITCH_ATTR_AVAILABLE_IPMC_ENTRY:
case SAI_SWITCH_ATTR_AVAILABLE_SNAT_ENTRY:
case SAI_SWITCH_ATTR_AVAILABLE_DNAT_ENTRY:
{
sai_status_t status = sai_switch_api->get_switch_attribute(gSwitchId, 1, &attr);
if (status != SAI_STATUS_SUCCESS)
{
if(status == SAI_STATUS_NOT_SUPPORTED)
{
// remove unsupported resources from map
m_resourcesMap.erase(res.first);
}
SWSS_LOG_ERROR("Failed to get switch attribute %u , rv:%d", attr.id, status);
break;
}
Expand Down Expand Up @@ -504,22 +533,36 @@ void CrmOrch::updateCrmCountersTable()
// Update CRM used counters in COUNTERS_DB
for (const auto &i : crmUsedCntsTableMap)
{
for (const auto &cnt : m_resourcesMap.at(i.second).countersMap)
try
{
for (const auto &cnt : m_resourcesMap.at(i.second).countersMap)
{
FieldValueTuple attr(i.first, to_string(cnt.second.usedCounter));
vector<FieldValueTuple> attrs = { attr };
m_countersCrmTable->set(cnt.first, attrs);
}
}
catch(const out_of_range &e)
{
FieldValueTuple attr(i.first, to_string(cnt.second.usedCounter));
vector<FieldValueTuple> attrs = { attr };
m_countersCrmTable->set(cnt.first, attrs);
// expected when a resource is unavailable
}
}

// Update CRM available counters in COUNTERS_DB
for (const auto &i : crmAvailCntsTableMap)
{
for (const auto &cnt : m_resourcesMap.at(i.second).countersMap)
try
{
for (const auto &cnt : m_resourcesMap.at(i.second).countersMap)
{
FieldValueTuple attr(i.first, to_string(cnt.second.availableCounter));
vector<FieldValueTuple> attrs = { attr };
m_countersCrmTable->set(cnt.first, attrs);
}
}
catch(const out_of_range &e)
{
FieldValueTuple attr(i.first, to_string(cnt.second.availableCounter));
vector<FieldValueTuple> attrs = { attr };
m_countersCrmTable->set(cnt.first, attrs);
// expected when a resource is unavailable
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions orchagent/crmorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ enum class CrmResourceType
CRM_ACL_ENTRY,
CRM_ACL_COUNTER,
CRM_FDB_ENTRY,
CRM_IPMC_ENTRY,
CRM_SNAT_ENTRY,
CRM_DNAT_ENTRY,
};

enum class CrmThresholdType
Expand Down
69 changes: 69 additions & 0 deletions tests/test_crm.py
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,31 @@ def test_CrmAclGroup(self, dvs, testlog):
#table_used_counter = getCrmCounterValue(dvs, 'ACL_STATS:INGRESS:PORT', 'crm_stats_acl_group_used')
#assert table_used_counter == 0

def test_CrmSnatEntry(self, dvs, testlog):

# get counters
used_counter = getCrmCounterValue(dvs, 'STATS', 'crm_stats_snat_entry_used')
avail_counter = getCrmCounterValue(dvs, 'STATS', 'crm_stats_snat_entry_available')
assert used_counter == 0
assert avail_counter != 0

def test_CrmDnatEntry(self, dvs, testlog):

# get counters
used_counter = getCrmCounterValue(dvs, 'STATS', 'crm_stats_dnat_entry_used')
avail_counter = getCrmCounterValue(dvs, 'STATS', 'crm_stats_dnat_entry_available')
assert used_counter == 0
assert avail_counter != 0

# commented ipmc test case till vslib is updated
# def test_CrmIpmcEntry(self, dvs, testlog):
#
# # get counters
# used_counter = getCrmCounterValue(dvs, 'STATS', 'crm_stats_ipmc_entry_used')
# avail_counter = getCrmCounterValue(dvs, 'STATS', 'crm_stats_ipmc_entry_available')
# assert used_counter == 0
# assert avail_counter != 0

def test_Configure(self, dvs, testlog):

#polling interval
Expand Down Expand Up @@ -905,6 +930,50 @@ def test_Configure_fdb(self, dvs, testlog):
threshold_type = getCrmConfigStr(dvs, 'Config', 'fdb_entry_threshold_type')
assert threshold_type == 'percentage'

def test_Configure_snat(self, dvs, testlog):

#thresholds snat low/high threshold/type
dvs.runcmd("crm config thresholds snat low 50")
dvs.runcmd("crm config thresholds snat high 90")
dvs.runcmd("crm config thresholds snat type percentage")

time.sleep(2)
threshold_low = getCrmConfigValue(dvs, 'Config', 'snat_entry_low_threshold')
assert threshold_low == 50
threshold_high = getCrmConfigValue(dvs, 'Config', 'snat_entry_high_threshold')
assert threshold_high == 90
threshold_type = getCrmConfigStr(dvs, 'Config', 'snat_entry_threshold_type')
assert threshold_type == 'percentage'

def test_Configure_dnat(self, dvs, testlog):

#thresholds dnat low/high threshold/type
dvs.runcmd("crm config thresholds dnat low 50")
dvs.runcmd("crm config thresholds dnat high 90")
dvs.runcmd("crm config thresholds dnat type percentage")

time.sleep(2)
threshold_low = getCrmConfigValue(dvs, 'Config', 'dnat_entry_low_threshold')
assert threshold_low == 50
threshold_high = getCrmConfigValue(dvs, 'Config', 'dnat_entry_high_threshold')
assert threshold_high == 90
threshold_type = getCrmConfigStr(dvs, 'Config', 'dnat_entry_threshold_type')
assert threshold_type == 'percentage'

def test_Configure_ipmc(self, dvs, testlog):

#thresholds ipmc low/high threshold/type
dvs.runcmd("crm config thresholds ipmc low 50")
dvs.runcmd("crm config thresholds ipmc high 90")
dvs.runcmd("crm config thresholds ipmc type percentage")

time.sleep(2)
threshold_low = getCrmConfigValue(dvs, 'Config', 'ipmc_entry_low_threshold')
assert threshold_low == 50
threshold_high = getCrmConfigValue(dvs, 'Config', 'ipmc_entry_high_threshold')
assert threshold_high == 90
threshold_type = getCrmConfigStr(dvs, 'Config', 'ipmc_entry_threshold_type')
assert threshold_type == 'percentage'

# Add Dummy always-pass test at end as workaroud
# for issue when Flaky fail on final test it invokes module tear-down before retrying
Expand Down

0 comments on commit a43f6be

Please sign in to comment.