Merge pull request #18605 from pguibert6WIND/sharp_usid

Add sharp support for seg6local routes with uSID flavor
This commit is contained in:
Russ White 2025-04-29 11:16:21 -04:00 committed by GitHub
commit 5398e01dca
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 245 additions and 7 deletions

View file

@ -198,14 +198,24 @@ keyword. At present, no sharp commands will be preserved in the config.
router# sharp install seg6local-routes 1::4 nexthop-seg6local dum0 End_DX4 10.0.0.1 1 router# sharp install seg6local-routes 1::4 nexthop-seg6local dum0 End_DX4 10.0.0.1 1
router# sharp install seg6local-routes 1::5 nexthop-seg6local dum0 End_DT6 10 1 router# sharp install seg6local-routes 1::5 nexthop-seg6local dum0 End_DT6 10 1
router# sharp install seg6local-routes 1::6 nexthop-seg6local dum0 End_DT46 10 1 router# sharp install seg6local-routes 1::6 nexthop-seg6local dum0 End_DT46 10 1
router# sharp install seg6local-routes 1::7 nexthop-seg6local dum0 uN 1
router# sharp install seg6local-routes 1::8 nexthop-seg6local dum0 uA 2001::1 1
router# sharp install seg6local-routes 1::9 nexthop-seg6local dum0 uN usid-block-length 40 usid-function-length 8 1
router# sharp install seg6local-routes 1::10 nexthop-seg6local dum0 uA 2001::1 usid-block-length 40 usid-function-length 8 1
router# sharp install seg6local-routes 1::11 nexthop-seg6local dum0 End_B6_Encap nexthop-seg6 2001::5 encap 2001:a::b:c 2001:a::d:e 1
router# show ipv6 route router# show ipv6 route
D>* 1::1/128 [150/0] is directly connected, dum0, seg6local End USP, weight 1, 00:00:05 D>* 1::1/128 [150/0] is directly connected, dum0, seg6local End -, weight 1, 00:00:05
D>* 1::2/128 [150/0] is directly connected, dum0, seg6local End.X nh6 2001::1, weight 1, 00:00:05 D>* 1::2/128 [150/0] is directly connected, dum0, seg6local End.X nh6 2001::1, weight 1, 00:00:05
D>* 1::3/128 [150/0] is directly connected, dum0, seg6local End.T table 10, weight 1, 00:00:05 D>* 1::3/128 [150/0] is directly connected, dum0, seg6local End.T table 10, weight 1, 00:00:05
D>* 1::4/128 [150/0] is directly connected, dum0, seg6local End.DX4 nh4 10.0.0.1, weight 1, 00:00:05 D>* 1::4/128 [150/0] is directly connected, dum0, seg6local End.DX4 nh4 10.0.0.1, weight 1, 00:00:05
D>* 1::5/128 [150/0] is directly connected, dum0, seg6local End.DT6 table 10, weight 1, 00:00:05 D>* 1::5/128 [150/0] is directly connected, dum0, seg6local End.DT6 table 10, weight 1, 00:00:05
D>* 1::6/128 [150/0] is directly connected, dum0, seg6local End.DT46 table 10, weight 1, 00:00:05 D>* 1::6/128 [150/0] is directly connected, dum0, seg6local End.DT46 table 10, weight 1, 00:00:05
D>* 1::7/128 [150/0] is directly connected, dum0, seg6local End -, weight 1, 00:00:05
D>* 1::8/128 [150/0] is directly connected, dum0, seg6local End.X nh6 2001::1, weight 1, 00:01:17
D>* 1::9/128 [150/0] is directly connected, dum0, seg6local End -, weight 1, 00:00:12
D>* 1::10/128 [150/0] is directly connected, dum0, seg6local End.X nh6 2001::1, weight 1, 00:00:05
D>* 1::11/128 [150/0] is directly connected, dum0, seg6local End.B6.Encap nh6 2001::5, seg6 2001:a::b:c,2001:a::d:e, weight 1, 00:00:04
bash# ip -6 route bash# ip -6 route
1::1 encap seg6local action End dev dum0 proto 194 metric 20 pref medium 1::1 encap seg6local action End dev dum0 proto 194 metric 20 pref medium
@ -214,6 +224,12 @@ keyword. At present, no sharp commands will be preserved in the config.
1::4 encap seg6local action End.DX4 nh4 10.0.0.1 dev dum0 proto 194 metric 20 pref medium 1::4 encap seg6local action End.DX4 nh4 10.0.0.1 dev dum0 proto 194 metric 20 pref medium
1::5 encap seg6local action End.DT6 table 10 dev dum0 proto 194 metric 20 pref medium 1::5 encap seg6local action End.DT6 table 10 dev dum0 proto 194 metric 20 pref medium
1::6 encap seg6local action End.DT46 table 10 dev dum0 proto 194 metric 20 pref medium 1::6 encap seg6local action End.DT46 table 10 dev dum0 proto 194 metric 20 pref medium
1::7 encap seg6local action End flavors next-csid lblen 32 nflen 16 dev dum0 proto 194 metric 20 pref medium
1::8 encap seg6local action End.X nh6 2001::1 flavors next-csid lblen 32 nflen 16 dev dum0 proto 194 metric 20 pref medium
1::9 encap seg6local action End flavors next-csid lblen 40 nflen 8 dev dum0 proto 194 metric 20 pref medium
1::10 encap seg6local action End.X nh6 2001::1 flavors next-csid lblen 40 nflen 8 dev dum0 proto 194 metric 20 pref medium
1::11 encap seg6local action End.B6.Encaps segs 2 [ 2001:a::b:c 2001:a::d:e ] via 2001::5 dev dum0 proto 194 metric 20 pref medium
.. clicmd:: show sharp segment-routing srv6 .. clicmd:: show sharp segment-routing srv6

View file

@ -439,19 +439,125 @@ DEFPY (install_seg6_routes,
return CMD_SUCCESS; return CMD_SUCCESS;
} }
DEFPY(install_seg6local_segs_routes, install_seg6local_segs_routes_cmd,
"sharp install seg6local-routes [vrf NAME$vrf_name]\
X:X::X:X$start6\
nexthop-seg6local NAME$seg6l_oif\
<End_B6_Encap$end_b6_encap|uB6_Encap$ub6_encap>\
nexthop-seg6 X:X::X:X$seg6_nh6\
encap X:X::X:X$seg6_seg1 X:X::X:X$seg6_seg2\
[usid-block-length (1-128)$lcblen] [usid-function-length (1-128)$lcfunclen] \
(1-1000000)$routes [repeat (2-1000)$rpt]",
"Sharp routing Protocol\n"
"install some routes\n"
"Routes to install\n"
"The vrf we would like to install into if non-default\n"
"The NAME of the vrf\n"
"v6 Address to start /32 generation at\n"
"Nexthop-seg6local to use\n"
"Output device to use\n"
"SRv6 End.B6.Encap function to use\n"
"SRv6 uB6.Encap function to use\n"
"Nexthop-seg6 to use\n"
"V6 Nexthop address to use\n"
"Encap mode\n"
"Segment List, 1st SID to use\n"
"Segment List, 2nd SID to use\n"
"uSID locator block length\n"
"Value in bits\n"
"uSID node Function length\n"
"Value in bits\n"
"How many to create\n"
"Should we repeat this command\n"
"How many times to repeat this command\n")
{
struct vrf *vrf;
uint32_t route_flags = 0;
struct seg6local_context ctx = {};
enum seg6local_action_t action;
struct in6_addr seg_list[2];
struct in6_addr *p_seg_list = &seg_list[0];
sg.r.total_routes = routes;
sg.r.installed_routes = 0;
if (rpt >= 2)
sg.r.repeat = rpt * 2;
else
sg.r.repeat = 0;
memset(&sg.r.orig_prefix, 0, sizeof(sg.r.orig_prefix));
nexthop_del_srv6_seg6local(&sg.r.nhop);
nexthop_del_srv6_seg6(&sg.r.nhop);
memset(&sg.r.nhop, 0, sizeof(sg.r.nhop));
memset(&sg.r.nhop_group, 0, sizeof(sg.r.nhop_group));
memset(&sg.r.backup_nhop, 0, sizeof(sg.r.nhop));
memset(&sg.r.backup_nhop_group, 0, sizeof(sg.r.nhop_group));
sg.r.opaque[0] = '\0';
sg.r.inst = 0;
sg.r.orig_prefix.family = AF_INET6;
sg.r.orig_prefix.prefixlen = 128;
sg.r.orig_prefix.u.prefix6 = start6;
if (!vrf_name)
vrf_name = VRF_DEFAULT_NAME;
vrf = vrf_lookup_by_name(vrf_name);
if (!vrf) {
vty_out(vty, "The vrf NAME specified: %s does not exist\n", vrf_name);
return CMD_WARNING;
}
ctx.nh6 = seg6_nh6;
action = ZEBRA_SEG6_LOCAL_ACTION_END_B6_ENCAP;
if (ub6_encap) {
SET_SRV6_FLV_OP(ctx.flv.flv_ops, ZEBRA_SEG6_LOCAL_FLV_OP_NEXT_CSID);
if (lcblen)
ctx.flv.lcblock_len = lcblen;
if (lcfunclen)
ctx.flv.lcnode_func_len = lcfunclen;
}
sg.r.nhop.type = NEXTHOP_TYPE_IPV6_IFINDEX;
sg.r.nhop.gate.ipv6 = seg6_nh6;
sg.r.nhop.ifindex = ifname2ifindex(seg6l_oif, vrf->vrf_id);
sg.r.nhop.vrf_id = vrf->vrf_id;
sg.r.nhop_group.nexthop = &sg.r.nhop;
nexthop_add_srv6_seg6local(&sg.r.nhop, action, &ctx);
sg.r.nhop_group.nexthop = &sg.r.nhop;
seg_list[0] = seg6_seg1;
seg_list[1] = seg6_seg2;
nexthop_add_srv6_seg6(&sg.r.nhop, p_seg_list, 2);
sg.r.vrf_id = vrf->vrf_id;
sharp_install_routes_helper(&sg.r.orig_prefix, sg.r.vrf_id, sg.r.inst, 0, &sg.r.nhop_group,
&sg.r.backup_nhop_group, routes, route_flags, sg.r.opaque);
return CMD_SUCCESS;
}
DEFPY (install_seg6local_routes, DEFPY (install_seg6local_routes,
install_seg6local_routes_cmd, install_seg6local_routes_cmd,
"sharp install seg6local-routes [vrf NAME$vrf_name]\ "sharp install seg6local-routes [vrf NAME$vrf_name]\
X:X::X:X$start6\ X:X::X:X$start6\
nexthop-seg6local NAME$seg6l_oif\ nexthop-seg6local NAME$seg6l_oif\
<End$seg6l_end|\ <End$seg6l_end|\
uN$seg6l_micro_end|\
End_X$seg6l_endx X:X::X:X$seg6l_endx_nh6|\ End_X$seg6l_endx X:X::X:X$seg6l_endx_nh6|\
uA$seg6l_micro_endx X:X::X:X$seg6l_micro_endx_nh6|\
End_T$seg6l_endt (1-4294967295)$seg6l_endt_table|\ End_T$seg6l_endt (1-4294967295)$seg6l_endt_table|\
uDT$seg6l_micro_endt (1-4294967295)$seg6l_micro_endt_table|\
End_DX4$seg6l_enddx4 A.B.C.D$seg6l_enddx4_nh4|\ End_DX4$seg6l_enddx4 A.B.C.D$seg6l_enddx4_nh4|\
uDX4$seg6l_micro_enddx4 A.B.C.D$seg6l_micro_enddx4_nh4|\
End_DX6$seg6l_enddx6 X:X::X:X$seg6l_enddx6_nh6|\ End_DX6$seg6l_enddx6 X:X::X:X$seg6l_enddx6_nh6|\
uDX6$seg6l_micro_enddx6 X:X::X:X$seg6l_micro_enddx6_nh6|\
End_DT6$seg6l_enddt6 (1-4294967295)$seg6l_enddt6_table|\ End_DT6$seg6l_enddt6 (1-4294967295)$seg6l_enddt6_table|\
uDT6$seg6l_micro_enddt6 (1-4294967295)$seg6l_micro_enddt6_table|\
End_DT4$seg6l_enddt4 (1-4294967295)$seg6l_enddt4_table|\ End_DT4$seg6l_enddt4 (1-4294967295)$seg6l_enddt4_table|\
End_DT46$seg6l_enddt46 (1-4294967295)$seg6l_enddt46_table>\ uDT4$seg6l_micro_enddt4 (1-4294967295)$seg6l_micro_enddt4_table|\
End_DT46$seg6l_enddt46 (1-4294967295)$seg6l_enddt46_table|\
uDT46$seg6l_micro_enddt46 (1-4294967295)$seg6l_micro_enddt46_table>\
[usid-block-length (1-128)$lcblen] [usid-function-length (1-128)$lcfunclen] \
(1-1000000)$routes [repeat (2-1000)$rpt]", (1-1000000)$routes [repeat (2-1000)$rpt]",
"Sharp routing Protocol\n" "Sharp routing Protocol\n"
"install some routes\n" "install some routes\n"
@ -462,20 +568,39 @@ DEFPY (install_seg6local_routes,
"Nexthop-seg6local to use\n" "Nexthop-seg6local to use\n"
"Output device to use\n" "Output device to use\n"
"SRv6 End function to use\n" "SRv6 End function to use\n"
"SRv6 uN function to use\n"
"SRv6 End.X function to use\n" "SRv6 End.X function to use\n"
"V6 Nexthop address to use\n" "V6 Nexthop address to use\n"
"SRv6 uA function to use\n"
"V6 Nexthop address to use\n"
"SRv6 End.T function to use\n" "SRv6 End.T function to use\n"
"Redirect table id to use\n" "Redirect table id to use\n"
"SRv6 uDT function to use\n"
"Redirect table id to use\n"
"SRv6 End.DX4 function to use\n" "SRv6 End.DX4 function to use\n"
"V4 Nexthop address to use\n" "V4 Nexthop address to use\n"
"SRv6 uDX4 function to use\n"
"V4 Nexthop address to use\n"
"SRv6 End.DX6 function to use\n" "SRv6 End.DX6 function to use\n"
"V6 Nexthop address to use\n" "V6 Nexthop address to use\n"
"SRv6 uDX6 function to use\n"
"V6 Nexthop address to use\n"
"SRv6 End.DT6 function to use\n" "SRv6 End.DT6 function to use\n"
"Redirect table id to use\n" "Redirect table id to use\n"
"SRv6 uDT6 function to use\n"
"Redirect table id to use\n"
"SRv6 End.DT4 function to use\n" "SRv6 End.DT4 function to use\n"
"Redirect table id to use\n" "Redirect table id to use\n"
"SRv6 uDT4 function to use\n"
"Redirect table id to use\n"
"SRv6 End.DT46 function to use\n" "SRv6 End.DT46 function to use\n"
"Redirect table id to use\n" "Redirect table id to use\n"
"SRv6 uDT46 function to use\n"
"Redirect table id to use\n"
"uSID locator block length\n"
"Value in bits\n"
"uSID node Function length\n"
"Value in bits\n"
"How many to create\n" "How many to create\n"
"Should we repeat this command\n" "Should we repeat this command\n"
"How many times to repeat this command\n") "How many times to repeat this command\n")
@ -519,28 +644,64 @@ DEFPY (install_seg6local_routes,
if (seg6l_enddx4) { if (seg6l_enddx4) {
action = ZEBRA_SEG6_LOCAL_ACTION_END_DX4; action = ZEBRA_SEG6_LOCAL_ACTION_END_DX4;
ctx.nh4 = seg6l_enddx4_nh4; ctx.nh4 = seg6l_enddx4_nh4;
} else if (seg6l_micro_enddx4) {
action = ZEBRA_SEG6_LOCAL_ACTION_END_DX4;
ctx.nh4 = seg6l_micro_enddx4_nh4;
SET_SRV6_FLV_OP(ctx.flv.flv_ops, ZEBRA_SEG6_LOCAL_FLV_OP_NEXT_CSID);
} else if (seg6l_enddx6) { } else if (seg6l_enddx6) {
action = ZEBRA_SEG6_LOCAL_ACTION_END_DX6; action = ZEBRA_SEG6_LOCAL_ACTION_END_DX6;
ctx.nh6 = seg6l_enddx6_nh6; ctx.nh6 = seg6l_enddx6_nh6;
} else if (seg6l_micro_enddx6) {
action = ZEBRA_SEG6_LOCAL_ACTION_END_DX6;
ctx.nh6 = seg6l_enddx6_nh6;
SET_SRV6_FLV_OP(ctx.flv.flv_ops, ZEBRA_SEG6_LOCAL_FLV_OP_NEXT_CSID);
} else if (seg6l_endx) { } else if (seg6l_endx) {
action = ZEBRA_SEG6_LOCAL_ACTION_END_X; action = ZEBRA_SEG6_LOCAL_ACTION_END_X;
ctx.nh6 = seg6l_endx_nh6; ctx.nh6 = seg6l_endx_nh6;
} else if (seg6l_micro_endx) {
action = ZEBRA_SEG6_LOCAL_ACTION_END_X;
ctx.nh6 = seg6l_micro_endx_nh6;
SET_SRV6_FLV_OP(ctx.flv.flv_ops, ZEBRA_SEG6_LOCAL_FLV_OP_NEXT_CSID);
} else if (seg6l_endt) { } else if (seg6l_endt) {
action = ZEBRA_SEG6_LOCAL_ACTION_END_T; action = ZEBRA_SEG6_LOCAL_ACTION_END_T;
ctx.table = seg6l_endt_table; ctx.table = seg6l_endt_table;
} else if (seg6l_micro_endt) {
action = ZEBRA_SEG6_LOCAL_ACTION_END_T;
ctx.table = seg6l_micro_endt_table;
SET_SRV6_FLV_OP(ctx.flv.flv_ops, ZEBRA_SEG6_LOCAL_FLV_OP_NEXT_CSID);
} else if (seg6l_enddt6) { } else if (seg6l_enddt6) {
action = ZEBRA_SEG6_LOCAL_ACTION_END_DT6; action = ZEBRA_SEG6_LOCAL_ACTION_END_DT6;
ctx.table = seg6l_enddt6_table; ctx.table = seg6l_enddt6_table;
} else if (seg6l_micro_enddt6) {
action = ZEBRA_SEG6_LOCAL_ACTION_END_DT6;
ctx.table = seg6l_micro_enddt6_table;
SET_SRV6_FLV_OP(ctx.flv.flv_ops, ZEBRA_SEG6_LOCAL_FLV_OP_NEXT_CSID);
} else if (seg6l_enddt4) { } else if (seg6l_enddt4) {
action = ZEBRA_SEG6_LOCAL_ACTION_END_DT4; action = ZEBRA_SEG6_LOCAL_ACTION_END_DT4;
ctx.table = seg6l_enddt4_table; ctx.table = seg6l_enddt4_table;
} else if (seg6l_micro_enddt4) {
action = ZEBRA_SEG6_LOCAL_ACTION_END_DT4;
ctx.table = seg6l_micro_enddt4_table;
SET_SRV6_FLV_OP(ctx.flv.flv_ops, ZEBRA_SEG6_LOCAL_FLV_OP_NEXT_CSID);
} else if (seg6l_enddt46) { } else if (seg6l_enddt46) {
action = ZEBRA_SEG6_LOCAL_ACTION_END_DT46; action = ZEBRA_SEG6_LOCAL_ACTION_END_DT46;
ctx.table = seg6l_enddt46_table; ctx.table = seg6l_enddt46_table;
} else { } else if (seg6l_micro_enddt46) {
action = ZEBRA_SEG6_LOCAL_ACTION_END_DT46;
ctx.table = seg6l_micro_enddt46_table;
SET_SRV6_FLV_OP(ctx.flv.flv_ops, ZEBRA_SEG6_LOCAL_FLV_OP_NEXT_CSID);
} else if (seg6l_micro_end) {
action = ZEBRA_SEG6_LOCAL_ACTION_END;
SET_SRV6_FLV_OP(ctx.flv.flv_ops, ZEBRA_SEG6_LOCAL_FLV_OP_NEXT_CSID);
} else
action = ZEBRA_SEG6_LOCAL_ACTION_END; action = ZEBRA_SEG6_LOCAL_ACTION_END;
}
if (CHECK_SRV6_FLV_OP(ctx.flv.flv_ops, ZEBRA_SEG6_LOCAL_FLV_OP_NEXT_CSID)) {
if (lcblen)
ctx.flv.lcblock_len = lcblen;
if (lcfunclen)
ctx.flv.lcnode_func_len = lcfunclen;
}
sg.r.nhop.type = NEXTHOP_TYPE_IFINDEX; sg.r.nhop.type = NEXTHOP_TYPE_IFINDEX;
sg.r.nhop.ifindex = ifname2ifindex(seg6l_oif, vrf->vrf_id); sg.r.nhop.ifindex = ifname2ifindex(seg6l_oif, vrf->vrf_id);
sg.r.nhop.vrf_id = vrf->vrf_id; sg.r.nhop.vrf_id = vrf->vrf_id;
@ -1491,6 +1652,7 @@ void sharp_vty_init(void)
install_element(ENABLE_NODE, &install_routes_cmd); install_element(ENABLE_NODE, &install_routes_cmd);
install_element(ENABLE_NODE, &install_seg6_routes_cmd); install_element(ENABLE_NODE, &install_seg6_routes_cmd);
install_element(ENABLE_NODE, &install_seg6local_routes_cmd); install_element(ENABLE_NODE, &install_seg6local_routes_cmd);
install_element(ENABLE_NODE, &install_seg6local_segs_routes_cmd);
install_element(ENABLE_NODE, &remove_routes_cmd); install_element(ENABLE_NODE, &remove_routes_cmd);
install_element(ENABLE_NODE, &vrf_label_cmd); install_element(ENABLE_NODE, &vrf_label_cmd);
install_element(ENABLE_NODE, &sharp_nht_data_dump_cmd); install_element(ENABLE_NODE, &sharp_nht_data_dump_cmd);

View file

@ -94,6 +94,12 @@ struct gw_family_t {
union g_addr gate; union g_addr gate;
}; };
struct buf_req {
struct nlmsghdr n;
struct nhmsg nhm;
char buf[];
};
static const char ipv4_ll_buf[16] = "169.254.0.1"; static const char ipv4_ll_buf[16] = "169.254.0.1";
static struct in_addr ipv4_ll; static struct in_addr ipv4_ll;
@ -2936,6 +2942,54 @@ static bool _netlink_nexthop_build_group(struct nlmsghdr *n, size_t req_size, ui
return true; return true;
} }
static ssize_t fill_srh_end_b6_encaps(char *buffer, size_t buflen, struct seg6_seg_stack *segs)
{
struct ipv6_sr_hdr *srh;
size_t srhlen;
int i;
if (!segs || segs->num_segs > SRV6_MAX_SEGS) {
/* Exceeding maximum supported SIDs */
return -1;
}
srhlen = SRH_BASE_HEADER_LENGTH + SRH_SEGMENT_LENGTH * segs->num_segs;
if (buflen < srhlen)
return -1;
memset(buffer, 0, buflen);
srh = (struct ipv6_sr_hdr *)buffer;
srh->hdrlen = (srhlen >> 3) - 1;
srh->type = 4;
srh->segments_left = segs->num_segs - 1;
srh->first_segment = segs->num_segs - 1;
for (i = 0; i < segs->num_segs; i++) {
memcpy(&srh->segments[segs->num_segs - i - 1], &segs->seg[i],
sizeof(struct in6_addr));
}
return srhlen;
}
static int netlink_nexthop_msg_encode_end_b6_encaps(struct buf_req *req, const struct nexthop *nh,
size_t buflen)
{
int srh_len;
char srh_buf[4096];
if (!nl_attr_put32(&req->n, buflen, SEG6_LOCAL_ACTION, SEG6_LOCAL_ACTION_END_B6_ENCAP))
return 0;
srh_len = fill_srh_end_b6_encaps(srh_buf, sizeof(srh_buf), nh->nh_srv6->seg6_segs);
if (srh_len < 0)
return 0;
if (!nl_attr_put(&req->n, buflen, SEG6_LOCAL_SRH, srh_buf, srh_len))
return 0;
return 1;
}
/** /**
* Next hop packet encoding helper function. * Next hop packet encoding helper function.
* *
@ -3248,6 +3302,12 @@ ssize_t netlink_nexthop_msg_encode(uint16_t cmd,
ctx6->table)) ctx6->table))
return 0; return 0;
break; break;
case ZEBRA_SEG6_LOCAL_ACTION_END_B6_ENCAP:
netlink_nexthop_msg_encode_end_b6_encaps((struct buf_req
*)
req,
nh, buflen);
break;
default: default:
zlog_err("%s: unsupport seg6local behaviour action=%u", zlog_err("%s: unsupport seg6local behaviour action=%u",
__func__, action); __func__, action);
@ -3261,9 +3321,9 @@ ssize_t netlink_nexthop_msg_encode(uint16_t cmd,
nl_attr_nest_end(&req->n, nest); nl_attr_nest_end(&req->n, nest);
} }
if (nh->nh_srv6->seg6_segs && if (nh->nh_srv6->seg6_segs && nh->nh_srv6->seg6_segs->num_segs &&
nh->nh_srv6->seg6_segs->num_segs && !sid_zero(nh->nh_srv6->seg6_segs) &&
!sid_zero(nh->nh_srv6->seg6_segs)) { nh->nh_srv6->seg6local_action == ZEBRA_SEG6_LOCAL_ACTION_UNSPEC) {
char tun_buf[4096]; char tun_buf[4096];
ssize_t tun_len; ssize_t tun_len;