]> git.puffer.fish Git - mirror/frr.git/commitdiff
fpm: add next hop group support
authorRafael Zalamena <rzalamena@opensourcerouting.org>
Tue, 5 May 2020 13:54:06 +0000 (10:54 -0300)
committerRafael Zalamena <rzalamena@opensourcerouting.org>
Tue, 5 May 2020 13:54:06 +0000 (10:54 -0300)
Add support for the new kernel messages: `RTM_NEWNEXTHOP` and
`RTM_DELNEXTHOP`.

Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
zebra/dplane_fpm_nl.c
zebra/rt_netlink.c
zebra/rt_netlink.h

index bf8042efe5afc4a4010701e65d1efc9ef7cba637..d93a5b03cd536b17753a8c60a353f9d8bf389bfc 100644 (file)
@@ -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:
index 882babec810a1f1df1f66e32dda71a56ddff3e02..713fc1a465c32e67173adad75cf305ce23a80bac 100644 (file)
@@ -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);
index a364d305c5daec6d0b682b3e3a2ef9d743ac4819..5d76d1e67592618b2c4b67c33557b92f50e0ca43 100644 (file)
@@ -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);