]> git.puffer.fish Git - mirror/frr.git/commitdiff
staticd: Track state of where we are and limit installs/updates to min 4690/head
authorDonald Sharp <sharpd@cumulusnetworks.com>
Tue, 16 Jul 2019 12:27:31 +0000 (08:27 -0400)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Tue, 16 Jul 2019 12:27:31 +0000 (08:27 -0400)
Track the state of the route and how we have installed it or not.
This commit limits the number of installs/updates/deletes to a
minimum number instead of repeated sends to zebra.

Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
staticd/static_nht.c
staticd/static_nht.h
staticd/static_zebra.c

index 8891ae321013a059c281369eb893b18bb00f5806..1a2ddd7f051b922a94653603e19fb696ad639823 100644 (file)
@@ -55,7 +55,8 @@ static void static_nht_update_rn(struct route_node *rn,
                    && memcmp(&nhp->u.prefix6, &si->addr.ipv6, 16) == 0)
                        si->nh_valid = !!nh_num;
 
-               static_zebra_route_add(rn, si, vrf->vrf_id, safi, true);
+               if (si->state == STATIC_START)
+                       static_zebra_route_add(rn, si, vrf->vrf_id, safi, true);
        }
 }
 
@@ -103,3 +104,101 @@ void static_nht_update(struct prefix *sp, struct prefix *nhp,
                                       vrf, nh_vrf_id);
        }
 }
+
+static void static_nht_reset_start_safi(struct prefix *nhp, afi_t afi,
+                                       safi_t safi, struct vrf *vrf,
+                                       vrf_id_t nh_vrf_id)
+{
+       struct static_vrf *svrf;
+       struct route_table *stable;
+       struct static_route *si;
+       struct route_node *rn;
+
+       svrf = vrf->info;
+       if (!svrf)
+               return;
+
+       stable = static_vrf_static_table(afi, safi, svrf);
+       if (!stable)
+               return;
+
+       for (rn = route_top(stable); rn; rn = route_next(rn)) {
+               for (si = rn->info; si; si = si->next) {
+                       if (si->nh_vrf_id != nh_vrf_id)
+                               continue;
+
+                       if (nhp->family == AF_INET
+                           && nhp->u.prefix4.s_addr != si->addr.ipv4.s_addr)
+                               continue;
+
+                       if (nhp->family == AF_INET6
+                           && memcmp(&nhp->u.prefix6, &si->addr.ipv6, 16) != 0)
+                               continue;
+
+                       /*
+                        * We've been told that a nexthop we depend
+                        * on has changed in some manner, so reset
+                        * the state machine to allow us to start
+                        * over.
+                        */
+                       si->state = STATIC_START;
+               }
+       }
+}
+
+void static_nht_reset_start(struct prefix *nhp, afi_t afi, vrf_id_t nh_vrf_id)
+{
+       struct vrf *vrf;
+
+       RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+               static_nht_reset_start_safi(nhp, afi, SAFI_UNICAST,
+                                           vrf, nh_vrf_id);
+               static_nht_reset_start_safi(nhp, afi, SAFI_MULTICAST,
+                                           vrf, nh_vrf_id);
+       }
+}
+
+static void static_nht_mark_state_safi(struct prefix *sp, afi_t afi,
+                                      safi_t safi, struct vrf *vrf,
+                                      enum static_install_states state)
+{
+       struct static_vrf *svrf;
+       struct route_table *stable;
+       struct static_route *si;
+       struct route_node *rn;
+
+       svrf = vrf->info;
+       if (!svrf)
+               return;
+
+       stable = static_vrf_static_table(afi, safi, svrf);
+       if (!stable)
+               return;
+
+       rn = srcdest_rnode_lookup(stable, sp, NULL);
+       if (!rn)
+               return;
+
+       for (si = rn->info; si; si = si->next)
+               si->state = state;
+
+       route_unlock_node(rn);
+}
+
+void static_nht_mark_state(struct prefix *sp, vrf_id_t vrf_id,
+                          enum static_install_states state)
+{
+       struct vrf *vrf;
+
+       afi_t afi = AFI_IP;
+
+       if (sp->family == AF_INET6)
+               afi = AFI_IP6;
+
+       vrf = vrf_lookup_by_id(vrf_id);
+       if (!vrf || !vrf->info)
+               return;
+
+       static_nht_mark_state_safi(sp, afi, SAFI_UNICAST, vrf, state);
+       static_nht_mark_state_safi(sp, afi, SAFI_MULTICAST, vrf, state);
+}
index 7b9461685600370606353ed87d044f891f321b8c..18bb9e39cacddc50e7947ea7dc33ac1d32f4cd2d 100644 (file)
  */
 extern void static_nht_update(struct prefix *sp, struct prefix *nhp,
                              uint32_t nh_num, afi_t afi, vrf_id_t vrf_id);
+
+/*
+ * For the given tracked nexthop, nhp, mark all routes that use
+ * this route as in starting state again.
+ */
+extern void static_nht_reset_start(struct prefix *nhp, afi_t afi,
+                                  vrf_id_t nh_vrf_id);
+
+/*
+ * For the given prefix, sp, mark it as in a particular state
+ */
+extern void static_nht_mark_state(struct prefix *sp, vrf_id_t vrf_id,
+                                 enum static_install_states state);
 #endif
index ad275d1f13266cd2f8ed57e1083b760676c39506..13c04259d733728f272d5d3c77a89f2083e1909b 100644 (file)
@@ -156,18 +156,23 @@ static int route_notify_owner(ZAPI_CALLBACK_ARGS)
 
        switch (note) {
        case ZAPI_ROUTE_FAIL_INSTALL:
+               static_nht_mark_state(&p, vrf_id, STATIC_NOT_INSTALLED);
                zlog_warn("%s: Route %s failed to install for table: %u",
                          __PRETTY_FUNCTION__, buf, table_id);
                break;
        case ZAPI_ROUTE_BETTER_ADMIN_WON:
+               static_nht_mark_state(&p, vrf_id, STATIC_NOT_INSTALLED);
                zlog_warn("%s: Route %s over-ridden by better route for table: %u",
                          __PRETTY_FUNCTION__, buf, table_id);
                break;
        case ZAPI_ROUTE_INSTALLED:
+               static_nht_mark_state(&p, vrf_id, STATIC_INSTALLED);
                break;
        case ZAPI_ROUTE_REMOVED:
+               static_nht_mark_state(&p, vrf_id, STATIC_NOT_INSTALLED);
                break;
        case ZAPI_ROUTE_REMOVE_FAIL:
+               static_nht_mark_state(&p, vrf_id, STATIC_INSTALLED);
                zlog_warn("%s: Route %s failure to remove for table: %u",
                          __PRETTY_FUNCTION__, buf, table_id);
                break;
@@ -212,6 +217,7 @@ static int static_zebra_nexthop_update(ZAPI_CALLBACK_ARGS)
        if (nhtd) {
                nhtd->nh_num = nhr.nexthop_num;
 
+               static_nht_reset_start(&nhr.prefix, afi, nhtd->nh_vrf_id);
                static_nht_update(NULL, &nhr.prefix, nhr.nexthop_num, afi,
                                  nhtd->nh_vrf_id);
        } else
@@ -395,6 +401,8 @@ extern void static_zebra_route_add(struct route_node *rn,
                api_nh->vrf_id = si->nh_vrf_id;
                api_nh->onlink = si->onlink;
 
+               si->state = STATIC_SENT_TO_ZEBRA;
+
                switch (si->type) {
                case STATIC_IFNAME:
                        if (si->ifindex == IFINDEX_INTERNAL)