From: Rafael Zalamena Date: Tue, 5 May 2020 13:54:06 +0000 (-0300) Subject: fpm: add next hop group support X-Git-Tag: base_7.5~368^2~4 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=e9a1cd931b61a55f778259076912bc4163cd3f0b;p=matthieu%2Ffrr.git fpm: add next hop group support Add support for the new kernel messages: `RTM_NEWNEXTHOP` and `RTM_DELNEXTHOP`. Signed-off-by: Rafael Zalamena --- diff --git a/zebra/dplane_fpm_nl.c b/zebra/dplane_fpm_nl.c index bf8042efe5..d93a5b03cd 100644 --- a/zebra/dplane_fpm_nl.c +++ b/zebra/dplane_fpm_nl.c @@ -676,9 +676,28 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx) nl_buf_len = (size_t)rv; break; + case DPLANE_OP_NH_DELETE: + rv = netlink_nexthop_encode(RTM_DELNEXTHOP, ctx, nl_buf, + sizeof(nl_buf)); + if (rv <= 0) { + zlog_err("%s: netlink_nexthop_encode failed", __func__); + return 0; + } + + nl_buf_len = (size_t)rv; + break; case DPLANE_OP_NH_INSTALL: case DPLANE_OP_NH_UPDATE: - case DPLANE_OP_NH_DELETE: + rv = netlink_nexthop_encode(RTM_NEWNEXTHOP, ctx, nl_buf, + sizeof(nl_buf)); + if (rv <= 0) { + zlog_err("%s: netlink_nexthop_encode failed", __func__); + return 0; + } + + nl_buf_len = (size_t)rv; + break; + case DPLANE_OP_LSP_INSTALL: case DPLANE_OP_LSP_UPDATE: case DPLANE_OP_LSP_DELETE: diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 882babec81..713fc1a465 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -1946,43 +1946,43 @@ static void _netlink_nexthop_build_group(struct nlmsghdr *n, size_t req_size, } /** - * netlink_nexthop() - Nexthop change via the netlink interface + * Next hop packet encoding helper function. * - * @ctx: Dataplane ctx + * \param[in] cmd netlink command. + * \param[in] ctx dataplane context (information snapshot). + * \param[out] buf buffer to hold the packet. + * \param[in] buflen amount of buffer bytes. * - * Return: Result status + * \returns -1 on failure or the number of bytes written to buf. */ -static int netlink_nexthop(int cmd, struct zebra_dplane_ctx *ctx) +ssize_t +netlink_nexthop_encode(uint16_t cmd, const struct zebra_dplane_ctx *ctx, + void *buf, size_t buflen) { struct { struct nlmsghdr n; struct nhmsg nhm; - char buf[NL_PKT_BUF_SIZE]; - } req; + char buf[]; + } *req = buf; mpls_lse_t out_lse[MPLS_MAX_LABELS]; char label_buf[256]; int num_labels = 0; - size_t req_size = sizeof(req); - - /* Nothing to do if the kernel doesn't support nexthop objects */ - if (!kernel_nexthops_supported()) - return 0; label_buf[0] = '\0'; - memset(&req, 0, req_size); + memset(req, 0, buflen); - req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct nhmsg)); - req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; + req->n.nlmsg_len = NLMSG_LENGTH(sizeof(struct nhmsg)); + req->n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; if (cmd == RTM_NEWNEXTHOP) - req.n.nlmsg_flags |= NLM_F_REPLACE; + req->n.nlmsg_flags |= NLM_F_REPLACE; - req.n.nlmsg_type = cmd; - req.n.nlmsg_pid = dplane_ctx_get_ns(ctx)->nls.snl.nl_pid; + req->n.nlmsg_type = cmd; + req->n.nlmsg_pid = dplane_ctx_get_ns(ctx)->nls.snl.nl_pid; - req.nhm.nh_family = AF_UNSPEC; + req->nhm.nh_family = AF_UNSPEC; /* TODO: Scope? */ uint32_t id = dplane_ctx_get_nhe_id(ctx); @@ -1994,7 +1994,7 @@ static int netlink_nexthop(int cmd, struct zebra_dplane_ctx *ctx) return -1; } - addattr32(&req.n, req_size, NHA_ID, id); + addattr32(&req->n, buflen, NHA_ID, id); if (cmd == RTM_NEWNEXTHOP) { /* @@ -2005,7 +2005,7 @@ static int netlink_nexthop(int cmd, struct zebra_dplane_ctx *ctx) */ if (dplane_ctx_get_nhe_nh_grp_count(ctx)) _netlink_nexthop_build_group( - &req.n, req_size, id, + &req->n, buflen, id, dplane_ctx_get_nhe_nh_grp(ctx), dplane_ctx_get_nhe_nh_grp_count(ctx)); else { @@ -2014,23 +2014,23 @@ static int netlink_nexthop(int cmd, struct zebra_dplane_ctx *ctx) afi_t afi = dplane_ctx_get_nhe_afi(ctx); if (afi == AFI_IP) - req.nhm.nh_family = AF_INET; + req->nhm.nh_family = AF_INET; else if (afi == AFI_IP6) - req.nhm.nh_family = AF_INET6; + req->nhm.nh_family = AF_INET6; switch (nh->type) { case NEXTHOP_TYPE_IPV4: case NEXTHOP_TYPE_IPV4_IFINDEX: - addattr_l(&req.n, req_size, NHA_GATEWAY, + addattr_l(&req->n, buflen, NHA_GATEWAY, &nh->gate.ipv4, IPV4_MAX_BYTELEN); break; case NEXTHOP_TYPE_IPV6: case NEXTHOP_TYPE_IPV6_IFINDEX: - addattr_l(&req.n, req_size, NHA_GATEWAY, + addattr_l(&req->n, buflen, NHA_GATEWAY, &nh->gate.ipv6, IPV6_MAX_BYTELEN); break; case NEXTHOP_TYPE_BLACKHOLE: - addattr_l(&req.n, req_size, NHA_BLACKHOLE, NULL, + addattr_l(&req->n, buflen, NHA_BLACKHOLE, NULL, 0); /* Blackhole shouldn't have anymore attributes */ @@ -2047,10 +2047,10 @@ static int netlink_nexthop(int cmd, struct zebra_dplane_ctx *ctx) return -1; } - addattr32(&req.n, req_size, NHA_OIF, nh->ifindex); + addattr32(&req->n, buflen, NHA_OIF, nh->ifindex); if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_ONLINK)) - req.nhm.nh_flags |= RTNH_F_ONLINK; + req->nhm.nh_flags |= RTNH_F_ONLINK; num_labels = build_label_stack(nh->nh_label, out_lse, @@ -2064,10 +2064,10 @@ static int netlink_nexthop(int cmd, struct zebra_dplane_ctx *ctx) /* * TODO: MPLS unsupported for now in kernel. */ - if (req.nhm.nh_family == AF_MPLS) + if (req->nhm.nh_family == AF_MPLS) goto nexthop_done; #if 0 - addattr_l(&req.n, req_size, NHA_NEWDST, + addattr_l(&req->n, buflen, NHA_NEWDST, &out_lse, num_labels * sizeof(mpls_lse_t)); @@ -2076,16 +2076,16 @@ static int netlink_nexthop(int cmd, struct zebra_dplane_ctx *ctx) struct rtattr *nest; uint16_t encap = LWTUNNEL_ENCAP_MPLS; - addattr_l(&req.n, req_size, + addattr_l(&req->n, buflen, NHA_ENCAP_TYPE, &encap, sizeof(uint16_t)); - nest = addattr_nest(&req.n, req_size, + nest = addattr_nest(&req->n, buflen, NHA_ENCAP); - addattr_l(&req.n, req_size, + addattr_l(&req->n, buflen, MPLS_IPTUNNEL_DST, &out_lse, num_labels * sizeof(mpls_lse_t)); - addattr_nest_end(&req.n, nest); + addattr_nest_end(&req->n, nest); } } @@ -2098,7 +2098,8 @@ nexthop_done: nh->vrf_id, label_buf); } - req.nhm.nh_protocol = zebra2proto(dplane_ctx_get_nhe_type(ctx)); + req->nhm.nh_protocol = + zebra2proto(dplane_ctx_get_nhe_type(ctx)); } else if (cmd != RTM_DELNEXTHOP) { flog_err( @@ -2112,8 +2113,7 @@ nexthop_done: zlog_debug("%s: %s, id=%u", __func__, nl_msg_type_to_str(cmd), id); - return netlink_talk_info(netlink_talk_filter, &req.n, - dplane_ctx_get_ns(ctx), 0); + return NLMSG_ALIGN(req->n.nlmsg_len); } /** @@ -2128,6 +2128,7 @@ enum zebra_dplane_result kernel_nexthop_update(struct zebra_dplane_ctx *ctx) enum dplane_op_e op; int cmd = 0; int ret = 0; + char buf[NL_PKT_BUF_SIZE]; op = dplane_ctx_get_op(ctx); if (op == DPLANE_OP_NH_INSTALL || op == DPLANE_OP_NH_UPDATE) @@ -2141,7 +2142,15 @@ enum zebra_dplane_result kernel_nexthop_update(struct zebra_dplane_ctx *ctx) return ZEBRA_DPLANE_REQUEST_FAILURE; } - ret = netlink_nexthop(cmd, ctx); + /* Nothing to do if the kernel doesn't support nexthop objects */ + if (!kernel_nexthops_supported()) + return ZEBRA_DPLANE_REQUEST_SUCCESS; + + if (netlink_nexthop_encode(cmd, ctx, buf, sizeof(buf)) > 0) + ret = netlink_talk_info(netlink_talk_filter, (void *)&buf, + dplane_ctx_get_ns(ctx), 0); + else + ret = 0; return (ret == 0 ? ZEBRA_DPLANE_REQUEST_SUCCESS : ZEBRA_DPLANE_REQUEST_FAILURE); diff --git a/zebra/rt_netlink.h b/zebra/rt_netlink.h index a364d305c5..5d76d1e675 100644 --- a/zebra/rt_netlink.h +++ b/zebra/rt_netlink.h @@ -78,6 +78,9 @@ extern int netlink_route_read(struct zebra_ns *zns); extern int netlink_nexthop_change(struct nlmsghdr *h, ns_id_t ns_id, int startup); extern int netlink_nexthop_read(struct zebra_ns *zns); +extern ssize_t netlink_nexthop_encode(uint16_t cmd, + const struct zebra_dplane_ctx *ctx, + void *buf, size_t buflen); extern int netlink_neigh_change(struct nlmsghdr *h, ns_id_t ns_id); extern int netlink_macfdb_read(struct zebra_ns *zns);