Skip to content

Commit 582beae

Browse files
[FPMSYNCD] EVPN Type5 prefix handling in FPMSYNCD (#1326)
EVPN Type5 prefix handling in FPMSYNCD. Add raw netlink msg processing for EVPN routes since rt_nl doesn't provide support to extract custom msg from the netlink msg.
1 parent d9ca6e2 commit 582beae

File tree

5 files changed

+656
-8
lines changed

5 files changed

+656
-8
lines changed

fpmsyncd/fpmlink.cpp

+118-4
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,104 @@
99
using namespace swss;
1010
using namespace std;
1111

12-
FpmLink::FpmLink(unsigned short port) :
12+
void netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta,
13+
int len)
14+
{
15+
while (RTA_OK(rta, len))
16+
{
17+
if (rta->rta_type <= max)
18+
{
19+
tb[rta->rta_type] = rta;
20+
}
21+
rta = RTA_NEXT(rta, len);
22+
}
23+
}
24+
25+
bool FpmLink::isRawProcessing(struct nlmsghdr *h)
26+
{
27+
int len;
28+
short encap_type = 0;
29+
struct rtmsg *rtm;
30+
struct rtattr *tb[RTA_MAX + 1];
31+
32+
rtm = (struct rtmsg *)NLMSG_DATA(h);
33+
34+
if (h->nlmsg_type != RTM_NEWROUTE && h->nlmsg_type != RTM_DELROUTE)
35+
{
36+
return false;
37+
}
38+
39+
len = (int)(h->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg)));
40+
if (len < 0)
41+
{
42+
return false;
43+
}
44+
45+
memset(tb, 0, sizeof(tb));
46+
netlink_parse_rtattr(tb, RTA_MAX, RTM_RTA(rtm), len);
47+
48+
if (!tb[RTA_MULTIPATH])
49+
{
50+
if (tb[RTA_ENCAP_TYPE])
51+
{
52+
encap_type = *(short *)RTA_DATA(tb[RTA_ENCAP_TYPE]);
53+
}
54+
}
55+
else
56+
{
57+
/* This is a multipath route */
58+
int len;
59+
struct rtnexthop *rtnh = (struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]);
60+
len = (int)RTA_PAYLOAD(tb[RTA_MULTIPATH]);
61+
struct rtattr *subtb[RTA_MAX + 1];
62+
63+
for (;;)
64+
{
65+
if (len < (int)sizeof(*rtnh) || rtnh->rtnh_len > len)
66+
{
67+
break;
68+
}
69+
70+
if (rtnh->rtnh_len > sizeof(*rtnh))
71+
{
72+
memset(subtb, 0, sizeof(subtb));
73+
netlink_parse_rtattr(subtb, RTA_MAX, RTNH_DATA(rtnh),
74+
(int)(rtnh->rtnh_len - sizeof(*rtnh)));
75+
if (subtb[RTA_ENCAP_TYPE])
76+
{
77+
encap_type = *(uint16_t *)RTA_DATA(subtb[RTA_ENCAP_TYPE]);
78+
break;
79+
}
80+
}
81+
82+
if (rtnh->rtnh_len == 0)
83+
{
84+
break;
85+
}
86+
87+
len -= NLMSG_ALIGN(rtnh->rtnh_len);
88+
rtnh = RTNH_NEXT(rtnh);
89+
}
90+
}
91+
92+
SWSS_LOG_INFO("Rx MsgType:%d Encap:%d", h->nlmsg_type, encap_type);
93+
94+
if (encap_type > 0)
95+
{
96+
return true;
97+
}
98+
99+
return false;
100+
}
101+
102+
FpmLink::FpmLink(RouteSync *rsync, unsigned short port) :
13103
MSG_BATCH_SIZE(256),
14104
m_bufSize(FPM_MAX_MSG_LEN * MSG_BATCH_SIZE),
15105
m_messageBuffer(NULL),
16106
m_pos(0),
17107
m_connected(false),
18-
m_server_up(false)
108+
m_server_up(false),
109+
m_routesync(rsync)
19110
{
20111
struct sockaddr_in addr;
21112
int true_val = 1;
@@ -120,12 +211,35 @@ uint64_t FpmLink::readData()
120211

121212
if (hdr->msg_type == FPM_MSG_TYPE_NETLINK)
122213
{
123-
nl_msg *msg = nlmsg_convert((nlmsghdr *)fpm_msg_data(hdr));
214+
bool isRaw = false;
215+
216+
nlmsghdr *nl_hdr = (nlmsghdr *)fpm_msg_data(hdr);
217+
218+
/*
219+
* EVPN Type5 Add Routes need to be process in Raw mode as they contain
220+
* RMAC, VLAN and L3VNI information.
221+
* Where as all other route will be using rtnl api to extract information
222+
* from the netlink msg.
223+
* */
224+
isRaw = isRawProcessing(nl_hdr);
225+
226+
nl_msg *msg = nlmsg_convert(nl_hdr);
124227
if (msg == NULL)
228+
{
125229
throw system_error(make_error_code(errc::bad_message), "Unable to convert nlmsg");
230+
}
126231

127232
nlmsg_set_proto(msg, NETLINK_ROUTE);
128-
NetDispatcher::getInstance().onNetlinkMessage(msg);
233+
234+
if (isRaw)
235+
{
236+
/* EVPN Type5 Add route processing */
237+
processRawMsg(nl_hdr);
238+
}
239+
else
240+
{
241+
NetDispatcher::getInstance().onNetlinkMessage(msg);
242+
}
129243
nlmsg_free(msg);
130244
}
131245
start += msg_len;

fpmsyncd/fpmlink.h

+9-1
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,14 @@
1313

1414
#include "selectable.h"
1515
#include "fpm/fpm.h"
16+
#include "fpmsyncd/routesync.h"
1617

1718
namespace swss {
1819

1920
class FpmLink : public Selectable {
2021
public:
2122
const int MSG_BATCH_SIZE;
22-
FpmLink(unsigned short port = FPM_DEFAULT_PORT);
23+
FpmLink(RouteSync *rsync, unsigned short port = FPM_DEFAULT_PORT);
2324
virtual ~FpmLink();
2425

2526
/* Wait for connection (blocking) */
@@ -32,7 +33,14 @@ class FpmLink : public Selectable {
3233
{
3334
};
3435

36+
bool isRawProcessing(struct nlmsghdr *h);
37+
void processRawMsg(struct nlmsghdr *h)
38+
{
39+
m_routesync->onMsgRaw(h);
40+
};
41+
3542
private:
43+
RouteSync *m_routesync;
3644
unsigned int m_bufSize;
3745
char *m_messageBuffer;
3846
unsigned int m_pos;

fpmsyncd/fpmsyncd.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
using namespace std;
1313
using namespace swss;
1414

15-
1615
/*
1716
* Default warm-restart timer interval for routing-stack app. To be used only if
1817
* no explicit value has been defined in configuration.
@@ -61,7 +60,7 @@ int main(int argc, char **argv)
6160
{
6261
try
6362
{
64-
FpmLink fpm;
63+
FpmLink fpm(&sync);
6564
Select s;
6665
SelectableTimer warmStartTimer(timespec{0, 0});
6766
// Before eoiu flags detected, check them periodically. It also stop upon detection of reconciliation done.

0 commit comments

Comments
 (0)