]> git.puffer.fish Git - matthieu/frr.git/commitdiff
fpm: add toggle to enable/disable next hop groups
authorRafael Zalamena <rzalamena@opensourcerouting.org>
Tue, 5 May 2020 19:17:44 +0000 (16:17 -0300)
committerRafael Zalamena <rzalamena@opensourcerouting.org>
Tue, 5 May 2020 19:22:07 +0000 (16:22 -0300)
If you haven't migrated your FPM server to use next hop groups, it is
possible that you want to disable this feature. This commit implements
a toggle to enable/disable next hop groups usage (even if your Linux
kernel is not using it).

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

index 20a9644a84ccc6fd952fa34e480d63ef964ba614..88d5ab5cecab21e40720f43bafa41b7cfa16fc9f 100644 (file)
@@ -74,6 +74,7 @@ struct fpm_nl_ctx {
        bool connecting;
        bool rib_complete;
        bool rmac_complete;
+       bool use_nhg;
        struct sockaddr_storage addr;
 
        /* data plane buffers. */
@@ -146,6 +147,8 @@ enum fpm_nl_events {
        FNE_DISABLE,
        /* Reset counters. */
        FNE_RESET_COUNTERS,
+       /* Toggle next hop group feature. */
+       FNE_TOGGLE_NHG,
 };
 
 /*
@@ -259,6 +262,37 @@ DEFUN(no_fpm_set_address, no_fpm_set_address_cmd,
        return CMD_SUCCESS;
 }
 
+DEFUN(fpm_use_nhg, fpm_use_nhg_cmd,
+      "fpm use-next-hop-groups",
+      FPM_STR
+      "Use netlink next hop groups feature.\n")
+{
+       /* Already enabled. */
+       if (gfnc->use_nhg)
+               return CMD_SUCCESS;
+
+       thread_add_event(gfnc->fthread->master, fpm_process_event, gfnc,
+                        FNE_TOGGLE_NHG, &gfnc->t_event);
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(no_fpm_use_nhg, no_fpm_use_nhg_cmd,
+      "no fpm use-next-hop-groups",
+      NO_STR
+      FPM_STR
+      "Use netlink next hop groups feature.\n")
+{
+       /* Already disabled. */
+       if (!gfnc->use_nhg)
+               return CMD_SUCCESS;
+
+       thread_add_event(gfnc->fthread->master, fpm_process_event, gfnc,
+                        FNE_TOGGLE_NHG, &gfnc->t_event);
+
+       return CMD_SUCCESS;
+}
+
 DEFUN(fpm_reset_counters, fpm_reset_counters_cmd,
       "clear fpm counters",
       CLEAR_STR
@@ -372,6 +406,11 @@ static int fpm_write_config(struct vty *vty)
                break;
        }
 
+       if (!gfnc->use_nhg) {
+               vty_out(vty, "no fpm use-next-hop-groups\n");
+               written = 1;
+       }
+
        return written;
 }
 
@@ -492,9 +531,25 @@ static int fpm_write(struct thread *t)
 
                fnc->connecting = false;
 
-               /* Ask zebra main thread to start walking the RIB table. */
-               thread_add_timer(zrouter.master, fpm_nhg_send, fnc, 0,
-                                &fnc->t_nhgwalk);
+               /*
+                * Walk the route tables to send old information before starting
+                * to send updated information.
+                *
+                * NOTE 1:
+                * RIB table walk is called after the next group table walk
+                * ends.
+                *
+                * NOTE 2:
+                * Don't attempt to go through next hop group table if we were
+                * explictly told to not use it.
+                */
+               if (fnc->use_nhg)
+                       thread_add_timer(zrouter.master, fpm_nhg_send, fnc, 0,
+                                        &fnc->t_nhgwalk);
+               else
+                       thread_add_timer(zrouter.master, fpm_rib_send, fnc, 0,
+                                        &fnc->t_ribwalk);
+
                thread_add_timer(zrouter.master, fpm_rmac_send, fnc, 0,
                                 &fnc->t_rmacwalk);
        }
@@ -636,16 +691,27 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx)
        size_t nl_buf_len;
        ssize_t rv;
        uint64_t obytes, obytes_peak;
+       enum dplane_op_e op = dplane_ctx_get_op(ctx);
+
+       /*
+        * If we were configured to not use next hop groups, then quit as soon
+        * as possible.
+        */
+       if ((!fnc->use_nhg)
+           && (op == DPLANE_OP_NH_DELETE || op == DPLANE_OP_NH_INSTALL
+               || op == DPLANE_OP_NH_UPDATE))
+               return 0;
 
        nl_buf_len = 0;
 
        frr_mutex_lock_autounlock(&fnc->obuf_mutex);
 
-       switch (dplane_ctx_get_op(ctx)) {
+       switch (op) {
        case DPLANE_OP_ROUTE_UPDATE:
        case DPLANE_OP_ROUTE_DELETE:
                rv = netlink_route_multipath(RTM_DELROUTE, ctx, nl_buf,
-                                            sizeof(nl_buf), true);
+                                            sizeof(nl_buf), true,
+                                            fnc->use_nhg);
                if (rv <= 0) {
                        zlog_err("%s: netlink_route_multipath failed",
                                 __func__);
@@ -655,14 +721,14 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx)
                nl_buf_len = (size_t)rv;
 
                /* UPDATE operations need a INSTALL, otherwise just quit. */
-               if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_DELETE)
+               if (op == DPLANE_OP_ROUTE_DELETE)
                        break;
 
                /* FALL THROUGH */
        case DPLANE_OP_ROUTE_INSTALL:
-               rv = netlink_route_multipath(RTM_NEWROUTE, ctx,
-                                            &nl_buf[nl_buf_len],
-                                            sizeof(nl_buf) - nl_buf_len, true);
+               rv = netlink_route_multipath(
+                       RTM_NEWROUTE, ctx, &nl_buf[nl_buf_len],
+                       sizeof(nl_buf) - nl_buf_len, true, fnc->use_nhg);
                if (rv <= 0) {
                        zlog_err("%s: netlink_route_multipath failed",
                                 __func__);
@@ -1098,6 +1164,12 @@ static int fpm_process_event(struct thread *t)
                memset(&fnc->counters, 0, sizeof(fnc->counters));
                break;
 
+       case FNE_TOGGLE_NHG:
+               zlog_info("%s: toggle next hop groups support", __func__);
+               fnc->use_nhg = !fnc->use_nhg;
+               fpm_reconnect(fnc);
+               break;
+
        default:
                if (IS_ZEBRA_DEBUG_FPM)
                        zlog_debug("%s: unhandled event %d", __func__, event);
@@ -1126,6 +1198,9 @@ static int fpm_nl_start(struct zebra_dplane_provider *prov)
        TAILQ_INIT(&fnc->ctxqueue);
        pthread_mutex_init(&fnc->ctxqueue_mutex, NULL);
 
+       /* Set default values. */
+       fnc->use_nhg = true;
+
        return 0;
 }
 
@@ -1248,6 +1323,8 @@ static int fpm_nl_new(struct thread_master *tm)
        install_element(ENABLE_NODE, &fpm_reset_counters_cmd);
        install_element(CONFIG_NODE, &fpm_set_address_cmd);
        install_element(CONFIG_NODE, &no_fpm_set_address_cmd);
+       install_element(CONFIG_NODE, &fpm_use_nhg_cmd);
+       install_element(CONFIG_NODE, &no_fpm_use_nhg_cmd);
 
        return 0;
 }
index 713fc1a465c32e67173adad75cf305ce23a80bac..ecd9947a58aa3d65b2aabf1d7adfcba2cd6367cc 100644 (file)
@@ -1544,7 +1544,8 @@ static void netlink_route_nexthop_encap(struct nlmsghdr *n, size_t nlen,
  * Routing table change via netlink interface, using a dataplane context object
  */
 ssize_t netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx,
-                               uint8_t *data, size_t datalen, bool fpm)
+                               uint8_t *data, size_t datalen, bool fpm,
+                               bool force_nhg)
 {
        int bytelen;
        struct nexthop *nexthop = NULL;
@@ -1666,7 +1667,7 @@ ssize_t netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx,
                          RTA_PAYLOAD(rta));
        }
 
-       if (kernel_nexthops_supported()) {
+       if (kernel_nexthops_supported() || force_nhg) {
                /* Kernel supports nexthop objects */
                if (IS_ZEBRA_DEBUG_KERNEL)
                        zlog_debug(
@@ -2189,7 +2190,7 @@ enum zebra_dplane_result kernel_route_update(struct zebra_dplane_ctx *ctx)
                            !RSYSTEM_ROUTE(dplane_ctx_get_old_type(ctx))) {
                                netlink_route_multipath(RTM_DELROUTE, ctx,
                                                        nl_pkt, sizeof(nl_pkt),
-                                                       false);
+                                                       false, false);
                                netlink_talk_info(netlink_talk_filter,
                                                  (struct nlmsghdr *)nl_pkt,
                                                  dplane_ctx_get_ns(ctx), 0);
@@ -2210,7 +2211,7 @@ enum zebra_dplane_result kernel_route_update(struct zebra_dplane_ctx *ctx)
                        if (!RSYSTEM_ROUTE(dplane_ctx_get_old_type(ctx))) {
                                netlink_route_multipath(RTM_DELROUTE, ctx,
                                                        nl_pkt, sizeof(nl_pkt),
-                                                       false);
+                                                       false, false);
                                netlink_talk_info(netlink_talk_filter,
                                                  (struct nlmsghdr *)nl_pkt,
                                                  dplane_ctx_get_ns(ctx), 0);
@@ -2224,7 +2225,7 @@ enum zebra_dplane_result kernel_route_update(struct zebra_dplane_ctx *ctx)
 
        if (!RSYSTEM_ROUTE(dplane_ctx_get_type(ctx))) {
                netlink_route_multipath(cmd, ctx, nl_pkt, sizeof(nl_pkt),
-                                       false);
+                                       false, false);
                ret = netlink_talk_info(netlink_talk_filter,
                                        (struct nlmsghdr *)nl_pkt,
                                        dplane_ctx_get_ns(ctx), 0);
index 5d76d1e67592618b2c4b67c33557b92f50e0ca43..3048eea75dc845e3cbf2430bbc3fef2cfbe4ee7d 100644 (file)
@@ -68,7 +68,7 @@ extern int netlink_mpls_multipath(int cmd, struct zebra_dplane_ctx *ctx);
 
 extern ssize_t netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx,
                                       uint8_t *data, size_t datalen,
-                                      bool fpm);
+                                      bool fpm, bool force_nhg);
 extern ssize_t netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx,
                                         uint8_t *data, size_t datalen);