]> git.proxmox.com Git - mirror_frr.git/blobdiff - staticd/static_nht.c
Merge pull request #5327 from lkrishnamoor/rm_rd_filter
[mirror_frr.git] / staticd / static_nht.c
index c6e4587b6aafa1691cffb49082a7c12c73b1fea9..1a2ddd7f051b922a94653603e19fb696ad639823 100644 (file)
 #include "table.h"
 #include "vrf.h"
 #include "nexthop.h"
+#include "srcdest_table.h"
 
 #include "static_vrf.h"
 #include "static_routes.h"
 #include "static_zebra.h"
 #include "static_nht.h"
 
-void static_nht_update(struct prefix *p, uint32_t nh_num,
-                      afi_t afi, vrf_id_t vrf_id)
+static void static_nht_update_rn(struct route_node *rn,
+                                struct prefix *nhp, uint32_t nh_num,
+                                vrf_id_t nh_vrf_id, struct vrf *vrf,
+                                safi_t safi)
 {
-       struct route_table *stable;
        struct static_route *si;
+
+       for (si = rn->info; si; si = si->next) {
+               if (si->nh_vrf_id != nh_vrf_id)
+                       continue;
+
+               if (si->type != STATIC_IPV4_GATEWAY
+                   && si->type != STATIC_IPV4_GATEWAY_IFNAME
+                   && si->type != STATIC_IPV6_GATEWAY
+                   && si->type != STATIC_IPV6_GATEWAY_IFNAME)
+                       continue;
+
+               if (nhp->family == AF_INET
+                   && nhp->u.prefix4.s_addr == si->addr.ipv4.s_addr)
+                       si->nh_valid = !!nh_num;
+
+               if (nhp->family == AF_INET6
+                   && memcmp(&nhp->u.prefix6, &si->addr.ipv6, 16) == 0)
+                       si->nh_valid = !!nh_num;
+
+               if (si->state == STATIC_START)
+                       static_zebra_route_add(rn, si, vrf->vrf_id, safi, true);
+       }
+}
+
+static void static_nht_update_safi(struct prefix *sp, struct prefix *nhp,
+                                  uint32_t nh_num, afi_t afi, safi_t safi,
+                                  struct vrf *vrf, vrf_id_t nh_vrf_id)
+{
+       struct route_table *stable;
        struct static_vrf *svrf;
        struct route_node *rn;
-       struct vrf *vrf;
-       bool orig;
-       bool reinstall;
 
-       vrf = vrf_lookup_by_id(vrf_id);
+       svrf = vrf->info;
+       if (!svrf)
+               return;
 
-       if (!vrf || !vrf->info)
+       stable = static_vrf_static_table(afi, safi, svrf);
+       if (!stable)
+               return;
+
+       if (sp) {
+               rn = srcdest_rnode_lookup(stable, sp, NULL);
+               if (rn) {
+                       static_nht_update_rn(rn, nhp, nh_num, nh_vrf_id,
+                                            vrf, safi);
+                       route_unlock_node(rn);
+               }
                return;
+       }
+
+       for (rn = route_top(stable); rn; rn = route_next(rn))
+               static_nht_update_rn(rn, nhp, nh_num, nh_vrf_id, vrf, safi);
+
+}
+
+void static_nht_update(struct prefix *sp, struct prefix *nhp,
+                      uint32_t nh_num, afi_t afi, vrf_id_t nh_vrf_id)
+{
+
+       struct vrf *vrf;
+
+       RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+               static_nht_update_safi(sp, nhp, nh_num, afi, SAFI_UNICAST,
+                                      vrf, nh_vrf_id);
+               static_nht_update_safi(sp, nhp, nh_num, afi, SAFI_MULTICAST,
+                                      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;
-       stable = static_vrf_static_table(afi, SAFI_UNICAST, svrf);
+       if (!svrf)
+               return;
+
+       stable = static_vrf_static_table(afi, safi, svrf);
        if (!stable)
                return;
 
        for (rn = route_top(stable); rn; rn = route_next(rn)) {
-               reinstall = false;
                for (si = rn->info; si; si = si->next) {
-                       if (si->type != STATIC_IPV4_GATEWAY &&
-                           si->type != STATIC_IPV4_GATEWAY_IFNAME &&
-                           si->type != STATIC_IPV6_GATEWAY &&
-                           si->type != STATIC_IPV6_GATEWAY_IFNAME)
+                       if (si->nh_vrf_id != nh_vrf_id)
                                continue;
 
-                       orig = si->nh_valid;
-                       if (p->family == AF_INET &&
-                           p->u.prefix4.s_addr == si->addr.ipv4.s_addr)
-                               si->nh_valid = !!nh_num;
-
-                       if (p->family == AF_INET6 &&
-                           memcmp(&p->u.prefix6, &si->addr.ipv6, 16) == 0)
-                               si->nh_valid = !!nh_num;
+                       if (nhp->family == AF_INET
+                           && nhp->u.prefix4.s_addr != si->addr.ipv4.s_addr)
+                               continue;
 
-                       if (orig != si->nh_valid)
-                               reinstall = true;
+                       if (nhp->family == AF_INET6
+                           && memcmp(&nhp->u.prefix6, &si->addr.ipv6, 16) != 0)
+                               continue;
 
-                       if (reinstall) {
-                               static_zebra_route_add(rn, si, vrf_id,
-                                                      SAFI_UNICAST, true);
-                               reinstall = false;
-                       }
+                       /*
+                        * 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);
+}