Skip to content

Commit 4fbc740

Browse files
committed
[fpmsyncd] updates for MPLS plus AZP libnl3 rebuild
1 parent 63cca52 commit 4fbc740

File tree

4 files changed

+277
-24
lines changed

4 files changed

+277
-24
lines changed

.azure-pipelines/build-template.yml

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,6 @@ jobs:
5454
sudo apt-get install -y libzmq5 libzmq3-dev
5555
sudo apt-get install -qq -y \
5656
libhiredis-dev \
57-
libnl-3-dev \
58-
libnl-genl-3-dev \
59-
libnl-route-3-dev \
60-
libnl-nf-3-dev \
6157
swig3.0
6258
sudo apt-get install -y libdbus-1-3
6359
sudo apt-get install -y libteam-dev \
@@ -83,6 +79,23 @@ jobs:
8379
runBranch: 'refs/heads/master'
8480
displayName: "Download sonic sairedis deb packages"
8581
- script: |
82+
git clone https://github.com/Azure/sonic-buildimage sonic-buildimage.libnl3; pushd sonic-buildimage.libnl3/src/libnl3
83+
git clone https://github.com/thom311/libnl libnl3-3.5.0; pushd libnl3-3.5.0; git checkout tags/libnl3_5_0
84+
git apply ../patch/0001-mpls-encap-accessors.patch
85+
git apply ../patch/0002-mpls-remove-nl_addr_valid.patch
86+
ln -s ../debian debian
87+
fakeroot dpkg-buildpackage -us -uc -b -j$(nproc)
88+
popd; popd
89+
displayName: "Compile libnl3"
90+
- script: |
91+
sudo dpkg -i s/sonic-buildimage.libnl3/src/libnl3/libnl-3-200_*.deb
92+
sudo dpkg -i s/sonic-buildimage.libnl3/src/libnl3/libnl-3-dev_*.deb
93+
sudo dpkg -i s/sonic-buildimage.libnl3/src/libnl3/libnl-genl-3-200_*.deb
94+
sudo dpkg -i s/sonic-buildimage.libnl3/src/libnl3/libnl-genl-3-dev_*.deb
95+
sudo dpkg -i s/sonic-buildimage.libnl3/src/libnl3/libnl-route-3-200_*.deb
96+
sudo dpkg -i s/sonic-buildimage.libnl3/src/libnl3/libnl-route-3-dev_*.deb
97+
sudo dpkg -i s/sonic-buildimage.libnl3/src/libnl3/libnl-nf-3-200_*.deb
98+
sudo dpkg -i s/sonic-buildimage.libnl3/src/libnl3/libnl-nf-3-dev_*.deb
8699
sudo dpkg -i ${{ parameters.swss_common_artifact_name }}/libswsscommon_1.0.0_${{ parameters.arch }}.deb
87100
sudo dpkg -i ${{ parameters.swss_common_artifact_name }}/libswsscommon-dev_1.0.0_${{ parameters.arch }}.deb
88101
sudo dpkg -i ${{ parameters.sairedis_artifact_name }}/libsaivs_*.deb
@@ -93,7 +106,7 @@ jobs:
93106
sudo dpkg -i ${{ parameters.sairedis_artifact_name }}/libsaimetadata-dev_*.deb
94107
sudo dpkg -i ${{ parameters.sairedis_artifact_name }}/syncd-vs_*.deb
95108
workingDirectory: $(Pipeline.Workspace)
96-
displayName: "Install sonic swss common and sairedis"
109+
displayName: "Install libnl3, sonic swss common and sairedis"
97110
- checkout: self
98111
submodules: true
99112
- script: |

fpmsyncd/routesync.cpp

Lines changed: 230 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ using namespace swss;
2121
#define VRF_PREFIX "Vrf"
2222
#define MGMT_VRF_PREFIX "mgmt"
2323

24+
#define NHG_DELIMITER ','
25+
2426
#ifndef ETH_ALEN
2527
#define ETH_ALEN 6
2628
#endif
@@ -44,6 +46,7 @@ using namespace swss;
4446

4547
RouteSync::RouteSync(RedisPipeline *pipeline) :
4648
m_routeTable(pipeline, APP_ROUTE_TABLE_NAME, true),
49+
m_label_routeTable(pipeline, APP_LABEL_ROUTE_TABLE_NAME, true),
4750
m_vnet_routeTable(pipeline, APP_VNET_RT_TABLE_NAME, true),
4851
m_vnet_tunnelTable(pipeline, APP_VNET_RT_TUNNEL_TABLE_NAME, true),
4952
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
113116
void RouteSync::getEvpnNextHopSep(string& nexthops, string& vni_list,
114117
string& mac_list, string& intf_list)
115118
{
116-
nexthops += string(",");
117-
vni_list += string(",");
118-
mac_list += string(",");
119-
intf_list += string(",");
119+
nexthops += NHG_DELIMITER;
120+
vni_list += NHG_DELIMITER;
121+
mac_list += NHG_DELIMITER;
122+
intf_list += NHG_DELIMITER;
120123

121124
return;
122125
}
@@ -571,6 +574,12 @@ void RouteSync::onMsg(int nlmsg_type, struct nl_object *obj)
571574

572575
/* Supports IPv4 or IPv6 address, otherwise return immediately */
573576
auto family = rtnl_route_get_family(route_obj);
577+
/* Check for Label route. */
578+
if (family == AF_MPLS)
579+
{
580+
onLabelRouteMsg(nlmsg_type, obj);
581+
return;
582+
}
574583
if (family != AF_INET && family != AF_INET6)
575584
{
576585
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)
708717
}
709718

710719
/* Get nexthop lists */
711-
string nexthops = getNextHopGw(route_obj);
712-
string ifnames = getNextHopIf(route_obj);
720+
string gw_list;
721+
string intf_list;
722+
string mpls_list;
723+
getNextHopList(route_obj, gw_list, mpls_list, intf_list);
713724
string weights = getNextHopWt(route_obj);
714725

715-
vector<string> alsv = tokenize(ifnames, ',');
726+
vector<string> alsv = tokenize(intf_list, NHG_DELIMITER);
716727
for (auto alias : alsv)
717728
{
718729
/*
@@ -722,17 +733,22 @@ void RouteSync::onRouteMsg(int nlmsg_type, struct nl_object *obj, char *vrf)
722733
if (alias == "eth0" || alias == "docker0")
723734
{
724735
SWSS_LOG_DEBUG("Skip routes to eth0 or docker0: %s %s %s",
725-
destipprefix, nexthops.c_str(), ifnames.c_str());
736+
destipprefix, gw_list.c_str(), intf_list.c_str());
726737
return;
727738
}
728739
}
729740

730741
vector<FieldValueTuple> fvVector;
731-
FieldValueTuple nh("nexthop", nexthops);
732-
FieldValueTuple idx("ifname", ifnames);
742+
FieldValueTuple gw("nexthop", gw_list);
743+
FieldValueTuple intf("ifname", intf_list);
733744

734-
fvVector.push_back(nh);
735-
fvVector.push_back(idx);
745+
fvVector.push_back(gw);
746+
fvVector.push_back(intf);
747+
if (!mpls_list.empty())
748+
{
749+
FieldValueTuple mpls_nh("mpls_nh", mpls_list);
750+
fvVector.push_back(mpls_nh);
751+
}
736752
if (!weights.empty())
737753
{
738754
FieldValueTuple wt("weight", weights);
@@ -742,8 +758,8 @@ void RouteSync::onRouteMsg(int nlmsg_type, struct nl_object *obj, char *vrf)
742758
if (!warmRestartInProgress)
743759
{
744760
m_routeTable.set(destipprefix, fvVector);
745-
SWSS_LOG_DEBUG("RouteTable set msg: %s %s %s",
746-
destipprefix, nexthops.c_str(), ifnames.c_str());
761+
SWSS_LOG_DEBUG("RouteTable set msg: %s %s %s %s", destipprefix,
762+
gw_list.c_str(), intf_list.c_str(), mpls_list.c_str());
747763
}
748764

749765
/*
@@ -752,8 +768,8 @@ void RouteSync::onRouteMsg(int nlmsg_type, struct nl_object *obj, char *vrf)
752768
*/
753769
else
754770
{
755-
SWSS_LOG_INFO("Warm-Restart mode: RouteTable set msg: %s %s %s",
756-
destipprefix, nexthops.c_str(), ifnames.c_str());
771+
SWSS_LOG_INFO("Warm-Restart mode: RouteTable set msg: %s %s %s %s", destipprefix,
772+
gw_list.c_str(), intf_list.c_str(), mpls_list.c_str());
757773

758774
const KeyOpFieldsValuesTuple kfv = std::make_tuple(destipprefix,
759775
SET_COMMAND,
@@ -763,6 +779,98 @@ void RouteSync::onRouteMsg(int nlmsg_type, struct nl_object *obj, char *vrf)
763779
}
764780

765781
/*
782+
* Handle label route
783+
* @arg nlmsg_type Netlink message type
784+
* @arg obj Netlink object
785+
*/
786+
void RouteSync::onLabelRouteMsg(int nlmsg_type, struct nl_object *obj)
787+
{
788+
struct rtnl_route *route_obj = (struct rtnl_route *)obj;
789+
struct nl_addr *daddr;
790+
char destaddr[MAX_ADDR_SIZE + 1] = {0};
791+
792+
daddr = rtnl_route_get_dst(route_obj);
793+
nl_addr2str(daddr, destaddr, MAX_ADDR_SIZE);
794+
SWSS_LOG_INFO("Receive new LabelRoute message dest addr: %s", destaddr);
795+
if (nl_addr_iszero(daddr)) return;
796+
797+
if (nlmsg_type == RTM_DELROUTE)
798+
{
799+
m_label_routeTable.del(destaddr);
800+
return;
801+
}
802+
else if (nlmsg_type != RTM_NEWROUTE)
803+
{
804+
SWSS_LOG_INFO("Unknown message-type: %d for LabelRoute %s", nlmsg_type, destaddr);
805+
return;
806+
}
807+
808+
/* Get the index of the master device */
809+
uint32_t master_index = rtnl_route_get_table(route_obj);
810+
/* if the table_id is not set in the route obj then route is for default vrf. */
811+
if (master_index)
812+
{
813+
SWSS_LOG_INFO("Unsupported Non-default VRF: %d for LabelRoute %s",
814+
master_index, destaddr);
815+
return;
816+
}
817+
818+
switch (rtnl_route_get_type(route_obj))
819+
{
820+
case RTN_BLACKHOLE:
821+
{
822+
vector<FieldValueTuple> fvVector;
823+
FieldValueTuple fv("blackhole", "true");
824+
fvVector.push_back(fv);
825+
m_label_routeTable.set(destaddr, fvVector);
826+
return;
827+
}
828+
case RTN_UNICAST:
829+
break;
830+
831+
case RTN_MULTICAST:
832+
case RTN_BROADCAST:
833+
case RTN_LOCAL:
834+
SWSS_LOG_INFO("BUM routes aren't supported yet (%s)", destaddr);
835+
return;
836+
837+
default:
838+
return;
839+
}
840+
841+
struct nl_list_head *nhs = rtnl_route_get_nexthops(route_obj);
842+
if (!nhs)
843+
{
844+
SWSS_LOG_INFO("Nexthop list is empty for LabelRoute %s", destaddr);
845+
return;
846+
}
847+
848+
/* Get nexthop lists */
849+
string gw_list;
850+
string intf_list;
851+
string mpls_list;
852+
getNextHopList(route_obj, gw_list, mpls_list, intf_list);
853+
854+
vector<FieldValueTuple> fvVector;
855+
FieldValueTuple gw("nexthop", gw_list);
856+
FieldValueTuple intf("ifname", intf_list);
857+
FieldValueTuple mpls_pop("mpls_pop", "1");
858+
859+
fvVector.push_back(gw);
860+
fvVector.push_back(intf);
861+
if (!mpls_list.empty())
862+
{
863+
FieldValueTuple mpls_nh("mpls_nh", mpls_list);
864+
fvVector.push_back(mpls_nh);
865+
}
866+
fvVector.push_back(mpls_pop);
867+
868+
m_label_routeTable.set(destaddr, fvVector);
869+
SWSS_LOG_INFO("LabelRouteTable set msg: %s %s %s %s", destaddr,
870+
gw_list.c_str(), intf_list.c_str(), mpls_list.c_str());
871+
}
872+
873+
/*
766874
* Handle vnet route
767875
* @arg nlmsg_type Netlink message type
768876
* @arg obj Netlink object
@@ -902,6 +1010,110 @@ bool RouteSync::getIfName(int if_index, char *if_name, size_t name_len)
9021010
return true;
9031011
}
9041012

1013+
/*
1014+
* getNextHopList() - parses next hop list attached to route_obj
1015+
* @arg route_obj (input) Netlink route object
1016+
* @arg gw_list (output) comma-separated list of NH IP gateways
1017+
* @arg mpls_list (output) comma-separated list of NH MPLS info
1018+
* @arg intf_list (output) comma-separated list of NH interfaces
1019+
*
1020+
* Return void
1021+
*/
1022+
void RouteSync::getNextHopList(struct rtnl_route *route_obj, string& gw_list,
1023+
string& mpls_list, string& intf_list)
1024+
{
1025+
bool mpls_found = false;
1026+
1027+
for (int i = 0; i < rtnl_route_get_nnexthops(route_obj); i++)
1028+
{
1029+
struct rtnl_nexthop *nexthop = rtnl_route_nexthop_n(route_obj, i);
1030+
struct nl_addr *addr = NULL;
1031+
1032+
/* RTA_GATEWAY is NH gateway info for IP routes only */
1033+
if ((addr = rtnl_route_nh_get_gateway(nexthop)))
1034+
{
1035+
char gw_ip[MAX_ADDR_SIZE + 1] = {0};
1036+
nl_addr2str(addr, gw_ip, MAX_ADDR_SIZE);
1037+
gw_list += gw_ip;
1038+
1039+
/* LWTUNNEL_ENCAP_MPLS RTA_DST is MPLS NH label stack for IP routes only */
1040+
if ((addr = rtnl_route_nh_get_encap_mpls_dst(nexthop)))
1041+
{
1042+
char labelstack[MAX_ADDR_SIZE + 1] = {0};
1043+
nl_addr2str(addr, labelstack, MAX_ADDR_SIZE);
1044+
mpls_list += string("push");
1045+
mpls_list += labelstack;
1046+
mpls_found = true;
1047+
}
1048+
/* Filler for proper parsing in routeorch */
1049+
else
1050+
{
1051+
mpls_list += string("na");
1052+
}
1053+
}
1054+
/* RTA_VIA is NH gateway info for MPLS routes only */
1055+
else if ((addr = rtnl_route_nh_get_via(nexthop)))
1056+
{
1057+
char gw_ip[MAX_ADDR_SIZE + 1] = {0};
1058+
nl_addr2str(addr, gw_ip, MAX_ADDR_SIZE);
1059+
gw_list += gw_ip;
1060+
1061+
/* RTA_NEWDST is MPLS NH label stack for MPLS routes only */
1062+
if ((addr = rtnl_route_nh_get_newdst(nexthop)))
1063+
{
1064+
char labelstack[MAX_ADDR_SIZE + 1] = {0};
1065+
nl_addr2str(addr, labelstack, MAX_ADDR_SIZE);
1066+
mpls_list += string("swap");
1067+
mpls_list += labelstack;
1068+
mpls_found = true;
1069+
}
1070+
/* Filler for proper parsing in routeorch */
1071+
else
1072+
{
1073+
mpls_list += string("na");
1074+
}
1075+
}
1076+
else
1077+
{
1078+
if (rtnl_route_get_family(route_obj) == AF_INET6)
1079+
{
1080+
gw_list += "::";
1081+
}
1082+
/* for MPLS route, use IPv4 as default gateway. */
1083+
else
1084+
{
1085+
gw_list += "0.0.0.0";
1086+
}
1087+
mpls_list += string("na");
1088+
}
1089+
1090+
/* Get the ID of next hop interface */
1091+
unsigned if_index = rtnl_route_nh_get_ifindex(nexthop);
1092+
char if_name[IFNAMSIZ] = "0";
1093+
if (getIfName(if_index, if_name, IFNAMSIZ))
1094+
{
1095+
intf_list += if_name;
1096+
}
1097+
/* If we cannot get the interface name */
1098+
else
1099+
{
1100+
intf_list += "unknown";
1101+
}
1102+
1103+
if (i + 1 < rtnl_route_get_nnexthops(route_obj))
1104+
{
1105+
gw_list += NHG_DELIMITER;
1106+
mpls_list += NHG_DELIMITER;
1107+
intf_list += NHG_DELIMITER;
1108+
}
1109+
}
1110+
1111+
if (!mpls_found)
1112+
{
1113+
mpls_list.clear();
1114+
}
1115+
}
1116+
9051117
/*
9061118
* Get next hop gateway IP addresses
9071119
* @arg route_obj route object
@@ -938,7 +1150,7 @@ string RouteSync::getNextHopGw(struct rtnl_route *route_obj)
9381150

9391151
if (i + 1 < rtnl_route_get_nnexthops(route_obj))
9401152
{
941-
result += string(",");
1153+
result += NHG_DELIMITER;
9421154
}
9431155
}
9441156

@@ -972,7 +1184,7 @@ string RouteSync::getNextHopIf(struct rtnl_route *route_obj)
9721184

9731185
if (i + 1 < rtnl_route_get_nnexthops(route_obj))
9741186
{
975-
result += string(",");
1187+
result += NHG_DELIMITER;
9761188
}
9771189
}
9781190

0 commit comments

Comments
 (0)