Skip to content

Commit 7d540cb

Browse files
authored
[fpmsyncd]: Fix uA SID programming for link-local adjacencies (#3958)
* [fpmsyncd]: Fix uA SID programming for link-local adjacencies A uA SID performs a shift and cross-connect to a direct neighbor over a specific interface. It is defined by two parameters: an interface and a nexthop IPv6 address. When FRR sends a uA SID to SONiC's fpmsyncd, it includes both of these parameters. However, fpmsyncd currently only extracts the nexthop IPv6 address. It then creates an entry in the SRV6_MY_SID_TABLE of ApplDB with action=ua and adj=<nexthop_ipv6_address>. Subsequently, OrchAgent retrieves this entry and attempts to resolve the adjacency to program the SID in the ASIC. The issue is that fpmsyncd extracts the nexthop IPv6 address from the message but does not extract the interface. In cases where the nexthop IPv6 address is a link-local address, the interface is essential for successful nexthop resolution. Without it, the resolution fails, and the SID is not programmed in the ASIC. For example, the following syslog messages show OrchAgent failing to resolve a link-local nexthop because the interface is missing: ``` Oct 27 08:31:19.345821 1cdc490d8ce2 INFO #orchagent: :- doTask: table name : SRV6_MY_SID_TABLE Oct 27 08:31:19.345895 1cdc490d8ce2 INFO #orchagent: :- createUpdateMysidEntry: MY SID STRING fcbb:bbbb:1:fe10:: Oct 27 08:31:19.345912 1cdc490d8ce2 INFO #orchagent: :- createUpdateMysidEntry: MySid: sid fcbb:bbbb:1:fe10::, action ua, vrf , block 32, node 16, func 16, arg 0 dt_vrf , adj fe80::e822:daff:feab:3ee9 Oct 27 08:31:19.345946 1cdc490d8ce2 INFO #orchagent: :- createUpdateMysidEntry: Adjacency fe80::e822:daff:feab:3ee9 Oct 27 08:31:19.345965 1cdc490d8ce2 INFO #orchagent: :- createUpdateMysidEntry: Nexthop for adjacency fe80::e822:daff:feab:3ee9 doesn't exist in DB yet Oct 27 08:31:19.345983 1cdc490d8ce2 ERR #orchagent: :- doTaskMySidTable: Failed to create/update my_sid entry for sid 32:16:16:0:fcbb:bbbb:1:fe10:: ```
1 parent 8541200 commit 7d540cb

File tree

5 files changed

+101
-11
lines changed

5 files changed

+101
-11
lines changed

fpmsyncd/routesync.cpp

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ enum {
9999
SRV6_LOCALSID_BPF = 9,
100100
SRV6_LOCALSID_SIDLIST = 10,
101101
SRV6_LOCALSID_ENCAP_SRC_ADDR = 11,
102+
SRV6_LOCALSID_IFNAME = 12,
102103
};
103104

104105
enum {
@@ -447,11 +448,12 @@ bool RouteSync::parseSrv6MySidFormat(struct rtattr *tb,
447448
bool RouteSync::parseSrv6MySid(struct rtattr *tb[], string &block_len,
448449
string &node_len, string &func_len,
449450
string &arg_len, string &action,
450-
string &vrf, string &adj)
451+
string &vrf, string &adj, string &intf)
451452
{
452453
uint32_t action_buf = SRV6_LOCALSID_ACTION_UNSPEC;
453454
char vrf_buf[IFNAMSIZ + 1] = {0};
454455
char adj_buf[MAX_ADDR_SIZE + 1] = {0};
456+
char intf_buf[IFNAMSIZ + 1] = {0};
455457

456458
if (tb[SRV6_LOCALSID_FORMAT])
457459
{
@@ -493,9 +495,16 @@ bool RouteSync::parseSrv6MySid(struct rtattr *tb[], string &block_len,
493495
strlen((char *)RTA_DATA(tb[SRV6_LOCALSID_VRFNAME])));
494496
}
495497

498+
if (tb[SRV6_LOCALSID_IFNAME])
499+
{
500+
memcpy(intf_buf, (char *)RTA_DATA(tb[SRV6_LOCALSID_IFNAME]),
501+
strlen((char *)RTA_DATA(tb[SRV6_LOCALSID_IFNAME])));
502+
}
503+
496504
action = mySidAction2Str(action_buf);
497505
vrf = vrf_buf;
498506
adj = adj_buf;
507+
intf = intf_buf;
499508

500509
if (action == "unknown")
501510
{
@@ -504,9 +513,9 @@ bool RouteSync::parseSrv6MySid(struct rtattr *tb[], string &block_len,
504513
}
505514

506515
SWSS_LOG_INFO("Rx block_len:%s node_len:%s func_len:%s arg_len:%s "
507-
"action:%s vrf:%s adj:%s",
516+
"action:%s vrf:%s adj:%s intf:%s",
508517
block_len.c_str(), node_len.c_str(), func_len.c_str(),
509-
arg_len.c_str(), action.c_str(), vrf.c_str(), adj.c_str());
518+
arg_len.c_str(), action.c_str(), vrf.c_str(), adj.c_str(), intf.c_str());
510519

511520
return true;
512521
}
@@ -1384,11 +1393,12 @@ void RouteSync::onSrv6MySidMsg(struct nlmsghdr *h, int len)
13841393
string action_str;
13851394
string vrf_str;
13861395
string adj_str;
1396+
string intf_str;
13871397
string my_sid_table_key;
13881398

13891399
if (!parseSrv6MySid(tb, block_len_str, node_len_str,
13901400
func_len_str, arg_len_str, action_str, vrf_str,
1391-
adj_str))
1401+
adj_str, intf_str))
13921402
{
13931403
SWSS_LOG_ERROR("Invalid Srv6 MySid");
13941404
return;
@@ -1490,6 +1500,13 @@ void RouteSync::onSrv6MySidMsg(struct nlmsghdr *h, int len)
14901500
return;
14911501
}
14921502

1503+
if (!(action_str.compare("ua")) && adj_str.empty())
1504+
{
1505+
SWSS_LOG_NOTICE("MySid uA IP Prefix: %s adj is empty",
1506+
sid_value_str);
1507+
return;
1508+
}
1509+
14931510
if (!(action_str.compare("end.dx6")) && adj_str.empty())
14941511
{
14951512
SWSS_LOG_NOTICE("MySid End.DX6 IP Prefix: %s adj is empty",
@@ -1513,6 +1530,11 @@ void RouteSync::onSrv6MySidMsg(struct nlmsghdr *h, int len)
15131530
if (!adj_str.empty())
15141531
{
15151532
fvw.adj = std::move(adj_str);
1533+
// Append the interface name to the adjacency if one is provided
1534+
if (!intf_str.empty())
1535+
{
1536+
fvw.adj += "@" + intf_str;
1537+
}
15161538
}
15171539

15181540
setTable(fvw, m_srv6MySidTable);

fpmsyncd/routesync.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ class RouteSync : public NetMsg
285285
bool parseSrv6MySid(struct rtattr *tb[], string &block_len,
286286
string &node_len, string &func_len,
287287
string &arg_len, string &action, string &vrf,
288-
string &adj);
288+
string &adj, string &intf);
289289

290290
bool parseSrv6MySidFormat(struct rtattr *tb, string &block_len,
291291
string &node_len, string &func_len,

tests/mock_tests/fpmsyncd/receive_srv6_mysids_ut.cpp

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,58 @@ namespace ut_fpmsyncd
569569
free_nlobj(nl_obj);
570570
}
571571

572+
/* Test Receiving an SRv6 My SID nexthop bound to the uA behavior with an interface */
573+
TEST_F(FpmSyncdSRv6MySIDsTest, RecevingRouteWithSRv6MySIDUAWithIntf)
574+
{
575+
ASSERT_NE(m_routeSync, nullptr);
576+
577+
/* Create a Netlink object containing an SRv6 My SID */
578+
IpAddress _mysid = IpAddress("fc00:0:1:e000::");
579+
int8_t _block_len = 32;
580+
int8_t _node_len = 16;
581+
int8_t _func_len = 16;
582+
int8_t _arg_len = 0;
583+
uint32_t _action = SRV6_LOCALSID_ACTION_UA;
584+
IpAddress _adj = IpAddress("fe80::e822:daff:feab:3ee9");
585+
char *_intf = "Ethernet0";
586+
string my_sid_table_key = get_srv6_my_sid_table_key(&_mysid, _block_len, _node_len, _func_len, _arg_len);
587+
588+
struct nlmsg *nl_obj = create_srv6_mysid_nlmsg(RTM_NEWSRV6LOCALSID, &_mysid, _block_len, _node_len, _func_len, _arg_len, _action, NULL, &_adj, _intf);
589+
if (!nl_obj)
590+
throw std::runtime_error("SRv6 My SID creation failed");
591+
592+
/* Send the Netlink object to the FpmLink */
593+
m_fpmLink->processRawMsg(&nl_obj->n);
594+
595+
/* Check that fpmsyncd created the correct entries in APP_DB */
596+
std::string action;
597+
ASSERT_EQ(m_srv6MySidTable->hget(my_sid_table_key, "action", action), true);
598+
ASSERT_EQ(action, "ua");
599+
600+
std::string adj;
601+
ASSERT_EQ(m_srv6MySidTable->hget(my_sid_table_key, "adj", adj), true);
602+
ASSERT_EQ(adj, "fe80::e822:daff:feab:3ee9@Ethernet0");
603+
604+
/* Destroy the Netlink object and free the memory */
605+
free_nlobj(nl_obj);
606+
607+
/* Delete My SID */
608+
nl_obj = create_srv6_mysid_nlmsg(RTM_DELSRV6LOCALSID, &_mysid, _block_len, _node_len, _func_len, _arg_len, _action, NULL, &_adj, _intf);
609+
if (!nl_obj)
610+
throw std::runtime_error("SRv6 My SID creation failed");
611+
612+
/* Send the Netlink object to the FpmLink */
613+
m_fpmLink->processRawMsg(&nl_obj->n);
614+
615+
/* Check that fpmsyncd created the correct entries in APP_DB */
616+
ASSERT_EQ(m_srv6MySidTable->hget(my_sid_table_key, "action", action), false);
617+
618+
ASSERT_EQ(m_srv6MySidTable->hget(my_sid_table_key, "adj", adj), false);
619+
620+
/* Destroy the Netlink object and free the memory */
621+
free_nlobj(nl_obj);
622+
}
623+
572624
/* Test Receiving an SRv6 My SID nexthop bound to the uDX6 behavior */
573625
TEST_F(FpmSyncdSRv6MySIDsTest, RecevingRouteWithSRv6MySIDUDX6)
574626
{
@@ -1014,7 +1066,7 @@ namespace ut_fpmsyncd
10141066
string my_sid_table_key = get_srv6_my_sid_table_key(&_mysid, _block_len, _node_len, _func_len, _arg_len);
10151067

10161068
/* Create a Netlink object containing an SRv6 My SID with IPv4 SID value */
1017-
nl_obj = create_srv6_mysid_nlmsg(RTM_NEWSRV6LOCALSID, &_mysid, 32, 16, 16, 0, SRV6_LOCALSID_ACTION_END, NULL, NULL, 10, 0, AF_INET);
1069+
nl_obj = create_srv6_mysid_nlmsg(RTM_NEWSRV6LOCALSID, &_mysid, 32, 16, 16, 0, SRV6_LOCALSID_ACTION_END, NULL, NULL, NULL, 10, 0, AF_INET);
10181070

10191071
/* Send the Netlink object to the FpmLink */
10201072
ASSERT_EQ(m_fpmLink->isRawProcessing(&nl_obj->n), true);
@@ -1042,7 +1094,7 @@ namespace ut_fpmsyncd
10421094
string my_sid_table_key = get_srv6_my_sid_table_key(&_mysid, _block_len, _node_len, _func_len, _arg_len);
10431095

10441096
/* Create a Netlink object containing an SRv6 My SID with invalid SID value prefix length */
1045-
nl_obj = create_srv6_mysid_nlmsg(RTM_NEWSRV6LOCALSID, &_mysid, 32, 16, 16, 0, SRV6_LOCALSID_ACTION_END, NULL, NULL, 10, 200, AF_INET6);
1097+
nl_obj = create_srv6_mysid_nlmsg(RTM_NEWSRV6LOCALSID, &_mysid, 32, 16, 16, 0, SRV6_LOCALSID_ACTION_END, NULL, NULL, NULL, 10, 200, AF_INET6);
10461098

10471099
/* Send the Netlink object to the FpmLink */
10481100
ASSERT_EQ(m_fpmLink->isRawProcessing(&nl_obj->n), true);
@@ -1182,7 +1234,7 @@ namespace ut_fpmsyncd
11821234
string my_sid_table_key = get_srv6_my_sid_table_key(&_mysid, _block_len, _node_len, _func_len, _arg_len);
11831235

11841236
/* Create a Netlink object containing an SRv6 My SID with missing block length */
1185-
nl_obj = create_srv6_mysid_nlmsg(RTM_NEWSRV6LOCALSID, &_mysid, -1, 16, 16, 0, SRV6_LOCALSID_ACTION_END, NULL, NULL, 10, AF_INET6, 200);
1237+
nl_obj = create_srv6_mysid_nlmsg(RTM_NEWSRV6LOCALSID, &_mysid, -1, 16, 16, 0, SRV6_LOCALSID_ACTION_END, NULL, NULL, NULL, 10, 200, AF_INET6);
11861238

11871239
/* Send the Netlink object to the FpmLink */
11881240
ASSERT_EQ(m_fpmLink->isRawProcessing(&nl_obj->n), true);
@@ -1210,7 +1262,7 @@ namespace ut_fpmsyncd
12101262
string my_sid_table_key = get_srv6_my_sid_table_key(&_mysid, _block_len, _node_len, _func_len, _arg_len);
12111263

12121264
/* Create a Netlink object containing an SRv6 My SID with missing node length */
1213-
nl_obj = create_srv6_mysid_nlmsg(RTM_NEWSRV6LOCALSID, &_mysid, 32, -1, 16, 0, SRV6_LOCALSID_ACTION_END, NULL, NULL, 10, AF_INET6, 200);
1265+
nl_obj = create_srv6_mysid_nlmsg(RTM_NEWSRV6LOCALSID, &_mysid, 32, -1, 16, 0, SRV6_LOCALSID_ACTION_END, NULL, NULL, NULL, 10, 200, AF_INET6);
12141266

12151267
/* Send the Netlink object to the FpmLink */
12161268
ASSERT_EQ(m_fpmLink->isRawProcessing(&nl_obj->n), true);
@@ -1238,7 +1290,7 @@ namespace ut_fpmsyncd
12381290
string my_sid_table_key = get_srv6_my_sid_table_key(&_mysid, _block_len, _node_len, _func_len, _arg_len);
12391291

12401292
/* Create a Netlink object containing an SRv6 My SID with missing node length */
1241-
nl_obj = create_srv6_mysid_nlmsg(RTM_NEWSRV6LOCALSID, &_mysid, 32, 16, -1, 0, SRV6_LOCALSID_ACTION_END, NULL, NULL, 10, AF_INET6, 200);
1293+
nl_obj = create_srv6_mysid_nlmsg(RTM_NEWSRV6LOCALSID, &_mysid, 32, 16, -1, 0, SRV6_LOCALSID_ACTION_END, NULL, NULL, NULL, 10, 200, AF_INET6);
12421294

12431295
/* Send the Netlink object to the FpmLink */
12441296
ASSERT_EQ(m_fpmLink->isRawProcessing(&nl_obj->n), true);

tests/mock_tests/fpmsyncd/ut_helpers_fpmsyncd.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ namespace ut_fpmsyncd
219219
uint32_t action,
220220
char *vrf,
221221
IpAddress *adj,
222+
char *intf,
222223
uint16_t table_id,
223224
uint8_t prefixlen,
224225
uint8_t address_family
@@ -354,6 +355,13 @@ namespace ut_fpmsyncd
354355
SRV6_LOCALSID_NH6,
355356
adj->getV6Addr(), 16))
356357
return NULL;
358+
}
359+
if (intf)
360+
{
361+
if (!nl_attr_put(&nl_obj->n, sizeof(*nl_obj),
362+
SRV6_LOCALSID_IFNAME,
363+
intf, (uint32_t)strlen(intf)))
364+
return NULL;
357365
}
358366
break;
359367
case SRV6_LOCALSID_ACTION_END_T:
@@ -451,6 +459,13 @@ namespace ut_fpmsyncd
451459
SRV6_LOCALSID_NH6,
452460
adj->getV6Addr(), 16))
453461
return NULL;
462+
}
463+
if (intf)
464+
{
465+
if (!nl_attr_put(&nl_obj->n, sizeof(*nl_obj),
466+
SRV6_LOCALSID_IFNAME,
467+
intf, (uint32_t)strlen(intf)))
468+
return NULL;
454469
}
455470
break;
456471
case SRV6_LOCALSID_ACTION_UDX4:

tests/mock_tests/fpmsyncd/ut_helpers_fpmsyncd.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ enum { /* Values copied from fpmsyncd/routesync.cpp */
6161
SRV6_LOCALSID_BPF = 9,
6262
SRV6_LOCALSID_SIDLIST = 10,
6363
SRV6_LOCALSID_ENCAP_SRC_ADDR = 11,
64+
SRV6_LOCALSID_IFNAME = 12,
6465
};
6566

6667
enum { /* Values copied from fpmsyncd/routesync.cpp */
@@ -105,7 +106,7 @@ namespace ut_fpmsyncd
105106
struct nlmsg *create_srv6_mysid_nlmsg(uint16_t cmd, IpAddress *mysid, int8_t block_len,
106107
int8_t node_len, int8_t func_len, int8_t arg_len,
107108
uint32_t action, char *vrf = NULL, IpAddress *nh = NULL,
108-
uint16_t table_id = 10, uint8_t prefixlen = 0,
109+
char *intf = NULL, uint16_t table_id = 10, uint8_t prefixlen = 0,
109110
uint8_t address_family = 0);
110111
/* Free the memory allocated for a Netlink object */
111112
inline void free_nlobj(struct nlmsg *msg)

0 commit comments

Comments
 (0)