From 76fb7ae4dea7604afe1185df91de941d9e3ce58f Mon Sep 17 00:00:00 2001 From: Hiroki Shirokura Date: Thu, 17 Dec 2020 23:43:01 +0900 Subject: [PATCH] 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 --- zebra/rt_netlink.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++ zebra/zapi_msg.c | 8 +++++++ zebra/zebra_nhg.c | 2 ++ zebra/zebra_vty.c | 13 ++++++++++++ 4 files changed, 75 insertions(+) diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 2ddda7449c..00eb0b6644 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) diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index fa6a4cfca7..25c51e2227 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -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'; diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index ddd37b4df7..84ce97b008 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -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)", diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index c178ce075c..fae443ca2e 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -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, -- 2.39.5