zebra: ZEBRA_ROUTE_ADD supports seg6 route (step3)

With this patch, zclient can intall seg6 rotues when
they set properties "nh_seg6_segs" on struct nexthop
and set ZEBRA_FLAG_SEG6_ROUTE on zapi_route's flag.

Signed-off-by: Hiroki Shirokura <slank.dev@gmail.com>
This commit is contained in:
Hiroki Shirokura 2020-12-17 23:43:01 +09:00 committed by Mark Stapp
parent 2aa01034f3
commit 76fb7ae4de
4 changed files with 75 additions and 0 deletions

View File

@ -1286,6 +1286,26 @@ static bool _netlink_route_encode_nexthop_src(const struct nexthop *nexthop,
return true;
}
static size_t fill_seg6ipt_encap(char *buffer, size_t buflen,
struct in6_addr *seg)
{
struct seg6_iptunnel_encap *ipt;
struct ipv6_sr_hdr *srh;
const size_t srhlen = 24;
memset(buffer, 0, buflen);
ipt = (struct seg6_iptunnel_encap *)buffer;
ipt->mode = SEG6_IPTUN_MODE_ENCAP;
srh = ipt->srh;
srh->hdrlen = (srhlen >> 3) - 1;
srh->type = 4;
srh->segments_left = 0;
srh->first_segment = 0;
memcpy(&srh->segments[0], seg, sizeof(struct in6_addr));
return srhlen + 4;
}
/* This function takes a nexthop as argument and adds
* the appropriate netlink attributes to an existing
* netlink message.
@ -1367,6 +1387,21 @@ static bool _netlink_route_build_singlepath(const struct prefix *p,
nl_attr_nest_end(nlmsg, nest);
}
if (nexthop->nh_seg6_segs) {
char tun_buf[4096];
size_t tun_len;
struct rtattr *nest;
nl_attr_put16(nlmsg, req_size, RTA_ENCAP_TYPE,
LWTUNNEL_ENCAP_SEG6);
nest = nl_attr_nest(nlmsg, req_size, RTA_ENCAP);
tun_len = fill_seg6ipt_encap(tun_buf, sizeof(tun_buf),
nexthop->nh_seg6_segs);
nl_attr_put(nlmsg, req_size, SEG6_IPTUNNEL_SRH,
tun_buf, tun_len);
nl_attr_nest_end(nlmsg, nest);
}
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
rtmsg->rtm_flags |= RTNH_F_ONLINK;
@ -2422,6 +2457,23 @@ ssize_t netlink_nexthop_msg_encode(uint16_t cmd,
nl_attr_nest_end(&req->n, nest);
}
if (nh->nh_seg6_segs) {
char tun_buf[4096];
size_t tun_len;
struct rtattr *nest;
nl_attr_put16(&req->n, buflen, NHA_ENCAP_TYPE,
LWTUNNEL_ENCAP_SEG6);
nest = nl_attr_nest(&req->n, buflen,
NHA_ENCAP | NLA_F_NESTED);
tun_len = fill_seg6ipt_encap(tun_buf,
sizeof(tun_buf),
nh->nh_seg6_segs);
nl_attr_put(&req->n, buflen, SEG6_IPTUNNEL_SRH,
tun_buf, tun_len);
nl_attr_nest_end(&req->n, nest);
}
nexthop_done:
if (IS_ZEBRA_DEBUG_KERNEL)

View File

@ -1783,6 +1783,14 @@ static bool zapi_read_nexthops(struct zserv *client, struct prefix *p,
&api_nh->seg6local_ctx);
}
if (CHECK_FLAG(flags, ZEBRA_FLAG_SEG6_ROUTE)
&& api_nh->type != NEXTHOP_TYPE_BLACKHOLE) {
if (IS_ZEBRA_DEBUG_RECV)
zlog_debug("%s: adding seg6", __func__);
nexthop_add_seg6(nexthop, &api_nh->seg6_segs);
}
if (IS_ZEBRA_DEBUG_RECV) {
labelbuf[0] = '\0';
nhbuf[0] = '\0';

View File

@ -1008,6 +1008,7 @@ void nhg_ctx_free(struct nhg_ctx **ctx)
nexthop_del_labels(nh);
nexthop_del_seg6local(nh);
nexthop_del_seg6(nh);
done:
XFREE(MTYPE_NHG_CTX, *ctx);
@ -1379,6 +1380,7 @@ static struct nhg_hash_entry *depends_find_singleton(const struct nexthop *nh,
/* The copy may have allocated labels; free them if necessary. */
nexthop_del_labels(&lookup);
nexthop_del_seg6local(&lookup);
nexthop_del_seg6(&lookup);
if (IS_ZEBRA_DEBUG_NHG_DETAIL)
zlog_debug("%s: nh %pNHv => %p (%u)",

View File

@ -662,6 +662,11 @@ static void show_route_nexthop_helper(struct vty *vty,
buf);
}
if (nexthop->nh_seg6_segs) {
inet_ntop(AF_INET6, nexthop->nh_seg6_segs, buf, sizeof(buf));
vty_out(vty, ", seg6 %s", buf);
}
if (nexthop->weight)
vty_out(vty, ", weight %u", nexthop->weight);
@ -685,6 +690,7 @@ static void show_nexthop_json_helper(json_object *json_nexthop,
json_object *json_labels = NULL;
json_object *json_backups = NULL;
json_object *json_seg6local = NULL;
json_object *json_seg6 = NULL;
int i;
json_object_int_add(json_nexthop, "flags",
@ -871,6 +877,13 @@ static void show_nexthop_json_helper(json_object *json_nexthop,
json_object_object_add(json_nexthop, "seg6local",
json_seg6local);
}
if (nexthop->nh_seg6_segs) {
json_seg6 = json_object_new_object();
inet_ntop(AF_INET6, nexthop->nh_seg6_segs, buf, sizeof(buf));
json_object_string_add(json_seg6, "segs", buf);
json_object_object_add(json_nexthop, "seg6", json_seg6);
}
}
static void vty_show_ip_route(struct vty *vty, struct route_node *rn,