[ovs-dev] [PATCH v2 ovn 5/5] ovn: integrate bfd for static routes

Lorenzo Bianconi lorenzo.bianconi at redhat.com
Fri Dec 11 12:25:47 UTC 2020


Introduce the --bfd option for ovn static routes in order to
check if the next-hop is properly running using the BFD
protocol. E.g:

$ovn-nbctl --bfd lr-route-add lr0 10.0.0.0/8 172.16.0.50

Add BFD static routes tests in system-ovn.at/ovn-nbctl.at.

Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi at redhat.com>
---
 NEWS                      |  3 ++-
 northd/ovn-northd.c       | 41 +++++++++++++++++++++++++++++----------
 tests/ovn-nbctl.at        |  5 ++++-
 tests/system-ovn.at       |  5 +++++
 utilities/ovn-nbctl.8.xml |  6 ++++++
 utilities/ovn-nbctl.c     | 18 +++++++++++------
 6 files changed, 60 insertions(+), 18 deletions(-)

diff --git a/NEWS b/NEWS
index 178766f7a..769e52366 100644
--- a/NEWS
+++ b/NEWS
@@ -24,7 +24,8 @@ OVN v20.12.0 - xx xxx xxxx
      significantly decrease size of a Southbound DB.  However, in some cases,
      it could have performance penalty for ovn-controller.  Disabled by
      default.
-   - BFD protocol support according to RFC880 [0]
+   - BFD protocol support according to RFC880 [0]. Introduce next-hop BFD
+     availability check for OVN static routes.
      [0] https://tools.ietf.org/html/rfc5880)
 
 OVN v20.09.0 - 28 Sep 2020
diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
index 21e04cdfe..83a86aaab 100644
--- a/northd/ovn-northd.c
+++ b/northd/ovn-northd.c
@@ -7628,7 +7628,7 @@ route_hash(struct parsed_route *route)
 /* Parse and validate the route. Return the parsed route if successful.
  * Otherwise return NULL. */
 static struct parsed_route *
-parsed_routes_add(struct ovs_list *routes,
+parsed_routes_add(struct northd_context *ctx, struct ovs_list *routes,
                   const struct nbrec_logical_router_static_route *route)
 {
     /* Verify that the next hop is an IP address with an all-ones mask. */
@@ -7670,6 +7670,23 @@ parsed_routes_add(struct ovs_list *routes,
         return NULL;
     }
 
+    if (smap_get_bool(&route->options, "bfd", false)) {
+        const struct nbrec_bfd *nb_bt;
+        int online = -1;
+
+        NBREC_BFD_FOR_EACH (nb_bt, ctx->ovnnb_idl) {
+            if (!strcmp(nb_bt->dst_ip, route->nexthop)) {
+                online = strcmp(nb_bt->status, "down");
+                if (online) {
+                    break;
+                }
+            }
+        }
+        if (!online) {
+            return NULL;
+        }
+    }
+
     struct parsed_route *pr = xzalloc(sizeof *pr);
     pr->prefix = prefix;
     pr->plen = plen;
@@ -10225,9 +10242,10 @@ build_ip_routing_flows_for_lrouter_port(
 }
 
 static void
-build_static_route_flows_for_lrouter(
-        struct ovn_datapath *od, struct hmap *lflows,
-        struct hmap *ports)
+build_static_route_flows_for_lrouter(struct northd_context *ctx,
+                                     struct ovn_datapath *od,
+                                     struct hmap *lflows,
+                                     struct hmap *ports)
 {
     if (od->nbr) {
         ovn_lflow_add(lflows, od, S_ROUTER_IN_IP_ROUTING_ECMP, 150,
@@ -10239,7 +10257,8 @@ build_static_route_flows_for_lrouter(
         struct ecmp_groups_node *group;
         for (int i = 0; i < od->nbr->n_static_routes; i++) {
             struct parsed_route *route =
-                parsed_routes_add(&parsed_routes, od->nbr->static_routes[i]);
+                parsed_routes_add(ctx, &parsed_routes,
+                                  od->nbr->static_routes[i]);
             if (!route) {
                 continue;
             }
@@ -11244,7 +11263,8 @@ struct lswitch_flow_build_info {
  */
 
 static void
-build_lswitch_and_lrouter_iterate_by_od(struct ovn_datapath *od,
+build_lswitch_and_lrouter_iterate_by_od(struct northd_context *ctx,
+                                        struct ovn_datapath *od,
                                         struct lswitch_flow_build_info *lsi)
 {
     /* Build Logical Switch Flows. */
@@ -11260,7 +11280,7 @@ build_lswitch_and_lrouter_iterate_by_od(struct ovn_datapath *od,
     build_neigh_learning_flows_for_lrouter(od, lsi->lflows, &lsi->match,
                                            &lsi->actions);
     build_ND_RA_flows_for_lrouter(od, lsi->lflows);
-    build_static_route_flows_for_lrouter(od, lsi->lflows, lsi->ports);
+    build_static_route_flows_for_lrouter(ctx, od, lsi->lflows, lsi->ports);
     build_mcast_lookup_flows_for_lrouter(od, lsi->lflows, &lsi->match,
                                          &lsi->actions);
     build_ingress_policy_flows_for_lrouter(od, lsi->lflows, lsi->ports);
@@ -11303,7 +11323,8 @@ build_lswitch_and_lrouter_iterate_by_op(struct ovn_port *op,
 }
 
 static void
-build_lswitch_and_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
+build_lswitch_and_lrouter_flows(struct northd_context *ctx,
+                                struct hmap *datapaths, struct hmap *ports,
                                 struct hmap *port_groups, struct hmap *lflows,
                                 struct hmap *mcgroups,
                                 struct hmap *igmp_groups,
@@ -11332,7 +11353,7 @@ build_lswitch_and_lrouter_flows(struct hmap *datapaths, struct hmap *ports,
      * will move here and will be reogranized by iterator type.
      */
     HMAP_FOR_EACH (od, key_node, datapaths) {
-        build_lswitch_and_lrouter_iterate_by_od(od, &lsi);
+        build_lswitch_and_lrouter_iterate_by_od(ctx, od, &lsi);
     }
     HMAP_FOR_EACH (op, key_node, ports) {
         build_lswitch_and_lrouter_iterate_by_op(op, &lsi);
@@ -11433,7 +11454,7 @@ build_lflows(struct northd_context *ctx, struct hmap *datapaths,
 {
     struct hmap lflows = HMAP_INITIALIZER(&lflows);
 
-    build_lswitch_and_lrouter_flows(datapaths, ports,
+    build_lswitch_and_lrouter_flows(ctx, datapaths, ports,
                                     port_groups, &lflows, mcgroups,
                                     igmp_groups, meter_groups, lbs);
 
diff --git a/tests/ovn-nbctl.at b/tests/ovn-nbctl.at
index 01edfcbc1..46366500e 100644
--- a/tests/ovn-nbctl.at
+++ b/tests/ovn-nbctl.at
@@ -1617,7 +1617,10 @@ IPv6 Routes
             2001:db8::/64        2001:db8:0:f102::1 dst-ip lp0
           2001:db8:1::/64        2001:db8:0:f103::1 dst-ip
                      ::/0        2001:db8:0:f101::1 dst-ip
-])])
+])
+
+AT_CHECK([ovn-nbctl --bfd lr-route-add lr0 100.0.0.1/24 192.168.0.1])])
+
 
 dnl ---------------------------------------------------------------------
 
diff --git a/tests/system-ovn.at b/tests/system-ovn.at
index d8c21404b..6bc1988e1 100644
--- a/tests/system-ovn.at
+++ b/tests/system-ovn.at
@@ -5612,6 +5612,9 @@ AT_CHECK([ovn-nbctl list bfd | awk -F: '/status/{print substr($2,2)}'], [0], [dn
 up
 ])
 
+ovn-nbctl --bfd lr-route-add R1 100.0.0.0/8 172.16.1.50
+OVS_WAIT_UNTIL([ovn-sbctl dump-flows R1 | grep 'match=(ip4.dst == 100.0.0.0/8)' | grep -q 172.16.1.50])
+
 NS_CHECK_EXEC([server], [bfdd-control stop], [0], [dnl
 stopping
 ])
@@ -5621,6 +5624,8 @@ AT_CHECK([ovn-nbctl list bfd | awk -F: '/status/{print substr($2,2)}'], [0], [dn
 down
 ])
 
+OVS_WAIT_UNTIL([test "$(ovn-sbctl dump-flows R1 | grep 'match=(ip4.dst == 100.0.0.0/8)' | grep 172.16.1.50)" = ""])
+
 kill $(pidof ovn-controller)
 
 as ovn-sb
diff --git a/utilities/ovn-nbctl.8.xml b/utilities/ovn-nbctl.8.xml
index e5a35f307..3410c6137 100644
--- a/utilities/ovn-nbctl.8.xml
+++ b/utilities/ovn-nbctl.8.xml
@@ -659,6 +659,7 @@
     <dl>
       <dt>[<code>--may-exist</code>] [<code>--policy</code>=<var>POLICY</var>]
         [<code>--ecmp</code>] [<code>--ecmp-symmetric-reply</code>]
+        [<code>--bfd</code>]
         <code>lr-route-add</code> <var>router</var>
         <var>prefix</var> <var>nexthop</var> [<var>port</var>]</dt>
       <dd>
@@ -695,6 +696,11 @@
           it is not necessary to set both.
         </p>
 
+        <p>
+          The <code>--bfd</code> option allows to check if the next-hop is
+          running using BFD protocol
+        </p>
+
         <p>
           It is an error if a route with <var>prefix</var> and
           <var>POLICY</var> already exists, unless <code>--may-exist</code>,
diff --git a/utilities/ovn-nbctl.c b/utilities/ovn-nbctl.c
index 3a95f6b1f..9d82e2cfa 100644
--- a/utilities/ovn-nbctl.c
+++ b/utilities/ovn-nbctl.c
@@ -699,7 +699,8 @@ Logical router port commands:\n\
                             ('overlay' or 'bridged')\n\
 \n\
 Route commands:\n\
-  [--policy=POLICY] [--ecmp] [--ecmp-symmetric-reply] lr-route-add ROUTER \n\
+  [--policy=POLICY] [--ecmp] [--ecmp-symmetric-reply] [--bfd] \
+  lr-route-add ROUTER \n\
                             PREFIX NEXTHOP [PORT]\n\
                             add a route to ROUTER\n\
   [--policy=POLICY] lr-route-del ROUTER [PREFIX [NEXTHOP [PORT]]]\n\
@@ -3932,6 +3933,7 @@ nbctl_lr_route_add(struct ctl_context *ctx)
         goto cleanup;
     }
 
+    bool bfd = shash_find(&ctx->options, "--bfd") != NULL;
     bool may_exist = shash_find(&ctx->options, "--may-exist") != NULL;
     bool ecmp_symmetric_reply = shash_find(&ctx->options,
                                            "--ecmp-symmetric-reply") != NULL;
@@ -4002,12 +4004,16 @@ nbctl_lr_route_add(struct ctl_context *ctx)
         nbrec_logical_router_static_route_set_policy(route, policy);
     }
 
+    struct smap options;
+    smap_init(&options);
     if (ecmp_symmetric_reply) {
-        const struct smap options = SMAP_CONST1(&options,
-                                                "ecmp_symmetric_reply",
-                                                "true");
-        nbrec_logical_router_static_route_set_options(route, &options);
+        smap_add(&options, "ecmp_symmetric_reply", "true");
     }
+    if (bfd) {
+        smap_add(&options, "bfd", "true");
+    }
+    nbrec_logical_router_static_route_set_options(route, &options);
+    smap_destroy(&options);
 
     nbrec_logical_router_verify_static_routes(lr);
     struct nbrec_logical_router_static_route **new_routes
@@ -6566,7 +6572,7 @@ static const struct ctl_command_syntax nbctl_commands[] = {
     /* logical router route commands. */
     { "lr-route-add", 3, 4, "ROUTER PREFIX NEXTHOP [PORT]", NULL,
       nbctl_lr_route_add, NULL, "--may-exist,--ecmp,--ecmp-symmetric-reply,"
-      "--policy=", RW },
+      "--bfd,--policy=", RW },
     { "lr-route-del", 1, 4, "ROUTER [PREFIX [NEXTHOP [PORT]]]", NULL,
       nbctl_lr_route_del, NULL, "--if-exists,--policy=", RW },
     { "lr-route-list", 1, 1, "ROUTER", NULL, nbctl_lr_route_list, NULL,
-- 
2.29.2



More information about the dev mailing list