From 9a4280b2b7451abc47f6d63e96b469611757be5b Mon Sep 17 00:00:00 2001 From: Dmytro Shytyi Date: Fri, 29 Dec 2023 14:40:48 +0100 Subject: [PATCH] zebra: add end.b6.encaps to rt_netlink Introduce the End.B6.Encaps in the rt_netlink code. Signed-off-by: Dmytro Shytyi Signed-off-by: Philippe Guibert --- lib/nexthop.c | 1 + zebra/rt_netlink.c | 77 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 73 insertions(+), 5 deletions(-) diff --git a/lib/nexthop.c b/lib/nexthop.c index fce4d39e0085..7d40d9fe03ab 100644 --- a/lib/nexthop.c +++ b/lib/nexthop.c @@ -899,6 +899,7 @@ void nexthop_copy_no_recurse(struct nexthop *copy, if (nexthop->nh_srv6) { if (nexthop->nh_srv6->seg6local_action == ZEBRA_SEG6_LOCAL_ACTION_END_B6_ENCAP && + nexthop->nh_srv6->seg6_segs && nexthop->nh_srv6->seg6_segs->num_segs > 1) nexthop_add_srv6_seg6local(copy, nexthop->nh_srv6 diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 7cba5a653681..3f69f83c0807 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -80,7 +80,7 @@ DEFINE_MTYPE_STATIC(LIB, NH_SRV6, "Nexthop srv6"); -static vlanid_t filter_vlan = 0; +static vlanid_t filter_vlan; /* We capture whether the current kernel supports nexthop ids; by * default, we'll use them if possible. There's also a configuration @@ -94,6 +94,12 @@ struct gw_family_t { 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 struct in_addr ipv4_ll; @@ -971,6 +977,7 @@ int netlink_route_change_read_unicast_internal(struct nlmsghdr *h, } afi_t afi = AFI_IP; + if (rtm->rtm_family == AF_INET6) afi = AFI_IP6; @@ -1084,7 +1091,7 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, NULL); } -static struct mcast_route_data *mroute = NULL; +static struct mcast_route_data *mroute; static int netlink_route_change_read_multicast(struct nlmsghdr *h, ns_id_t ns_id, int startup) @@ -2665,6 +2672,58 @@ static bool _netlink_nexthop_build_group(struct nlmsghdr *n, size_t req_size, 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. * @@ -2967,6 +3026,11 @@ ssize_t netlink_nexthop_msg_encode(uint16_t cmd, ctx->table)) return 0; break; + case ZEBRA_SEG6_LOCAL_ACTION_END_B6_ENCAP: + netlink_nexthop_msg_encode_end_b6_encaps( + (struct buf_req *)req, + nh, buflen); + break; default: zlog_err("%s: unsupport seg6local behaviour action=%u", __func__, action); @@ -2982,7 +3046,9 @@ ssize_t netlink_nexthop_msg_encode(uint16_t cmd, if (nh->nh_srv6->seg6_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]; ssize_t tun_len; struct rtattr *nest; @@ -3759,7 +3825,8 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id) return 0; zif = (struct zebra_if *)ifp->info; - if ((br_if = zif->brslave_info.br_if) == NULL) { + br_if = zif->brslave_info.br_if; + if (br_if == NULL) { if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug( "%s AF_BRIDGE IF %s(%u) brIF %u - no bridge master", @@ -3797,7 +3864,7 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id) * so perform an implicit delete of any local entry (if it exists). */ if (h->nlmsg_type == RTM_NEWNEIGH) { - /* Drop "permanent" entries. */ + /* Drop "permanent" entries. */ if (!vni_mcast_grp && (ndm->ndm_state & NUD_PERMANENT)) { if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug(