-
Notifications
You must be signed in to change notification settings - Fork 693
[fpmsyncd] updates for MPLS #1794
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,6 +21,8 @@ using namespace swss; | |
| #define VRF_PREFIX "Vrf" | ||
| #define MGMT_VRF_PREFIX "mgmt" | ||
|
|
||
| #define NHG_DELIMITER ',' | ||
|
|
||
| #ifndef ETH_ALEN | ||
| #define ETH_ALEN 6 | ||
| #endif | ||
|
|
@@ -44,6 +46,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"), | ||
|
|
@@ -113,10 +116,10 @@ void RouteSync::parseEncap(struct rtattr *tb, uint32_t &encap_value, string &rma | |
| void RouteSync::getEvpnNextHopSep(string& nexthops, string& vni_list, | ||
| string& mac_list, string& intf_list) | ||
| { | ||
| nexthops += string(","); | ||
| vni_list += string(","); | ||
| mac_list += string(","); | ||
| intf_list += string(","); | ||
| nexthops += NHG_DELIMITER; | ||
| vni_list += NHG_DELIMITER; | ||
| mac_list += NHG_DELIMITER; | ||
| intf_list += NHG_DELIMITER; | ||
|
|
||
| return; | ||
| } | ||
|
|
@@ -571,6 +574,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)); | ||
|
|
@@ -708,11 +717,13 @@ void RouteSync::onRouteMsg(int nlmsg_type, struct nl_object *obj, char *vrf) | |
| } | ||
|
|
||
| /* Get nexthop lists */ | ||
| string nexthops = getNextHopGw(route_obj); | ||
| string ifnames = getNextHopIf(route_obj); | ||
| string gw_list; | ||
| string intf_list; | ||
| string mpls_list; | ||
| getNextHopList(route_obj, gw_list, mpls_list, intf_list); | ||
| string weights = getNextHopWt(route_obj); | ||
|
|
||
| vector<string> alsv = tokenize(ifnames, ','); | ||
| vector<string> alsv = tokenize(intf_list, NHG_DELIMITER); | ||
| for (auto alias : alsv) | ||
| { | ||
| /* | ||
|
|
@@ -722,17 +733,22 @@ void RouteSync::onRouteMsg(int nlmsg_type, struct nl_object *obj, char *vrf) | |
| if (alias == "eth0" || alias == "docker0") | ||
| { | ||
| SWSS_LOG_DEBUG("Skip routes to eth0 or docker0: %s %s %s", | ||
| destipprefix, nexthops.c_str(), ifnames.c_str()); | ||
| destipprefix, gw_list.c_str(), intf_list.c_str()); | ||
| return; | ||
| } | ||
| } | ||
|
|
||
| vector<FieldValueTuple> fvVector; | ||
| FieldValueTuple nh("nexthop", nexthops); | ||
| FieldValueTuple idx("ifname", ifnames); | ||
| FieldValueTuple gw("nexthop", gw_list); | ||
| FieldValueTuple intf("ifname", intf_list); | ||
|
|
||
| fvVector.push_back(nh); | ||
| fvVector.push_back(idx); | ||
| fvVector.push_back(gw); | ||
| fvVector.push_back(intf); | ||
| if (!mpls_list.empty()) | ||
| { | ||
| FieldValueTuple mpls_nh("mpls_nh", mpls_list); | ||
| fvVector.push_back(mpls_nh); | ||
| } | ||
| if (!weights.empty()) | ||
| { | ||
| FieldValueTuple wt("weight", weights); | ||
|
|
@@ -742,8 +758,8 @@ void RouteSync::onRouteMsg(int nlmsg_type, struct nl_object *obj, char *vrf) | |
| if (!warmRestartInProgress) | ||
| { | ||
| m_routeTable.set(destipprefix, fvVector); | ||
| SWSS_LOG_DEBUG("RouteTable set msg: %s %s %s", | ||
| destipprefix, nexthops.c_str(), ifnames.c_str()); | ||
| SWSS_LOG_DEBUG("RouteTable set msg: %s %s %s %s", destipprefix, | ||
| gw_list.c_str(), intf_list.c_str(), mpls_list.c_str()); | ||
| } | ||
|
|
||
| /* | ||
|
|
@@ -752,8 +768,8 @@ void RouteSync::onRouteMsg(int nlmsg_type, struct nl_object *obj, char *vrf) | |
| */ | ||
| else | ||
| { | ||
| SWSS_LOG_INFO("Warm-Restart mode: RouteTable set msg: %s %s %s", | ||
| destipprefix, nexthops.c_str(), ifnames.c_str()); | ||
| SWSS_LOG_INFO("Warm-Restart mode: RouteTable set msg: %s %s %s %s", destipprefix, | ||
| gw_list.c_str(), intf_list.c_str(), mpls_list.c_str()); | ||
|
|
||
| const KeyOpFieldsValuesTuple kfv = std::make_tuple(destipprefix, | ||
| SET_COMMAND, | ||
|
|
@@ -763,6 +779,98 @@ 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 LabelRoute 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 LabelRoute %s", nlmsg_type, destaddr); | ||
| return; | ||
| } | ||
|
|
||
| /* Get the index of the master device */ | ||
| uint32_t master_index = rtnl_route_get_table(route_obj); | ||
| /* if the table_id is not set in the route obj then route is for default vrf. */ | ||
| if (master_index) | ||
| { | ||
| SWSS_LOG_INFO("Unsupported Non-default VRF: %d for LabelRoute %s", | ||
| master_index, 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 LabelRoute %s", destaddr); | ||
| return; | ||
| } | ||
|
|
||
| /* Get nexthop lists */ | ||
| string gw_list; | ||
| string intf_list; | ||
| string mpls_list; | ||
| getNextHopList(route_obj, gw_list, mpls_list, intf_list); | ||
|
|
||
| vector<FieldValueTuple> fvVector; | ||
| FieldValueTuple gw("nexthop", gw_list); | ||
| FieldValueTuple intf("ifname", intf_list); | ||
| FieldValueTuple mpls_pop("mpls_pop", "1"); | ||
|
|
||
| fvVector.push_back(gw); | ||
| fvVector.push_back(intf); | ||
| if (!mpls_list.empty()) | ||
| { | ||
| FieldValueTuple mpls_nh("mpls_nh", mpls_list); | ||
| fvVector.push_back(mpls_nh); | ||
| } | ||
| fvVector.push_back(mpls_pop); | ||
|
|
||
| m_label_routeTable.set(destaddr, fvVector); | ||
| SWSS_LOG_INFO("LabelRouteTable set msg: %s %s %s %s", destaddr, | ||
| gw_list.c_str(), intf_list.c_str(), mpls_list.c_str()); | ||
| } | ||
|
|
||
| /* | ||
| * Handle vnet route | ||
| * @arg nlmsg_type Netlink message type | ||
| * @arg obj Netlink object | ||
|
|
@@ -902,6 +1010,123 @@ bool RouteSync::getIfName(int if_index, char *if_name, size_t name_len) | |
| return true; | ||
| } | ||
|
|
||
| #ifndef LIBNL3_ENCAP_MPLS | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. lets remove this and update azure pipeline to fetch libnl3 debian package from sonic-buildimaage
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @smaheshm I am not familiar with the azure pipeline infrastructure and will need input with exact changes required to fetch libnl3 debian packages from sonic-buildimage.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @smaheshm I have submitted a new PR sonic-net/sonic-buildimage#8064 that is the only other change required to make this PR work in the Azure pipeline as it is currently. |
||
| /* Thise stub is needed for sonic-swss Azure pipeline, since encap_mpls | ||
| * accessor is not yet upstreamed to external libnl3 project and sonic-swss | ||
| * uses released version of libnl3 rather than customized version available | ||
| * in sonic-buildimage. | ||
| */ | ||
| static | ||
| struct nl_addr *rtnl_route_nh_get_encap_mpls_dst(struct rtnl_nexthop *nh) | ||
| { | ||
| return NULL; | ||
| } | ||
| #endif // LIBNL3_ENCAP_MPLS | ||
|
|
||
| /* | ||
| * getNextHopList() - parses next hop list attached to route_obj | ||
| * @arg route_obj (input) Netlink route object | ||
| * @arg gw_list (output) comma-separated list of NH IP gateways | ||
| * @arg mpls_list (output) comma-separated list of NH MPLS info | ||
| * @arg intf_list (output) comma-separated list of NH interfaces | ||
| * | ||
| * Return void | ||
| */ | ||
| void RouteSync::getNextHopList(struct rtnl_route *route_obj, string& gw_list, | ||
| string& mpls_list, string& intf_list) | ||
| { | ||
| bool mpls_found = false; | ||
|
|
||
| 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; | ||
|
|
||
| /* RTA_GATEWAY is NH gateway info for IP routes only */ | ||
| if ((addr = rtnl_route_nh_get_gateway(nexthop))) | ||
| { | ||
| char gw_ip[MAX_ADDR_SIZE + 1] = {0}; | ||
| nl_addr2str(addr, gw_ip, MAX_ADDR_SIZE); | ||
| gw_list += gw_ip; | ||
|
|
||
| /* LWTUNNEL_ENCAP_MPLS RTA_DST is MPLS NH label stack for IP routes only */ | ||
| if ((addr = rtnl_route_nh_get_encap_mpls_dst(nexthop))) | ||
| { | ||
| char labelstack[MAX_ADDR_SIZE + 1] = {0}; | ||
| nl_addr2str(addr, labelstack, MAX_ADDR_SIZE); | ||
| mpls_list += string("push"); | ||
| mpls_list += labelstack; | ||
| mpls_found = true; | ||
| } | ||
| /* Filler for proper parsing in routeorch */ | ||
| else | ||
| { | ||
| mpls_list += string("na"); | ||
| } | ||
| } | ||
| /* RTA_VIA is NH gateway info for MPLS routes only */ | ||
| else if ((addr = rtnl_route_nh_get_via(nexthop))) | ||
| { | ||
| char gw_ip[MAX_ADDR_SIZE + 1] = {0}; | ||
| nl_addr2str(addr, gw_ip, MAX_ADDR_SIZE); | ||
| gw_list += gw_ip; | ||
|
|
||
| /* RTA_NEWDST is MPLS NH label stack for MPLS routes only */ | ||
| if ((addr = rtnl_route_nh_get_newdst(nexthop))) | ||
| { | ||
| char labelstack[MAX_ADDR_SIZE + 1] = {0}; | ||
| nl_addr2str(addr, labelstack, MAX_ADDR_SIZE); | ||
| mpls_list += string("swap"); | ||
| mpls_list += labelstack; | ||
| mpls_found = true; | ||
| } | ||
| /* Filler for proper parsing in routeorch */ | ||
| else | ||
| { | ||
| mpls_list += string("na"); | ||
| } | ||
| } | ||
| else | ||
| { | ||
| if (rtnl_route_get_family(route_obj) == AF_INET6) | ||
| { | ||
| gw_list += "::"; | ||
| } | ||
| /* for MPLS route, use IPv4 as default gateway. */ | ||
| else | ||
| { | ||
| gw_list += "0.0.0.0"; | ||
| } | ||
| mpls_list += string("na"); | ||
| } | ||
|
|
||
| /* Get the ID of next hop interface */ | ||
| unsigned if_index = rtnl_route_nh_get_ifindex(nexthop); | ||
| char if_name[IFNAMSIZ] = "0"; | ||
| if (getIfName(if_index, if_name, IFNAMSIZ)) | ||
| { | ||
| intf_list += if_name; | ||
| } | ||
| /* If we cannot get the interface name */ | ||
| else | ||
| { | ||
| intf_list += "unknown"; | ||
| } | ||
|
|
||
| if (i + 1 < rtnl_route_get_nnexthops(route_obj)) | ||
| { | ||
| gw_list += NHG_DELIMITER; | ||
| mpls_list += NHG_DELIMITER; | ||
| intf_list += NHG_DELIMITER; | ||
| } | ||
| } | ||
|
|
||
| if (!mpls_found) | ||
| { | ||
| mpls_list.clear(); | ||
| } | ||
| } | ||
|
|
||
| /* | ||
| * Get next hop gateway IP addresses | ||
| * @arg route_obj route object | ||
|
|
@@ -938,7 +1163,7 @@ string RouteSync::getNextHopGw(struct rtnl_route *route_obj) | |
|
|
||
| if (i + 1 < rtnl_route_get_nnexthops(route_obj)) | ||
| { | ||
| result += string(","); | ||
| result += NHG_DELIMITER; | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -972,7 +1197,7 @@ string RouteSync::getNextHopIf(struct rtnl_route *route_obj) | |
|
|
||
| if (i + 1 < rtnl_route_get_nnexthops(route_obj)) | ||
| { | ||
| result += string(","); | ||
| result += NHG_DELIMITER; | ||
| } | ||
| } | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How did you find out non-zero value implies a VRF table. "254" is the main table that ip route installs, 255 and 253 are local and default route table. All these are non-VRF tables.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@smahesh You do know that SONiC has modified the fpm netlink message content from frr to something non-standard, right? The rtnl_route_get_table() function will not return the RT_TABLE value in SONiC fpmsyncd, it returns the VRF ifindex value instead because SONiC has patched this.
https://github.com/Azure/sonic-buildimage/blob/master/src/sonic-frr/patch/0003-Use-vrf_id-for-vrf-not-tabled_id.patch
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for the info, no I wasn't aware.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@smaheshm Yes, this is the reason I have to disable VRF support in the other PR (#1765) where I provide the fpmsyncd runtime option to listen to kernel netlink instead of frr fpm. kernel netlink messages send the standard RT_TABLE ID in the netlink message, whereas frr fpm substitutes the patched VRF ifindex value.