]> git.proxmox.com Git - mirror_frr.git/blobdiff - staticd/static_routes.c
lib: add frr-isisd to the native models
[mirror_frr.git] / staticd / static_routes.c
index b7699ae3f33aa782dfe6dae834135be8374b5b6a..a5f0f74b003e667d21ae201ee068b29e3f8412c2 100644 (file)
@@ -33,7 +33,8 @@
 #include "static_zebra.h"
 
 /* Install static route into rib. */
-static void static_install_route(struct route_node *rn, safi_t safi)
+static void static_install_route(struct route_node *rn,
+                                struct static_route *si_changed, safi_t safi)
 {
        struct static_route *si;
 
@@ -42,19 +43,20 @@ static void static_install_route(struct route_node *rn, safi_t safi)
 
        si = rn->info;
        if (si)
-               static_zebra_route_add(rn, si->vrf_id, safi, true);
+               static_zebra_route_add(rn, si_changed, si->vrf_id, safi, true);
 
 }
 
 /* Uninstall static route from RIB. */
 static void static_uninstall_route(vrf_id_t vrf_id, safi_t safi,
-                                  struct route_node *rn)
+                                  struct route_node *rn,
+                                  struct static_route *si_changed)
 {
 
        if (rn->info)
-               static_zebra_route_add(rn, vrf_id, safi, true);
+               static_zebra_route_add(rn, si_changed, vrf_id, safi, true);
        else
-               static_zebra_route_add(rn, vrf_id, safi, false);
+               static_zebra_route_add(rn, si_changed, vrf_id, safi, false);
 }
 
 int static_add_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p,
@@ -62,8 +64,8 @@ int static_add_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p,
                     const char *ifname, enum static_blackhole_type bh_type,
                     route_tag_t tag, uint8_t distance, struct static_vrf *svrf,
                     struct static_vrf *nh_svrf,
-                    struct static_nh_label *snh_label,
-                    uint32_t table_id)
+                    struct static_nh_label *snh_label, uint32_t table_id,
+                    bool onlink)
 {
        struct route_node *rn;
        struct static_route *si;
@@ -102,7 +104,7 @@ int static_add_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p,
                            && (table_id == si->table_id)
                            && !memcmp(&si->snh_label, snh_label,
                                       sizeof(struct static_nh_label))
-                           && si->bh_type == bh_type) {
+                           && si->bh_type == bh_type && si->onlink == onlink) {
                                route_unlock_node(rn);
                                return 0;
                        }
@@ -127,6 +129,7 @@ int static_add_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p,
        si->nh_vrf_id = nh_svrf->vrf->vrf_id;
        strcpy(si->nh_vrfname, nh_svrf->vrf->name);
        si->table_id = table_id;
+       si->onlink = onlink;
 
        if (ifname)
                strlcpy(si->ifname, ifname, sizeof(si->ifname));
@@ -180,14 +183,14 @@ int static_add_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p,
 
        /* check whether interface exists in system & install if it does */
        if (!ifname)
-               static_install_route(rn, safi);
+               static_install_route(rn, si, safi);
        else {
                struct interface *ifp;
 
                ifp = if_lookup_by_name(ifname, nh_svrf->vrf->vrf_id);
                if (ifp && ifp->ifindex != IFINDEX_INTERNAL) {
                        si->ifindex = ifp->ifindex;
-                       static_install_route(rn, safi);
+                       static_install_route(rn, si, safi);
                } else
                        zlog_warn("Static Route using %s interface not installed because the interface does not exist in specified vrf",
                                  ifname);
@@ -253,7 +256,7 @@ int static_delete_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p,
         * If we have other si nodes then route replace
         * else delete the route
         */
-       static_uninstall_route(si->vrf_id, safi, rn);
+       static_uninstall_route(si->vrf_id, safi, rn, si);
        route_unlock_node(rn);
 
        /* Free static route configuration. */
@@ -294,9 +297,9 @@ static void static_ifindex_update_af(struct interface *ifp, bool up, afi_t afi,
                                                continue;
                                        si->ifindex = IFINDEX_INTERNAL;
                                }
-                       }
 
-                       static_install_route(rn, safi);
+                               static_install_route(rn, si, safi);
+                       }
                }
        }
 }
@@ -319,16 +322,13 @@ static void static_fixup_vrf(struct static_vrf *svrf,
        struct route_node *rn;
        struct static_route *si;
        struct interface *ifp;
-       bool install;
 
        for (rn = route_top(stable); rn; rn = route_next(rn)) {
-               install = false;
                for (si = rn->info; si; si = si->next) {
                        if (strcmp(svrf->vrf->name, si->nh_vrfname) != 0)
                                continue;
 
                        si->nh_vrf_id = svrf->vrf->vrf_id;
-                       install = true;
                        if (si->ifindex) {
                                ifp = if_lookup_by_name(si->ifname,
                                                        si->nh_vrf_id);
@@ -337,10 +337,9 @@ static void static_fixup_vrf(struct static_vrf *svrf,
                                else
                                        continue;
                        }
-               }
 
-               if (install)
-                       static_install_route(rn, safi);
+                       static_install_route(rn, si, safi);
+               }
        }
 }
 
@@ -361,10 +360,8 @@ static void static_enable_vrf(struct static_vrf *svrf,
        struct static_route *si;
        struct interface *ifp;
        struct vrf *vrf = svrf->vrf;
-       bool install;
 
        for (rn = route_top(stable); rn; rn = route_next(rn)) {
-               install = false;
                for (si = rn->info; si; si = si->next) {
                        si->vrf_id = vrf->vrf_id;
                        if (si->ifindex) {
@@ -375,11 +372,8 @@ static void static_enable_vrf(struct static_vrf *svrf,
                                else
                                        continue;
                        }
-                       install = true;
+                       static_install_route(rn, si, safi);
                }
-
-               if (install)
-                       static_install_route(rn, safi);
        }
 }
 
@@ -441,7 +435,7 @@ static void static_cleanup_vrf(struct static_vrf *svrf,
                        if (strcmp(svrf->vrf->name, si->nh_vrfname) != 0)
                                continue;
 
-                       static_uninstall_route(si->vrf_id, safi, rn);
+                       static_uninstall_route(si->vrf_id, safi, rn, si);
                }
        }
 }
@@ -462,7 +456,7 @@ static void static_disable_vrf(struct route_table *stable,
 
        for (rn = route_top(stable); rn; rn = route_next(rn))
                for (si = rn->info; si; si = si->next)
-                       static_uninstall_route(si->vrf_id, safi, rn);
+                       static_uninstall_route(si->vrf_id, safi, rn, si);
 }
 
 /*
@@ -503,6 +497,66 @@ void static_cleanup_vrf_ids(struct static_vrf *disable_svrf)
        }
 }
 
+/*
+ * This function enables static routes when an interface it relies
+ * on in a different vrf is coming up.
+ *
+ * stable -> The stable we are looking at.
+ * ifp -> interface coming up
+ * afi -> the afi in question
+ * safi -> the safi in question
+ */
+static void static_fixup_intf_nh(struct route_table *stable,
+                                struct interface *ifp,
+                                afi_t afi, safi_t safi)
+{
+       struct route_node *rn;
+       struct static_route *si;
+
+       for (rn = route_top(stable); rn; rn = route_next(rn)) {
+               for (si = rn->info; si; si = si->next) {
+                       if (si->nh_vrf_id != ifp->vrf_id)
+                               continue;
+
+                       if (si->ifindex != ifp->ifindex)
+                               continue;
+
+                       static_install_route(rn, si, safi);
+               }
+       }
+}
+
+/*
+ * This function enables static routes that rely on an interface in
+ * a different vrf when that interface comes up.
+ */
+void static_install_intf_nh(struct interface *ifp)
+{
+       struct route_table *stable;
+       struct vrf *vrf;
+       afi_t afi;
+       safi_t safi;
+
+       RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name) {
+               struct static_vrf *svrf = vrf->info;
+
+               /* Not needed if same vrf since happens naturally */
+               if (vrf->vrf_id == ifp->vrf_id)
+                       continue;
+
+               /* Install any static routes configured for this interface. */
+               for (afi = AFI_IP; afi < AFI_MAX; afi++) {
+                       for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
+                               stable = svrf->stable[afi][safi];
+                               if (!stable)
+                                       continue;
+
+                               static_fixup_intf_nh(stable, ifp, afi, safi);
+                       }
+               }
+       }
+}
+
 /* called from if_{add,delete}_update, i.e. when ifindex becomes [in]valid */
 void static_ifindex_update(struct interface *ifp, bool up)
 {