Skip to content
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

[fpmsyncd] Add support for SRv6 #2515

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
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
871 changes: 870 additions & 1 deletion fpmsyncd/routesync.cpp

Large diffs are not rendered by default.

35 changes: 34 additions & 1 deletion fpmsyncd/routesync.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,9 @@ class RouteSync : public NetMsg
/* vnet route table */
ProducerStateTable m_vnet_routeTable;
/* vnet vxlan tunnel table */
ProducerStateTable m_vnet_tunnelTable;
ProducerStateTable m_vnet_tunnelTable;
/* srv6 local sid table */
ProducerStateTable m_srv6LocalSidTable;
struct nl_cache *m_link_cache;
struct nl_sock *m_nl_sock;

Expand All @@ -89,6 +91,17 @@ class RouteSync : public NetMsg

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

void parseEncapSrv6SteerRoute(struct rtattr *tb, string &vpn_sid, string &src_addr);

void parseEncapSrv6LocalSid(struct rtattr *tb, string &block_len,
string &node_len, string &func_len,
string &arg_len, string &action, string &vrf,
string &adj);

void parseEncapSrv6LocalSidFormat(struct rtattr *tb, string &block_len,
string &node_len, string &func_len,
string &arg_len);

void parseRtAttrNested(struct rtattr **tb, int max,
struct rtattr *rta);

Expand All @@ -98,6 +111,12 @@ class RouteSync : public NetMsg
/* Handle prefix route */
void onEvpnRouteMsg(struct nlmsghdr *h, int len);

/* Handle routes containing an SRv6 nexthop */
void onSrv6SteerRouteMsg(struct nlmsghdr *h, int len);

/* Handle routes containing an SRv6 Local SID nexthop */
void onSrv6LocalSidMsg(struct nlmsghdr *h, int len);

/* Handle vnet route */
void onVnetRouteMsg(int nlmsg_type, struct nl_object *obj, string vnet);

Expand All @@ -119,6 +138,15 @@ class RouteSync : public NetMsg
string& nexthops, string& vni_list, string& mac_list,
string& intf_list);

bool getSrv6SteerRouteNextHop(struct nlmsghdr *h, int received_bytes,
struct rtattr *tb[], string &vpn_sid, string &src_addr);

bool getSrv6LocalSidNextHop(struct nlmsghdr *h, int received_bytes,
struct rtattr *tb[], string &block_len,
string &node_len, string &func_len,
string &arg_len, string &act, string &vrf,
string &adj);

/* Get next hop list */
void getNextHopList(struct rtnl_route *route_obj, string& gw_list,
string& mpls_list, string& intf_list);
Expand All @@ -140,6 +168,11 @@ class RouteSync : public NetMsg

/* Sends FPM message with RTM_F_OFFLOAD flag set for all routes in the table */
void sendOffloadReply(swss::DBConnector& db, const std::string& table);

/* Get encap type */
uint16_t getEncapType(struct nlmsghdr *h);

const char *localSidAction2Str(uint32_t action);
};

}
Expand Down
1 change: 1 addition & 0 deletions tests/mock_tests/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
tests
tests_fpmsyncd
8 changes: 6 additions & 2 deletions tests/mock_tests/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -179,17 +179,21 @@ tests_intfmgrd_LDADD = $(LDADD_GTEST) $(LDADD_SAI) -lnl-genl-3 -lhiredis -lhired

tests_fpmsyncd_SOURCES = fpmsyncd/test_fpmlink.cpp \
fpmsyncd/test_routesync.cpp \
fpmsyncd/receive_srv6_steer_routes_ut.cpp \
fpmsyncd/receive_srv6_localsids_ut.cpp \
fpmsyncd/ut_helpers_fpmsyncd.cpp \
fake_netlink.cpp \
fake_warmstarthelper.cpp \
fake_producerstatetable.cpp \
mock_dbconnector.cpp \
mock_table.cpp \
mock_hiredis.cpp \
mock_redisreply.cpp \
$(top_srcdir)/warmrestart/ \
$(top_srcdir)/fpmsyncd/fpmlink.cpp \
$(top_srcdir)/fpmsyncd/routesync.cpp

tests_fpmsyncd_INCLUDES = $(tests_INCLUDES) -I$(top_srcdir)/tests_fpmsyncd -I$(top_srcdir)/lib -I$(top_srcdir)/warmrestart
tests_fpmsyncd_INCLUDES = $(tests_INCLUDES) -I$(top_srcdir)/tests_fpmsyncd -I$(top_srcdir)/lib -I$(top_srcdir)/warmrestart -I$(top_srcdir)/fpmsyncd
tests_fpmsyncd_CXXFLAGS = -Wl,-wrap,rtnl_link_i2name
tests_fpmsyncd_CFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_GTEST) $(CFLAGS_SAI)
tests_fpmsyncd_CPPFLAGS = $(DBGFLAGS) $(AM_CFLAGS) $(CFLAGS_COMMON) $(CFLAGS_GTEST) $(CFLAGS_SAI) $(tests_fpmsyncd_INCLUDES)
tests_fpmsyncd_LDADD = $(LDADD_GTEST) $(LDADD_SAI) -lnl-genl-3 -lhiredis -lhiredis \
Expand Down
261 changes: 261 additions & 0 deletions tests/mock_tests/fpmsyncd/receive_srv6_localsids_ut.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
#include "ut_helpers_fpmsyncd.h"
#include "gtest/gtest.h"
#include <gmock/gmock.h>
#include "mock_table.h"
#include <net/if.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include "ipaddress.h"

#define private public // Need to modify internal cache
#include "fpmlink.h"
#include "routesync.h"
#undef private

using namespace swss;
using namespace testing;

/*
Test Fixture
*/
namespace ut_fpmsyncd
{
struct FpmSyncdSRv6LocalSIDsTest : public ::testing::Test
{
std::shared_ptr<swss::DBConnector> m_app_db;
std::shared_ptr<swss::RedisPipeline> pipeline;
std::shared_ptr<RouteSync> m_routeSync;
std::shared_ptr<FpmLink> m_fpmLink;
std::shared_ptr<swss::Table> m_srv6LocalSidTable;

virtual void SetUp() override
{
testing_db::reset();

m_app_db = std::make_shared<swss::DBConnector>("APPL_DB", 0);

/* Construct dependencies */

/* 1) RouteSync */
pipeline = std::make_shared<swss::RedisPipeline>(m_app_db.get());
m_routeSync = std::make_shared<RouteSync>(pipeline.get());

/* 2) FpmLink */
m_fpmLink = std::make_shared<FpmLink>(m_routeSync.get());

/* 3) SRV6_MY_SID_TABLE in APP_DB */
m_srv6LocalSidTable = std::make_shared<swss::Table>(m_app_db.get(), APP_SRV6_MY_SID_TABLE_NAME);
}

virtual void TearDown() override
{
}
};
}

namespace ut_fpmsyncd
{
/* Test Receiving a route containing an SRv6 Local SID nexthop bound to the End.DT4 behavior */
TEST_F(FpmSyncdSRv6LocalSIDsTest, RecevingRouteWithSRv6LocalSIDEndDT4)
{
ASSERT_NE(m_routeSync, nullptr);

/* Create a Netlink object containing an SRv6 Local SID */
IpAddress _localsid = IpAddress("fc00:0:1:1::");
uint8_t _block_len = 32;
uint8_t _node_len = 16;
uint8_t _func_len = 16;
uint8_t _arg_len = 0;
uint32_t _action = SRV6_LOCALSID_ACTION_END_DT4;
char *_vrf = "Vrf10";

struct nlmsg *nl_obj = create_srv6_localsid_nlmsg(RTM_NEWROUTE, &_localsid, _block_len, _node_len, _func_len, _arg_len, _action, _vrf);
if (!nl_obj)
printf("Error\n\n");

/* Send the Netlink object to the FpmLink */
m_fpmLink->processRawMsg(&nl_obj->n);

/* Check that fpmsyncd created the correct entries in APP_DB */
std::string action;
ASSERT_EQ(m_srv6LocalSidTable->hget("32:16:16:0:fc00:0:1:1::", "action", action), true);
ASSERT_EQ(action, "end.dt4");

std::string vrf;
ASSERT_EQ(m_srv6LocalSidTable->hget("32:16:16:0:fc00:0:1:1::", "vrf", vrf), true);
ASSERT_EQ(vrf, "Vrf10");

/* Destroy the Netlink object and free the memory */
free_nlobj(nl_obj);
}

/* Test Receiving a route containing an SRv6 Local SID nexthop bound to the End.DT6 behavior */
TEST_F(FpmSyncdSRv6LocalSIDsTest, RecevingRouteWithSRv6LocalSIDEndDT6)
{
ASSERT_NE(m_routeSync, nullptr);

/* Create a Netlink object containing an SRv6 Local SID */
IpAddress _localsid = IpAddress("fc00:0:1:1::");
uint8_t _block_len = 32;
uint8_t _node_len = 16;
uint8_t _func_len = 16;
uint8_t _arg_len = 0;
uint32_t _action = SRV6_LOCALSID_ACTION_END_DT6;
char *_vrf = "Vrf10";

struct nlmsg *nl_obj = create_srv6_localsid_nlmsg(RTM_NEWROUTE, &_localsid, _block_len, _node_len, _func_len, _arg_len, _action, _vrf);
if (!nl_obj)
printf("Error\n\n");

/* Send the Netlink object to the FpmLink */
m_fpmLink->processRawMsg(&nl_obj->n);

/* Check that fpmsyncd created the correct entries in APP_DB */
std::string action;
ASSERT_EQ(m_srv6LocalSidTable->hget("32:16:16:0:fc00:0:1:1::", "action", action), true);
ASSERT_EQ(action, "end.dt6");

std::string vrf;
ASSERT_EQ(m_srv6LocalSidTable->hget("32:16:16:0:fc00:0:1:1::", "vrf", vrf), true);
ASSERT_EQ(vrf, "Vrf10");

/* Destroy the Netlink object and free the memory */
free_nlobj(nl_obj);
}

/* Test Receiving a route containing an SRv6 Local SID nexthop bound to the End.DT46 behavior */
TEST_F(FpmSyncdSRv6LocalSIDsTest, RecevingRouteWithSRv6LocalSIDEndDT46)
{
ASSERT_NE(m_routeSync, nullptr);

/* Create a Netlink object containing an SRv6 Local SID */
IpAddress _localsid = IpAddress("fc00:0:1:1::");
uint8_t _block_len = 32;
uint8_t _node_len = 16;
uint8_t _func_len = 16;
uint8_t _arg_len = 0;
uint32_t _action = SRV6_LOCALSID_ACTION_END_DT46;
char *_vrf = "Vrf10";

struct nlmsg *nl_obj = create_srv6_localsid_nlmsg(RTM_NEWROUTE, &_localsid, _block_len, _node_len, _func_len, _arg_len, _action, _vrf);
if (!nl_obj)
printf("Error\n\n");

/* Send the Netlink object to the FpmLink */
m_fpmLink->processRawMsg(&nl_obj->n);

/* Check that fpmsyncd created the correct entries in APP_DB */
std::string action;
ASSERT_EQ(m_srv6LocalSidTable->hget("32:16:16:0:fc00:0:1:1::", "action", action), true);
ASSERT_EQ(action, "end.dt46");

std::string vrf;
ASSERT_EQ(m_srv6LocalSidTable->hget("32:16:16:0:fc00:0:1:1::", "vrf", vrf), true);
ASSERT_EQ(vrf, "Vrf10");

/* Destroy the Netlink object and free the memory */
free_nlobj(nl_obj);
}

/* Test Receiving a route containing an SRv6 Local SID nexthop bound to the uDT4 behavior */
TEST_F(FpmSyncdSRv6LocalSIDsTest, RecevingRouteWithSRv6LocalSIDUDT4)
{
ASSERT_NE(m_routeSync, nullptr);

/* Create a Netlink object containing an SRv6 Local SID */
IpAddress _localsid = IpAddress("fc00:0:1:1::");
uint8_t _block_len = 32;
uint8_t _node_len = 16;
uint8_t _func_len = 16;
uint8_t _arg_len = 0;
uint32_t _action = SRV6_LOCALSID_ACTION_UDT4;
char *_vrf = "Vrf10";

struct nlmsg *nl_obj = create_srv6_localsid_nlmsg(RTM_NEWROUTE, &_localsid, _block_len, _node_len, _func_len, _arg_len, _action, _vrf);
if (!nl_obj)
printf("Error\n\n");

/* Send the Netlink object to the FpmLink */
m_fpmLink->processRawMsg(&nl_obj->n);

/* Check that fpmsyncd created the correct entries in APP_DB */
std::string action;
ASSERT_EQ(m_srv6LocalSidTable->hget("32:16:16:0:fc00:0:1:1::", "action", action), true);
ASSERT_EQ(action, "udt4");

std::string vrf;
ASSERT_EQ(m_srv6LocalSidTable->hget("32:16:16:0:fc00:0:1:1::", "vrf", vrf), true);
ASSERT_EQ(vrf, "Vrf10");

/* Destroy the Netlink object and free the memory */
free_nlobj(nl_obj);
}

/* Test Receiving a route containing an SRv6 Local SID nexthop bound to the uDT6 behavior */
TEST_F(FpmSyncdSRv6LocalSIDsTest, RecevingRouteWithSRv6LocalSIDUDT6)
{
ASSERT_NE(m_routeSync, nullptr);

/* Create a Netlink object containing an SRv6 Local SID */
IpAddress _localsid = IpAddress("fc00:0:1:1::");
uint8_t _block_len = 32;
uint8_t _node_len = 16;
uint8_t _func_len = 16;
uint8_t _arg_len = 0;
uint32_t _action = SRV6_LOCALSID_ACTION_UDT6;
char *_vrf = "Vrf10";

struct nlmsg *nl_obj = create_srv6_localsid_nlmsg(RTM_NEWROUTE, &_localsid, _block_len, _node_len, _func_len, _arg_len, _action, _vrf);
if (!nl_obj)
printf("Error\n\n");

/* Send the Netlink object to the FpmLink */
m_fpmLink->processRawMsg(&nl_obj->n);

/* Check that fpmsyncd created the correct entries in APP_DB */
std::string action;
ASSERT_EQ(m_srv6LocalSidTable->hget("32:16:16:0:fc00:0:1:1::", "action", action), true);
ASSERT_EQ(action, "udt6");

std::string vrf;
ASSERT_EQ(m_srv6LocalSidTable->hget("32:16:16:0:fc00:0:1:1::", "vrf", vrf), true);
ASSERT_EQ(vrf, "Vrf10");

/* Destroy the Netlink object and free the memory */
free_nlobj(nl_obj);
}

/* Test Receiving a route containing an SRv6 Local SID nexthop bound to the uDT46 behavior */
TEST_F(FpmSyncdSRv6LocalSIDsTest, RecevingRouteWithSRv6LocalSIDUDT46)
{
ASSERT_NE(m_routeSync, nullptr);

/* Create a Netlink object containing an SRv6 Local SID */
IpAddress _localsid = IpAddress("fc00:0:1:1::");
uint8_t _block_len = 32;
uint8_t _node_len = 16;
uint8_t _func_len = 16;
uint8_t _arg_len = 0;
uint32_t _action = SRV6_LOCALSID_ACTION_UDT46;
char *_vrf = "Vrf10";

struct nlmsg *nl_obj = create_srv6_localsid_nlmsg(RTM_NEWROUTE, &_localsid, _block_len, _node_len, _func_len, _arg_len, _action, _vrf);
if (!nl_obj)
printf("Error\n\n");

/* Send the Netlink object to the FpmLink */
m_fpmLink->processRawMsg(&nl_obj->n);

/* Check that fpmsyncd created the correct entries in APP_DB */
std::string action;
ASSERT_EQ(m_srv6LocalSidTable->hget("32:16:16:0:fc00:0:1:1::", "action", action), true);
ASSERT_EQ(action, "udt46");

std::string vrf;
ASSERT_EQ(m_srv6LocalSidTable->hget("32:16:16:0:fc00:0:1:1::", "vrf", vrf), true);
ASSERT_EQ(vrf, "Vrf10");

/* Destroy the Netlink object and free the memory */
free_nlobj(nl_obj);
}
}
Loading