Skip to content

Commit

Permalink
sonic-swss changes for MPLS
Browse files Browse the repository at this point in the history
  • Loading branch information
qbdwlr committed Apr 9, 2021
1 parent d8b8ca9 commit ed25692
Show file tree
Hide file tree
Showing 17 changed files with 1,290 additions and 93 deletions.
11 changes: 11 additions & 0 deletions cfgmgr/intfmgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,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 @@ -473,6 +474,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 @@ -518,6 +523,12 @@ bool IntfMgr::doIntfGeneralTask(const vector<string>& keys,
FieldValueTuple fvTuple("nat_zone", nat_zone);
data.push_back(fvTuple);
}
/* Set mpls */
if (!mpls.empty())
{
FieldValueTuple fvTuple("mpls", mpls);
data.push_back(fvTuple);
}
}

if (!vrf_name.empty())
Expand Down
139 changes: 138 additions & 1 deletion fpmsyncd/routesync.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ using namespace swss;

RouteSync::RouteSync(RedisPipeline *pipeline) :
m_routeTable(pipeline, APP_ROUTE_TABLE_NAME, true),
m_label_routeTable(pipeline, APP_LABEL_ROUTE_TABLE_NAME, true),
m_vnet_routeTable(pipeline, APP_VNET_RT_TABLE_NAME, true),
m_vnet_tunnelTable(pipeline, APP_VNET_RT_TUNNEL_TABLE_NAME, true),
m_warmStartHelper(pipeline, &m_routeTable, APP_ROUTE_TABLE_NAME, "bgp", "bgp"),
Expand Down Expand Up @@ -570,6 +571,12 @@ void RouteSync::onMsg(int nlmsg_type, struct nl_object *obj)

/* Supports IPv4 or IPv6 address, otherwise return immediately */
auto family = rtnl_route_get_family(route_obj);
/* Check for Label route. */
if (family == AF_MPLS)
{
onLabelRouteMsg(nlmsg_type, obj);
return;
}
if (family != AF_INET && family != AF_INET6)
{
SWSS_LOG_INFO("Unknown route family support (object: %s)", nl_object_get_type(obj));
Expand Down Expand Up @@ -698,7 +705,7 @@ void RouteSync::onRouteMsg(int nlmsg_type, struct nl_object *obj, char *vrf)
}

/* Get nexthop lists */
string nexthops = getNextHopGw(route_obj);
string nexthops = getNextHopList(route_obj);
string ifnames = getNextHopIf(route_obj);

vector<string> alsv = tokenize(ifnames, ',');
Expand Down Expand Up @@ -747,6 +754,80 @@ void RouteSync::onRouteMsg(int nlmsg_type, struct nl_object *obj, char *vrf)
}

/*
* Handle label route
* @arg nlmsg_type Netlink message type
* @arg obj Netlink object
*/
void RouteSync::onLabelRouteMsg(int nlmsg_type, struct nl_object *obj)
{
struct rtnl_route *route_obj = (struct rtnl_route *)obj;
struct nl_addr *daddr;
char destaddr[MAX_ADDR_SIZE + 1] = {0};

daddr = rtnl_route_get_dst(route_obj);
nl_addr2str(daddr, destaddr, MAX_ADDR_SIZE);
SWSS_LOG_INFO("Receive new route message dest addr: %s", destaddr);
if (nl_addr_iszero(daddr)) return;

if (nlmsg_type == RTM_DELROUTE)
{
m_label_routeTable.del(destaddr);
return;
}
else if (nlmsg_type != RTM_NEWROUTE)
{
SWSS_LOG_INFO("Unknown message-type: %d for %s", nlmsg_type, destaddr);
return;
}

switch (rtnl_route_get_type(route_obj))
{
case RTN_BLACKHOLE:
{
vector<FieldValueTuple> fvVector;
FieldValueTuple fv("blackhole", "true");
fvVector.push_back(fv);
m_label_routeTable.set(destaddr, fvVector);
return;
}
case RTN_UNICAST:
break;

case RTN_MULTICAST:
case RTN_BROADCAST:
case RTN_LOCAL:
SWSS_LOG_INFO("BUM routes aren't supported yet (%s)", destaddr);
return;

default:
return;
}

struct nl_list_head *nhs = rtnl_route_get_nexthops(route_obj);
if (!nhs)
{
SWSS_LOG_INFO("Nexthop list is empty for %s", destaddr);
return;
}

/* Get nexthop lists */
string nexthops = getNextHopList(route_obj);
string ifnames = getNextHopIf(route_obj);

vector<FieldValueTuple> fvVector;
FieldValueTuple nh("nexthop", nexthops);
FieldValueTuple idx("ifname", ifnames);

fvVector.push_back(nh);
fvVector.push_back(idx);
fvVector.push_back(wt);

m_label_routeTable.set(destaddr, fvVector);
SWSS_LOG_INFO("LabelRouteTable set msg: %s %s %s",
destaddr, nexthops.c_str(), ifnames.c_str());
}

/*
* Handle vnet route
* @arg nlmsg_type Netlink message type
* @arg obj Netlink object
Expand Down Expand Up @@ -886,6 +967,62 @@ bool RouteSync::getIfName(int if_index, char *if_name, size_t name_len)
return true;
}

/*
* Get next hop List
* @arg route_obj route object
*
* Return concatenation of NHs: nh0 + "," + nh1 + .... + "," + nhN
*/
string RouteSync::getNextHopList(struct rtnl_route *route_obj)
{
string result = "";

for (int i = 0; i < rtnl_route_get_nnexthops(route_obj); i++)
{
struct rtnl_nexthop *nexthop = rtnl_route_nexthop_n(route_obj, i);
struct nl_addr *addr = NULL;

if ((addr = rtnl_route_nh_get_newdst(nexthop)))
{
/* Next hop label is not empty */
char label[MAX_ADDR_SIZE + 1] = {0};
nl_addr2str(addr, label, MAX_ADDR_SIZE);
result += label;
result += string("+");
}
else if ((addr = rtnl_route_nh_get_encap_mpls_dst(nexthop)))
{
/* Next hop encap is not empty */
char label[MAX_ADDR_SIZE + 1] = {0};
nl_addr2str(addr, label, MAX_ADDR_SIZE);
result += label;
result += string("+");
}

if ((addr = rtnl_route_nh_get_gateway(nexthop)))
{
/* Next hop gateway is not empty */
char gw_ip[MAX_ADDR_SIZE + 1] = {0};
nl_addr2str(addr, gw_ip, MAX_ADDR_SIZE);
result += gw_ip;
}
else if ((addr = rtnl_route_nh_get_via(nexthop)))
{
/* Next hop via is not empty */
char via_ip[MAX_ADDR_SIZE + 1] = {0};
nl_addr2str(addr, via_ip, MAX_ADDR_SIZE);
result += via_ip;
}

if (i + 1 < rtnl_route_get_nnexthops(route_obj))
{
result += string(",");
}
}

return result;
}

/*
* Get next hop gateway IP addresses
* @arg route_obj route object
Expand Down
8 changes: 8 additions & 0 deletions fpmsyncd/routesync.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ class RouteSync : public NetMsg
private:
/* regular route table */
ProducerStateTable m_routeTable;
/* label route table */
ProducerStateTable m_label_routeTable;
/* vnet route table */
ProducerStateTable m_vnet_routeTable;
/* vnet vxlan tunnel table */
Expand All @@ -41,6 +43,9 @@ class RouteSync : public NetMsg
/* Handle regular route (include VRF route) */
void onRouteMsg(int nlmsg_type, struct nl_object *obj, char *vrf);

/* Handle label route */
void onLabelRouteMsg(int nlmsg_type, struct nl_object *obj);

void parseEncap(struct rtattr *tb, uint32_t &encap_value, string &rmac);

void parseRtAttrNested(struct rtattr **tb, int max,
Expand Down Expand Up @@ -70,6 +75,9 @@ class RouteSync : public NetMsg
string& nexthops, string& vni_list, string& mac_list,
string& intf_list);

/* Get next hop list */
string getNextHopList(struct rtnl_route *route_obj);

/* Get next hop gateway IP addresses */
string getNextHopGw(struct rtnl_route *route_obj);

Expand Down
40 changes: 40 additions & 0 deletions orchagent/bulker.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,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 @@ -84,6 +91,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 @@ -150,6 +169,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 @@ -452,6 +484,14 @@ inline EntityBulker<sai_fdb_api_t>::EntityBulker(sai_fdb_api_t *api)
*/
}

template <>
inline EntityBulker<sai_mpls_api_t>::EntityBulker(sai_mpls_api_t *api)
{
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
37 changes: 30 additions & 7 deletions orchagent/crmorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ 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" },
};

const map<CrmResourceType, uint32_t> crmResSaiAvailAttrMap =
Expand All @@ -60,7 +61,8 @@ 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 },
};

const map<string, CrmResourceType> crmThreshTypeResMap =
Expand All @@ -80,7 +82,8 @@ 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 },
};

const map<string, CrmResourceType> crmThreshLowResMap =
Expand All @@ -100,7 +103,8 @@ 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 },
};

const map<string, CrmResourceType> crmThreshHighResMap =
Expand All @@ -120,7 +124,8 @@ 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 },
};

const map<string, CrmThresholdType> crmThreshTypeMap =
Expand All @@ -147,7 +152,8 @@ 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 },
};

const map<string, CrmResourceType> crmUsedCntsTableMap =
Expand All @@ -167,7 +173,8 @@ 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 },
};

CrmOrch::CrmOrch(DBConnector *db, string tableName):
Expand Down Expand Up @@ -536,6 +543,22 @@ 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 = (uint32_t)availCount;

break;
}

default:
SWSS_LOG_ERROR("Failed to get CRM resource type %u. Unknown resource type.\n", (uint32_t)res.first);
return;
Expand Down

0 comments on commit ed25692

Please sign in to comment.