]> git.puffer.fish Git - mirror/frr.git/commitdiff
zebra: Implement call back for route install/delete success/fail
authorDonald Sharp <sharpd@cumulusnetworks.com>
Tue, 14 Nov 2017 14:57:37 +0000 (09:57 -0500)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 29 Nov 2017 17:56:34 +0000 (12:56 -0500)
When a route is installed or deleted into the kernel allow a
callback mechanism to handle the success/failure of
the kernel call.

This separation is to allow us to do these things:

1) In the future create a true pthread to handle route
install/deletes.  This way we can schedule these
events in a smarter fashion

2) Allow us to use a common southbound api for route
install and deletion.

Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
zebra/rib.h
zebra/rt.h
zebra/rt_netlink.c
zebra/rt_socket.c
zebra/zebra_rib.c

index 61beebb40938a80a09b155c469d18347ba1c85c6..818844cb6d55e345a1f686eb7d3f2cad455dba8c 100644 (file)
@@ -285,9 +285,9 @@ extern int zebra_check_addr(struct prefix *p);
 extern void rib_addnode(struct route_node *rn, struct route_entry *re,
                        int process);
 extern void rib_delnode(struct route_node *rn, struct route_entry *re);
-extern int rib_install_kernel(struct route_node *rn, struct route_entry *re,
-                             struct route_entry *old);
-extern int rib_uninstall_kernel(struct route_node *rn, struct route_entry *re);
+extern void rib_install_kernel(struct route_node *rn, struct route_entry *re,
+                              struct route_entry *old);
+extern void rib_uninstall_kernel(struct route_node *rn, struct route_entry *re);
 
 /* NOTE:
  * All rib_add function will not just add prefix into RIB, but
index 3ce15e964022377ebe00f4d4e0ab6bd50a047387..2581b9012c8759f64bd2e993ff1572e71220c199 100644 (file)
  * success failure should be handled by the caller.
  */
 
-extern int kernel_route_rib(struct prefix *, struct prefix *,
-                           struct route_entry *, struct route_entry *);
+
+enum southbound_results {
+       SOUTHBOUND_INSTALL_SUCCESS,
+       SOUTHBOUND_INSTALL_FAILURE,
+       SOUTHBOUND_DELETE_SUCCESS,
+       SOUTHBOUND_DELETE_FAILURE,
+};
+
+/*
+ * Install/delete the specified prefix p from the kernel
+ *
+ * old = NULL, new = pointer - Install new
+ * old = pointer, new = pointer - Route replace Old w/ New
+ * old = pointer, new = NULL, - Route Delete
+ *
+ * Please note not all kernels support route replace
+ * semantics so we will end up with a delete than
+ * a re-add.
+ */
+extern void kernel_route_rib(struct prefix *p, struct prefix *src_p,
+                            struct route_entry *old, struct route_entry *new);
+
+/*
+ * So route install/failure may not be immediately known
+ * so let's separate it out and allow the result to
+ * be passed back up.
+ */
+extern void kernel_route_rib_pass_fail(struct prefix *p,
+                                      struct route_entry *re,
+                                      enum southbound_results res);
 
 extern int kernel_address_add_ipv4(struct interface *, struct connected *);
 extern int kernel_address_delete_ipv4(struct interface *, struct connected *);
index 3830e1fbdefbe24302ee474682906c1729422dbf..8afa47753f3b8ce59f7eacfacb4d9a6959aa5861 100644 (file)
@@ -1598,33 +1598,51 @@ int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *in)
        return suc;
 }
 
-int kernel_route_rib(struct prefix *p, struct prefix *src_p,
-                    struct route_entry *old, struct route_entry *new)
+void kernel_route_rib(struct prefix *p, struct prefix *src_p,
+                     struct route_entry *old, struct route_entry *new)
 {
+       int ret = 0;
+
        assert(old || new);
 
-       if (!old && new)
-               return netlink_route_multipath(RTM_NEWROUTE, p, src_p, new, 0);
-       if (old && !new)
-               return netlink_route_multipath(RTM_DELROUTE, p, src_p, old, 0);
+       if (new) {
+               if (p->family == AF_INET)
+                       ret = netlink_route_multipath(RTM_NEWROUTE, p, src_p,
+                                                     new, (old) ? 1 : 0);
+               else {
+                       /*
+                        * So v6 route replace semantics are not in
+                        * the kernel at this point as I understand it.
+                        * So let's do a delete than an add.
+                        * In the future once v6 route replace semantics
+                        * are in we can figure out what to do here to
+                        * allow working with old and new kernels.
+                        *
+                        * I'm also intentionally ignoring the failure case
+                        * of the route delete.  If that happens yeah we're
+                        * screwed.
+                        */
+                       if (old)
+                               netlink_route_multipath(RTM_DELROUTE, p,
+                                                       src_p, old, 0);
+                       ret = netlink_route_multipath(RTM_NEWROUTE, p,
+                                                     src_p, new, 0);
+               }
+               kernel_route_rib_pass_fail(p, new,
+                                          (!ret) ?
+                                          SOUTHBOUND_INSTALL_SUCCESS :
+                                          SOUTHBOUND_INSTALL_FAILURE);
+               return;
+       }
 
-       if (p->family == AF_INET)
-               return netlink_route_multipath(RTM_NEWROUTE, p, src_p, new, 1);
+       if (old) {
+               ret = netlink_route_multipath(RTM_DELROUTE, p, src_p, old, 0);
 
-       /*
-        * So v6 route replace semantics are not in the kernel at this
-        * point as I understand it.
-        * So let's do a delete than an add.
-        * In the future once v6 route replace semantics are in
-        * we can figure out what to do here to allow working
-        * with old and new kernels.
-        *
-        * I'm also intentionally ignoring the failure case
-        * of the route delete.  If that happens yeah we're
-        * screwed.
-        */
-       netlink_route_multipath(RTM_DELROUTE, p, src_p, old, 0);
-       return netlink_route_multipath(RTM_NEWROUTE, p, src_p, new, 0);
+               kernel_route_rib_pass_fail(p, old,
+                                          (!ret) ?
+                                          SOUTHBOUND_DELETE_SUCCESS :
+                                          SOUTHBOUND_DELETE_FAILURE);
+       }
 }
 
 int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla,
index e5887949470d6b8e70dc07ee5aa2601ed4947e90..4393c87d4595b089a3e84026f1b5f628cd80ae31 100644 (file)
@@ -387,8 +387,8 @@ static int kernel_rtm(int cmd, struct prefix *p, struct route_entry *re)
        return 0;
 }
 
-int kernel_route_rib(struct prefix *p, struct prefix *src_p,
-                    struct route_entry *old, struct route_entry *new)
+void kernel_route_rib(struct prefix *p, struct prefix *src_p,
+                     struct route_entry *old, struct route_entry *new)
 {
        int route = 0;
 
@@ -409,7 +409,17 @@ int kernel_route_rib(struct prefix *p, struct prefix *src_p,
        if (zserv_privs.change(ZPRIVS_LOWER))
                zlog_err("Can't lower privileges");
 
-       return route;
+       if (new) {
+               kernel_route_rib_pass_fail(p, new,
+                                          (!route) ?
+                                          SOUTHBOUND_INSTALL_SUCCESS :
+                                          SOUTBHOUND_INSTALL_FAILURE);
+       } else {
+               kernel_route_rib_pass_fail(p, old,
+                                          (!route) ?
+                                          SOUTHBOUND_DELETE_SUCCESS :
+                                          SOUTHBOUND_DELETE_FAILURE);
+       }
 }
 
 int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla,
index 791f319120be91c1a175511340c6e95bf54b631a..58b69659955cf2328e05592c225963376685af0d 100644 (file)
@@ -993,13 +993,49 @@ int zebra_rib_labeled_unicast(struct route_entry *re)
        return 1;
 }
 
+void kernel_route_rib_pass_fail(struct prefix *p, struct route_entry *re,
+                               enum southbound_results res)
+{
+       struct nexthop *nexthop;
+       char buf[PREFIX_STRLEN];
+
+       switch (res) {
+       case SOUTHBOUND_INSTALL_SUCCESS:
+               for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
+                       if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
+                               continue;
+
+                       if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
+                               SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
+                       else
+                               UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
+               }
+               zsend_route_notify_owner(re->type, re->instance, re->vrf_id,
+                                        p, ZAPI_ROUTE_INSTALLED);
+               break;
+       case SOUTHBOUND_INSTALL_FAILURE:
+               zsend_route_notify_owner(re->type, re->instance, re->vrf_id,
+                                        p, ZAPI_ROUTE_FAIL_INSTALL);
+               zlog_warn("%u:%s: Route install failed", re->vrf_id,
+                         prefix2str(p, buf, sizeof(buf)));
+               break;
+       case SOUTHBOUND_DELETE_SUCCESS:
+               for (ALL_NEXTHOPS(re->nexthop, nexthop))
+                       UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
+               break;
+       case SOUTHBOUND_DELETE_FAILURE:
+               zlog_warn("%u:%s: Route Deletion failure", re->vrf_id,
+                         prefix2str(p, buf, sizeof(buf)));
+               break;
+       }
+}
+
 /* Update flag indicates whether this is a "replace" or not. Currently, this
  * is only used for IPv4.
  */
-int rib_install_kernel(struct route_node *rn, struct route_entry *re,
-                      struct route_entry *old)
+void rib_install_kernel(struct route_node *rn, struct route_entry *re,
+                       struct route_entry *old)
 {
-       int ret = 0;
        struct nexthop *nexthop;
        rib_table_info_t *info = srcdest_rnode_table_info(rn);
        struct prefix *p, *src_p;
@@ -1010,7 +1046,7 @@ int rib_install_kernel(struct route_node *rn, struct route_entry *re,
        if (info->safi != SAFI_UNICAST) {
                for (ALL_NEXTHOPS(re->nexthop, nexthop))
                        SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
-               return ret;
+               return;
        } else {
                struct nexthop *prev;
 
@@ -1042,33 +1078,15 @@ int rib_install_kernel(struct route_node *rn, struct route_entry *re,
         * the kernel.
         */
        hook_call(rib_update, rn, "installing in kernel");
-       ret = kernel_route_rib(p, src_p, old, re);
+       kernel_route_rib(p, src_p, old, re);
        zvrf->installs++;
 
-       /* If install succeeds, update FIB flag for nexthops. */
-       if (!ret) {
-               for (ALL_NEXTHOPS(re->nexthop, nexthop)) {
-                       if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
-                               continue;
-
-                       if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
-                               SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
-                       else
-                               UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
-               }
-               zsend_route_notify_owner(re->type, re->instance, re->vrf_id,
-                                        p, ZAPI_ROUTE_INSTALLED);
-       } else
-               zsend_route_notify_owner(re->type, re->instance, re->vrf_id,
-                                        p, ZAPI_ROUTE_FAIL_INSTALL);
-
-       return ret;
+       return;
 }
 
 /* Uninstall the route from kernel. */
-int rib_uninstall_kernel(struct route_node *rn, struct route_entry *re)
+void rib_uninstall_kernel(struct route_node *rn, struct route_entry *re)
 {
-       int ret = 0;
        struct nexthop *nexthop;
        rib_table_info_t *info = srcdest_rnode_table_info(rn);
        struct prefix *p, *src_p;
@@ -1079,7 +1097,7 @@ int rib_uninstall_kernel(struct route_node *rn, struct route_entry *re)
        if (info->safi != SAFI_UNICAST) {
                for (ALL_NEXTHOPS(re->nexthop, nexthop))
                        UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
-               return ret;
+               return;
        }
 
        /*
@@ -1087,13 +1105,10 @@ int rib_uninstall_kernel(struct route_node *rn, struct route_entry *re)
         * the kernel.
         */
        hook_call(rib_update, rn, "uninstalling from kernel");
-       ret = kernel_route_rib(p, src_p, re, NULL);
+       kernel_route_rib(p, src_p, re, NULL);
        zvrf->removals++;
 
-       for (ALL_NEXTHOPS(re->nexthop, nexthop))
-               UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
-
-       return ret;
+       return;
 }
 
 /* Uninstall the route from kernel. */
@@ -1207,14 +1222,8 @@ static void rib_process_add_fib(struct zebra_vrf *zvrf, struct route_node *rn,
        if (zebra_rib_labeled_unicast(new))
                zebra_mpls_lsp_install(zvrf, rn, new);
 
-       if (!RIB_SYSTEM_ROUTE(new)) {
-               if (rib_install_kernel(rn, new, NULL)) {
-                       char buf[SRCDEST2STR_BUFFER];
-                       srcdest_rnode2str(rn, buf, sizeof(buf));
-                       zlog_warn("%u:%s: Route install failed", zvrf_id(zvrf),
-                                 buf);
-               }
-       }
+       if (!RIB_SYSTEM_ROUTE(new))
+               rib_install_kernel(rn, new, NULL);
 
        UNSET_FLAG(new->status, ROUTE_ENTRY_CHANGED);
 }
@@ -1301,13 +1310,7 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
                                if (zebra_rib_labeled_unicast(new))
                                        zebra_mpls_lsp_install(zvrf, rn, new);
 
-                               if (rib_install_kernel(rn, new, old)) {
-                                       char buf[SRCDEST2STR_BUFFER];
-                                       srcdest_rnode2str(rn, buf, sizeof(buf));
-                                       installed = 0;
-                                       zlog_warn("%u:%s: Route install failed",
-                                                 zvrf_id(zvrf), buf);
-                               }
+                               rib_install_kernel(rn, new, old);
                        }
 
                        /* If install succeeded or system route, cleanup flags
@@ -2633,7 +2636,6 @@ static void rib_sweep_table(struct route_table *table)
        struct route_entry *re;
        struct route_entry *next;
        struct nexthop *nexthop;
-       int ret = 0;
 
        if (!table)
                return;
@@ -2670,9 +2672,8 @@ static void rib_sweep_table(struct route_table *table)
                        for (ALL_NEXTHOPS(re->nexthop, nexthop))
                                SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB);
 
-                       ret = rib_uninstall_kernel(rn, re);
-                       if (!ret)
-                               rib_delnode(rn, re);
+                       rib_uninstall_kernel(rn, re);
+                       rib_delnode(rn, re);
                }
        }
 }