Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 18 additions & 5 deletions .azure-pipelines/build-template.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,6 @@ jobs:
sudo apt-get install -y libzmq5 libzmq3-dev
sudo apt-get install -qq -y \
libhiredis-dev \
libnl-3-dev \
libnl-genl-3-dev \
libnl-route-3-dev \
libnl-nf-3-dev \
swig3.0
sudo apt-get install -y libdbus-1-3
sudo apt-get install -y libteam-dev \
Expand All @@ -83,6 +79,23 @@ jobs:
runBranch: 'refs/heads/master'
displayName: "Download sonic sairedis deb packages"
- script: |
git clone https://github.com/Azure/sonic-buildimage sonic-buildimage.libnl3; pushd sonic-buildimage.libnl3/src/libnl3
git clone https://github.com/thom311/libnl libnl3-3.5.0; pushd libnl3-3.5.0; git checkout tags/libnl3_5_0
git apply ../patch/0001-mpls-encap-accessors.patch
git apply ../patch/0002-mpls-remove-nl_addr_valid.patch
ln -s ../debian debian
fakeroot dpkg-buildpackage -us -uc -b -j$(nproc)
popd; popd
displayName: "Compile libnl3"
- script: |
sudo dpkg -i s/sonic-buildimage.libnl3/src/libnl3/libnl-3-200_*.deb
sudo dpkg -i s/sonic-buildimage.libnl3/src/libnl3/libnl-3-dev_*.deb
sudo dpkg -i s/sonic-buildimage.libnl3/src/libnl3/libnl-genl-3-200_*.deb
sudo dpkg -i s/sonic-buildimage.libnl3/src/libnl3/libnl-genl-3-dev_*.deb
sudo dpkg -i s/sonic-buildimage.libnl3/src/libnl3/libnl-route-3-200_*.deb
sudo dpkg -i s/sonic-buildimage.libnl3/src/libnl3/libnl-route-3-dev_*.deb
sudo dpkg -i s/sonic-buildimage.libnl3/src/libnl3/libnl-nf-3-200_*.deb
sudo dpkg -i s/sonic-buildimage.libnl3/src/libnl3/libnl-nf-3-dev_*.deb
sudo dpkg -i ${{ parameters.swss_common_artifact_name }}/libswsscommon_1.0.0_${{ parameters.arch }}.deb
sudo dpkg -i ${{ parameters.swss_common_artifact_name }}/libswsscommon-dev_1.0.0_${{ parameters.arch }}.deb
sudo dpkg -i ${{ parameters.sairedis_artifact_name }}/libsaivs_*.deb
Expand All @@ -93,7 +106,7 @@ jobs:
sudo dpkg -i ${{ parameters.sairedis_artifact_name }}/libsaimetadata-dev_*.deb
sudo dpkg -i ${{ parameters.sairedis_artifact_name }}/syncd-vs_*.deb
workingDirectory: $(Pipeline.Workspace)
displayName: "Install sonic swss common and sairedis"
displayName: "Install libnl3, sonic swss common and sairedis"
- checkout: self
submodules: true
- script: |
Expand Down
248 changes: 230 additions & 18 deletions fpmsyncd/routesync.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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"),
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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)
{
/*
Expand All @@ -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);
Expand All @@ -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());
}

/*
Expand All @@ -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,
Expand All @@ -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
Expand Down Expand Up @@ -902,6 +1010,110 @@ bool RouteSync::getIfName(int if_index, char *if_name, size_t name_len)
return true;
}

/*
* 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
Expand Down Expand Up @@ -938,7 +1150,7 @@ string RouteSync::getNextHopGw(struct rtnl_route *route_obj)

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

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

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

Expand Down
Loading