Skip to content

Commit

Permalink
[MPLS] sonic-swss changes for MPLS (sonic-net#1686)
Browse files Browse the repository at this point in the history
SONiC swss support for MPLS:

* RouteOrch support for SAI MPLS inseg
* NeighOrch support for MPLS NHs.
* CrmOrch support for MPLS inseg and NH accounting.
* New sonic-swss/tests/test_mpls.py for verification.

Unit-tests in sonic-swss/tests/test_mpls.py and sonic-utilities/tests
  • Loading branch information
qbdwlr authored Jun 28, 2021
1 parent 4c8e2b5 commit e86b900
Show file tree
Hide file tree
Showing 21 changed files with 2,148 additions and 140 deletions.
43 changes: 43 additions & 0 deletions cfgmgr/intfmgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,33 @@ void IntfMgr::setIntfVrf(const string &alias, const string &vrfName)
}
}

bool IntfMgr::setIntfMpls(const string &alias, const string& mpls)
{
stringstream cmd;
string res;

if (mpls == "enable")
{
cmd << "sysctl -w net.mpls.conf." << alias << ".input=1";
}
else if ((mpls == "disable") || mpls.empty())
{
cmd << "sysctl -w net.mpls.conf." << alias << ".input=0";
}
else
{
SWSS_LOG_ERROR("MPLS state is invalid: \"%s\"", mpls.c_str());
return false;
}
int ret = swss::exec(cmd.str(), res);
// Don't return error unless MPLS is explicitly set
if (ret && !mpls.empty())
{
SWSS_LOG_ERROR("Command '%s' failed with rc %d", cmd.str().c_str(), ret);
}
return true;
}

void IntfMgr::addLoopbackIntf(const string &alias)
{
stringstream cmd;
Expand Down Expand Up @@ -448,6 +475,7 @@ bool IntfMgr::doIntfGeneralTask(const vector<string>& keys,
string nat_zone = "";
string proxy_arp = "";
string grat_arp = "";
string mpls = "";

for (auto idx : data)
{
Expand All @@ -474,6 +502,10 @@ bool IntfMgr::doIntfGeneralTask(const vector<string>& keys,
{
grat_arp = value;
}
else if (field == "mpls")
{
mpls = value;
}

if (field == "nat_zone")
{
Expand Down Expand Up @@ -519,6 +551,17 @@ bool IntfMgr::doIntfGeneralTask(const vector<string>& keys,
FieldValueTuple fvTuple("nat_zone", nat_zone);
data.push_back(fvTuple);
}
/* Set mpls */
if (!setIntfMpls(alias, mpls))
{
SWSS_LOG_ERROR("Failed to set MPLS to \"%s\" for the \"%s\" interface", mpls.c_str(), alias.c_str());
return false;
}
if (!mpls.empty())
{
FieldValueTuple fvTuple("mpls", mpls);
data.push_back(fvTuple);
}
}

if (!parentAlias.empty())
Expand Down
1 change: 1 addition & 0 deletions cfgmgr/intfmgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class IntfMgr : public Orch
void setIntfIp(const std::string &alias, const std::string &opCmd, const IpPrefix &ipPrefix);
void setIntfVrf(const std::string &alias, const std::string &vrfName);
void setIntfMac(const std::string &alias, const std::string &macAddr);
bool setIntfMpls(const std::string &alias, const std::string &mpls);

bool doIntfGeneralTask(const std::vector<std::string>& keys, std::vector<FieldValueTuple> data, const std::string& op);
bool doIntfAddrTask(const std::vector<std::string>& keys, const std::vector<FieldValueTuple>& data, const std::string& op);
Expand Down
1 change: 1 addition & 0 deletions orchagent/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ orchagent_SOURCES = \
orch.cpp \
notifications.cpp \
routeorch.cpp \
mplsrouteorch.cpp \
neighorch.cpp \
intfsorch.cpp \
portsorch.cpp \
Expand Down
41 changes: 41 additions & 0 deletions orchagent/bulker.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,13 @@ static inline bool operator==(const sai_route_entry_t& a, const sai_route_entry_
;
}

static inline bool operator==(const sai_inseg_entry_t& a, const sai_inseg_entry_t& b)
{
return a.switch_id == b.switch_id
&& a.label == b.label
;
}

static inline std::size_t hash_value(const sai_ip_prefix_t& a)
{
size_t seed = 0;
Expand Down Expand Up @@ -85,6 +92,18 @@ namespace std
return seed;
}
};

template <>
struct hash<sai_inseg_entry_t>
{
size_t operator()(const sai_inseg_entry_t& a) const noexcept
{
size_t seed = 0;
boost::hash_combine(seed, a.switch_id);
boost::hash_combine(seed, a.label);
return seed;
}
};
}

// SAI typedef which is not available in SAI 1.5
Expand Down Expand Up @@ -151,6 +170,19 @@ struct SaiBulkerTraits<sai_next_hop_group_api_t>
//using bulk_set_entry_attribute_fn = sai_bulk_object_set_attribute_fn;
};

template<>
struct SaiBulkerTraits<sai_mpls_api_t>
{
using entry_t = sai_inseg_entry_t;
using api_t = sai_mpls_api_t;
using create_entry_fn = sai_create_inseg_entry_fn;
using remove_entry_fn = sai_remove_inseg_entry_fn;
using set_entry_attribute_fn = sai_set_inseg_entry_attribute_fn;
using bulk_create_entry_fn = sai_bulk_create_inseg_entry_fn;
using bulk_remove_entry_fn = sai_bulk_remove_inseg_entry_fn;
using bulk_set_entry_attribute_fn = sai_bulk_set_inseg_entry_attribute_fn;
};

template <typename T>
class EntityBulker
{
Expand Down Expand Up @@ -550,6 +582,15 @@ inline EntityBulker<sai_fdb_api_t>::EntityBulker(sai_fdb_api_t *api, size_t max_
*/
}

template <>
inline EntityBulker<sai_mpls_api_t>::EntityBulker(sai_mpls_api_t *api, size_t max_bulk_size) :
max_bulk_size(max_bulk_size)
{
create_entries = api->create_inseg_entries;
remove_entries = api->remove_inseg_entries;
set_entries_attribute = api->set_inseg_entries_attribute;
}

template <typename T>
class ObjectBulker
{
Expand Down
74 changes: 62 additions & 12 deletions orchagent/crmorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ const map<CrmResourceType, string> crmResTypeNameMap =
{ CrmResourceType::CRM_FDB_ENTRY, "FDB_ENTRY" },
{ CrmResourceType::CRM_IPMC_ENTRY, "IPMC_ENTRY" },
{ CrmResourceType::CRM_SNAT_ENTRY, "SNAT_ENTRY" },
{ CrmResourceType::CRM_DNAT_ENTRY, "DNAT_ENTRY" }
{ CrmResourceType::CRM_DNAT_ENTRY, "DNAT_ENTRY" },
{ CrmResourceType::CRM_MPLS_INSEG, "MPLS_INSEG" },
{ CrmResourceType::CRM_MPLS_NEXTHOP, "MPLS_NEXTHOP" },
};

const map<CrmResourceType, uint32_t> crmResSaiAvailAttrMap =
Expand All @@ -60,7 +62,9 @@ const map<CrmResourceType, uint32_t> crmResSaiAvailAttrMap =
{ 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 }
{ CrmResourceType::CRM_DNAT_ENTRY, SAI_SWITCH_ATTR_AVAILABLE_DNAT_ENTRY },
{ CrmResourceType::CRM_MPLS_INSEG, SAI_OBJECT_TYPE_INSEG_ENTRY },
{ CrmResourceType::CRM_MPLS_NEXTHOP, SAI_OBJECT_TYPE_NEXT_HOP },
};

const map<string, CrmResourceType> crmThreshTypeResMap =
Expand All @@ -80,7 +84,9 @@ const map<string, CrmResourceType> crmThreshTypeResMap =
{ "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 }
{ "dnat_entry_threshold_type", CrmResourceType::CRM_DNAT_ENTRY },
{ "mpls_inseg_threshold_type", CrmResourceType::CRM_MPLS_INSEG },
{ "mpls_nexthop_threshold_type", CrmResourceType::CRM_MPLS_NEXTHOP },
};

const map<string, CrmResourceType> crmThreshLowResMap =
Expand All @@ -100,7 +106,9 @@ const map<string, CrmResourceType> crmThreshLowResMap =
{"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 }
{"dnat_entry_low_threshold", CrmResourceType::CRM_DNAT_ENTRY },
{"mpls_inseg_low_threshold", CrmResourceType::CRM_MPLS_INSEG },
{"mpls_nexthop_low_threshold", CrmResourceType::CRM_MPLS_NEXTHOP },
};

const map<string, CrmResourceType> crmThreshHighResMap =
Expand All @@ -120,7 +128,9 @@ const map<string, CrmResourceType> crmThreshHighResMap =
{"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 }
{"dnat_entry_high_threshold", CrmResourceType::CRM_DNAT_ENTRY },
{"mpls_inseg_high_threshold", CrmResourceType::CRM_MPLS_INSEG },
{"mpls_nexthop_high_threshold", CrmResourceType::CRM_MPLS_NEXTHOP },
};

const map<string, CrmThresholdType> crmThreshTypeMap =
Expand All @@ -147,7 +157,9 @@ const map<string, CrmResourceType> crmAvailCntsTableMap =
{ "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 }
{ "crm_stats_dnat_entry_available", CrmResourceType::CRM_DNAT_ENTRY },
{ "crm_stats_mpls_inseg_available", CrmResourceType::CRM_MPLS_INSEG },
{ "crm_stats_mpls_nexthop_available", CrmResourceType::CRM_MPLS_NEXTHOP },
};

const map<string, CrmResourceType> crmUsedCntsTableMap =
Expand All @@ -167,7 +179,9 @@ const map<string, CrmResourceType> crmUsedCntsTableMap =
{ "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 }
{ "crm_stats_dnat_entry_used", CrmResourceType::CRM_DNAT_ENTRY },
{ "crm_stats_mpls_inseg_used", CrmResourceType::CRM_MPLS_INSEG },
{ "crm_stats_mpls_nexthop_used", CrmResourceType::CRM_MPLS_NEXTHOP },
};

CrmOrch::CrmOrch(DBConnector *db, string tableName):
Expand Down Expand Up @@ -463,10 +477,10 @@ void CrmOrch::getResAvailableCounters()
sai_status_t status = sai_switch_api->get_switch_attribute(gSwitchId, 1, &attr);
if (status != SAI_STATUS_SUCCESS)
{
if((status == SAI_STATUS_NOT_SUPPORTED) ||
(status == SAI_STATUS_NOT_IMPLEMENTED) ||
SAI_STATUS_IS_ATTR_NOT_SUPPORTED(status) ||
SAI_STATUS_IS_ATTR_NOT_IMPLEMENTED(status))
if ((status == SAI_STATUS_NOT_SUPPORTED) ||
(status == SAI_STATUS_NOT_IMPLEMENTED) ||
SAI_STATUS_IS_ATTR_NOT_SUPPORTED(status) ||
SAI_STATUS_IS_ATTR_NOT_IMPLEMENTED(status))
{
// mark unsupported resources
res.second.resStatus = CrmResourceStatus::CRM_RES_NOT_SUPPORTED;
Expand Down Expand Up @@ -536,8 +550,44 @@ void CrmOrch::getResAvailableCounters()
break;
}

case CrmResourceType::CRM_MPLS_INSEG:
{
sai_object_type_t objType = static_cast<sai_object_type_t>(crmResSaiAvailAttrMap.at(res.first));
uint64_t availCount = 0;
sai_status_t status = sai_object_type_get_availability(gSwitchId, objType, 0, nullptr, &availCount);
if (status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_ERROR("Failed to get availability for object_type %u , rv:%d", objType, status);
break;
}

res.second.countersMap[CRM_COUNTERS_TABLE_KEY].availableCounter = static_cast<uint32_t>(availCount);

break;
}

case CrmResourceType::CRM_MPLS_NEXTHOP:
{
sai_object_type_t objType = static_cast<sai_object_type_t>(crmResSaiAvailAttrMap.at(res.first));
sai_attribute_t attr;
uint64_t availCount = 0;

attr.id = SAI_NEXT_HOP_ATTR_TYPE;
attr.value.s32 = SAI_NEXT_HOP_TYPE_MPLS;
sai_status_t status = sai_object_type_get_availability(gSwitchId, objType, 1, &attr, &availCount);
if (status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_ERROR("Failed to get availability for object_type %u , rv:%d", objType, status);
break;
}

res.second.countersMap[CRM_COUNTERS_TABLE_KEY].availableCounter = static_cast<uint32_t>(availCount);

break;
}

default:
SWSS_LOG_ERROR("Failed to get CRM resource type %u. Unknown resource type.\n", (uint32_t)res.first);
SWSS_LOG_ERROR("Failed to get CRM resource type %u. Unknown resource type.\n", static_cast<uint32_t>(res.first));
return;
}
}
Expand Down
2 changes: 2 additions & 0 deletions orchagent/crmorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ enum class CrmResourceType
CRM_IPMC_ENTRY,
CRM_SNAT_ENTRY,
CRM_DNAT_ENTRY,
CRM_MPLS_INSEG,
CRM_MPLS_NEXTHOP,
};

enum class CrmThresholdType
Expand Down
50 changes: 50 additions & 0 deletions orchagent/intfsorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,31 @@ void IntfsOrch::decreaseRouterIntfsRefCount(const string &alias)
alias.c_str(), m_syncdIntfses[alias].ref_count);
}

bool IntfsOrch::setRouterIntfsMpls(const Port &port)
{
SWSS_LOG_ENTER();

sai_attribute_t attr;
attr.id = SAI_ROUTER_INTERFACE_ATTR_ADMIN_MPLS_STATE;
attr.value.booldata = port.m_mpls;

sai_status_t status =
sai_router_intfs_api->set_router_interface_attribute(port.m_rif_id, &attr);
if (status != SAI_STATUS_SUCCESS)
{
SWSS_LOG_ERROR("Failed to set router interface %s MPLS to %s, rv:%d",
port.m_alias.c_str(), (port.m_mpls ? "enable" : "disable"), status);
task_process_status handle_status = handleSaiSetStatus(SAI_API_ROUTER_INTERFACE, status);
if (handle_status != task_success)
{
return parseHandleSaiStatusFailure(handle_status);
}
}
SWSS_LOG_NOTICE("Set router interface %s MPLS to %s", port.m_alias.c_str(),
(port.m_mpls ? "enable" : "disable"));
return true;
}

bool IntfsOrch::setRouterIntfsMtu(const Port &port)
{
SWSS_LOG_ENTER();
Expand Down Expand Up @@ -636,6 +661,7 @@ void IntfsOrch::doTask(Consumer &consumer)
uint32_t nat_zone_id = 0;
string proxy_arp = "";
string inband_type = "";
bool mpls = false;

for (auto idx : data)
{
Expand All @@ -661,6 +687,10 @@ void IntfsOrch::doTask(Consumer &consumer)
continue;
}
}
else if (field == "mpls")
{
mpls = (value == "enable" ? true : false);
}
else if (field == "nat_zone")
{
try
Expand Down Expand Up @@ -852,6 +882,14 @@ void IntfsOrch::doTask(Consumer &consumer)
}
gPortsOrch->setPort(alias, port);
}
/* Set MPLS */
if ((!ip_prefix_in_key) && (port.m_mpls != mpls))
{
port.m_mpls = mpls;

setRouterIntfsMpls(port);
gPortsOrch->setPort(alias, port);
}
}
}

Expand Down Expand Up @@ -1091,6 +1129,17 @@ bool IntfsOrch::addRouterIntfs(sai_object_id_t vrf_id, Port &port)
attr.value.u32 = port.m_mtu;
attrs.push_back(attr);

if (port.m_mpls)
{
// Default value of ADMIN_MPLS_STATE is disabled and does not need
// to be explicitly included in RIF Create request.
attr.id = SAI_ROUTER_INTERFACE_ATTR_ADMIN_MPLS_STATE;
attr.value.booldata = port.m_mpls;

SWSS_LOG_INFO("Enabling MPLS on interface %s\n", port.m_alias.c_str());
attrs.push_back(attr);
}

if (gIsNatSupported)
{
attr.id = SAI_ROUTER_INTERFACE_ATTR_NAT_ZONE_ID;
Expand Down Expand Up @@ -1153,6 +1202,7 @@ bool IntfsOrch::removeRouterIntfs(Port &port)
port.m_rif_id = 0;
port.m_vr_id = 0;
port.m_nat_zone_id = 0;
port.m_mpls = false;
gPortsOrch->setPort(port.m_alias, port);

SWSS_LOG_NOTICE("Remove router interface for port %s", port.m_alias.c_str());
Expand Down
Loading

0 comments on commit e86b900

Please sign in to comment.