summaryrefslogtreecommitdiffstats
path: root/zebra/rt_netlink.c
diff options
context:
space:
mode:
authorHiroki Shirokura <slank.dev@gmail.com>2020-12-17 15:43:01 +0100
committerMark Stapp <mjs@voltanet.io>2021-06-02 16:24:48 +0200
commit76fb7ae4dea7604afe1185df91de941d9e3ce58f (patch)
tree136d629c32287630a959bc687294baa9c5964d9c /zebra/rt_netlink.c
parentlib: add new nexthop's attributes seg6 (step3) (diff)
downloadfrr-76fb7ae4dea7604afe1185df91de941d9e3ce58f.tar.xz
frr-76fb7ae4dea7604afe1185df91de941d9e3ce58f.zip
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>
Diffstat (limited to 'zebra/rt_netlink.c')
-rw-r--r--zebra/rt_netlink.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 2ddda7449..00eb0b664 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -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)