diff --git a/fpmsyncd/fpmsyncd.cpp b/fpmsyncd/fpmsyncd.cpp index 8f797e178c..1ad163e5bf 100644 --- a/fpmsyncd/fpmsyncd.cpp +++ b/fpmsyncd/fpmsyncd.cpp @@ -1,3 +1,4 @@ +#include #include #include #include "logger.h" @@ -7,6 +8,7 @@ #include "warmRestartHelper.h" #include "fpmsyncd/fpmlink.h" #include "fpmsyncd/routesync.h" +#include "netlink.h" using namespace std; @@ -44,12 +46,54 @@ static bool eoiuFlagsSet(Table &bgpStateTable) return true; } +static void usage() +{ + cout << "Usage: fpmsyncd [ -l ( fpm | net) ]" << endl; + cout << " fpm = FpmLink (default)" << endl; + cout << " net = NetLink" << endl; +} + int main(int argc, char **argv) { + bool useFpmLink = true; + int opt; + while ((opt = getopt(argc, argv, "l:h")) != -1 ) + { + switch (opt) + { + case 'l': + { + string linkmode(optarg); + if (linkmode == "net") + { + useFpmLink = false; + } + else if (linkmode == "fpm") + { + useFpmLink = true; + } + else + { + usage(); + return EXIT_FAILURE; + } + break; + } + + case 'h': + usage(); + return 1; + + default: /* '?' */ + usage(); + return EXIT_FAILURE; + } + } + swss::Logger::linkToDbNative("fpmsyncd"); DBConnector db("APPL_DB", 0); RedisPipeline pipeline(&db); - RouteSync sync(&pipeline); + RouteSync sync(&pipeline, useFpmLink); DBConnector stateDb("STATE_DB", 0); Table bgpStateTable(&stateDb, STATE_BGP_TABLE_NAME); @@ -61,7 +105,6 @@ int main(int argc, char **argv) { try { - FpmLink fpm(&sync); Select s; SelectableTimer warmStartTimer(timespec{0, 0}); // Before eoiu flags detected, check them periodically. It also stop upon detection of reconciliation done. @@ -75,11 +118,30 @@ int main(int argc, char **argv) */ pipeline.flush(); - cout << "Waiting for fpm-client connection..." << endl; - fpm.accept(); - cout << "Connected!" << endl; + shared_ptr link; + if (useFpmLink) + { + shared_ptr fpm = make_shared(&sync); + + cout << "Waiting for fpm-client connection..." << endl; + fpm->accept(); + cout << "Connected!" << endl; - s.addSelectable(&fpm); + link = fpm; + } + else + { + shared_ptr netlink = make_shared(); + + netlink->registerGroup(RTNLGRP_IPV4_ROUTE); + netlink->registerGroup(RTNLGRP_IPV6_ROUTE); + netlink->registerGroup(RTNLGRP_MPLS_ROUTE); + cout << "NetLink listening for route messages..." << endl; + netlink->dumpRequest(RTM_GETROUTE); + + link = netlink; + } + s.addSelectable(link.get()); /* If warm-restart feature is enabled, execute 'restoration' logic */ bool warmStartEnabled = sync.m_warmStartHelper.checkAndStart(); diff --git a/fpmsyncd/routesync.cpp b/fpmsyncd/routesync.cpp index 9910dca07e..ce7412add8 100644 --- a/fpmsyncd/routesync.cpp +++ b/fpmsyncd/routesync.cpp @@ -42,12 +42,13 @@ using namespace swss; #define ETHER_ADDR_STRLEN (3*ETH_ALEN) -RouteSync::RouteSync(RedisPipeline *pipeline) : +RouteSync::RouteSync(RedisPipeline *pipeline, bool useFpmLink) : m_routeTable(pipeline, APP_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"), - m_nl_sock(NULL), m_link_cache(NULL) + m_nl_sock(NULL), m_link_cache(NULL), + m_usingFpmLink(useFpmLink) { m_nl_sock = nl_socket_alloc(); nl_connect(m_nl_sock, NETLINK_ROUTE); @@ -582,7 +583,9 @@ void RouteSync::onMsg(int nlmsg_type, struct nl_object *obj) char master_name[IFNAMSIZ] = {0}; /* if the table_id is not set in the route obj then route is for default vrf. */ - if (master_index) + /* Linux Netlink connection does not substitute VRF ifindex for RTTABLE_ID + * so VRF not supported in Linux NetLink mode */ + if (m_usingFpmLink && master_index) { /* Get the name of the master device */ getIfName(master_index, master_name, IFNAMSIZ); @@ -598,7 +601,6 @@ void RouteSync::onMsg(int nlmsg_type, struct nl_object *obj) { onRouteMsg(nlmsg_type, obj, master_name); } - } else { diff --git a/fpmsyncd/routesync.h b/fpmsyncd/routesync.h index 71a20f9d66..ebf48b11fd 100644 --- a/fpmsyncd/routesync.h +++ b/fpmsyncd/routesync.h @@ -21,7 +21,7 @@ class RouteSync : public NetMsg public: enum { MAX_ADDR_SIZE = 64 }; - RouteSync(RedisPipeline *pipeline); + RouteSync(RedisPipeline *pipeline, bool usingFpmLink); virtual void onMsg(int nlmsg_type, struct nl_object *obj); @@ -37,6 +37,7 @@ class RouteSync : public NetMsg ProducerStateTable m_vnet_tunnelTable; struct nl_cache *m_link_cache; struct nl_sock *m_nl_sock; + bool m_usingFpmLink; /* Handle regular route (include VRF route) */ void onRouteMsg(int nlmsg_type, struct nl_object *obj, char *vrf);