]> git.proxmox.com Git - mirror_frr.git/commitdiff
pbrd: add support for interface nexthops
authorRenato Westphal <renato@opensourcerouting.org>
Thu, 14 Feb 2019 22:00:15 +0000 (20:00 -0200)
committerRenato Westphal <renato@opensourcerouting.org>
Fri, 15 Feb 2019 00:57:39 +0000 (22:57 -0200)
Now that nexthop groups can contain interface nexthops, make the
necessary adjustments in pbrd to handle them appropriately.

For normal IP nexthops, pbrd uses the NHT callbacks to validate
these nexthops (i.e. check if they are reachable). NHT can't be
used for interface nexthops though. To work around this issue,
use the interface event callbacks from the zclient API to validate
interface nexthops (an interface nexthop is valid only if the
corresponding interface is up and running).

Signed-off-by: Renato Westphal <renato@opensourcerouting.org>
pbrd/pbr_nht.c
pbrd/pbr_nht.h
pbrd/pbr_zebra.c

index e196b4fe2ce66114ab8c21ebcaa8f172807a7d4a..b269ce0cdfaea2fa6a491f3402421bc2f8dfdeea 100644 (file)
@@ -157,7 +157,7 @@ static bool pbr_nh_hash_equal(const void *arg1, const void *arg2)
 
        switch (pbrnc1->nexthop->type) {
        case NEXTHOP_TYPE_IFINDEX:
-               return true;
+               return pbrnc1->nexthop->ifindex == pbrnc2->nexthop->ifindex;
        case NEXTHOP_TYPE_IPV4_IFINDEX:
        case NEXTHOP_TYPE_IPV4:
                return pbrnc1->nexthop->gate.ipv4.s_addr
@@ -264,6 +264,14 @@ void pbr_nhgroup_add_nexthop_cb(const struct nexthop_group_cmd *nhgc,
 
        pbr_nht_install_nexthop_group(pnhgc, nhgc->nhg);
        pbr_map_check_nh_group_change(nhgc->name);
+
+       if (nhop->type == NEXTHOP_TYPE_IFINDEX) {
+               struct interface *ifp;
+
+               ifp = if_lookup_by_index(nhop->ifindex, nhop->vrf_id);
+               if (ifp)
+                       pbr_nht_nexthop_interface_update(ifp);
+       }
 }
 
 void pbr_nhgroup_del_nexthop_cb(const struct nexthop_group_cmd *nhgc,
@@ -667,6 +675,7 @@ bool pbr_nht_nexthop_group_valid(const char *name)
 
 struct pbr_nht_individual {
        struct zapi_route *nhr;
+       struct interface *ifp;
 
        uint32_t valid;
 };
@@ -730,6 +739,56 @@ void pbr_nht_nexthop_update(struct zapi_route *nhr)
        hash_iterate(pbr_nhg_hash, pbr_nht_nexthop_update_lookup, nhr);
 }
 
+static void
+pbr_nht_individual_nexthop_interface_update_lookup(struct hash_backet *b,
+                                                  void *data)
+{
+       struct pbr_nexthop_cache *pnhc = b->data;
+       struct pbr_nht_individual *pnhi = data;
+       bool old_valid;
+
+       old_valid = pnhc->valid;
+
+       if (pnhc->nexthop->type == NEXTHOP_TYPE_IFINDEX
+           && pnhc->nexthop->ifindex == pnhi->ifp->ifindex)
+               pnhc->valid = !!if_is_up(pnhi->ifp);
+
+       DEBUGD(&pbr_dbg_nht, "\tFound %s: old: %d new: %d", pnhi->ifp->name,
+              old_valid, pnhc->valid);
+
+       if (pnhc->valid)
+               pnhi->valid += 1;
+}
+
+static void pbr_nht_nexthop_interface_update_lookup(struct hash_backet *b,
+                                                   void *data)
+{
+       struct pbr_nexthop_group_cache *pnhgc = b->data;
+       struct pbr_nht_individual pnhi;
+       bool old_valid;
+
+       old_valid = pnhgc->valid;
+
+       pnhi.ifp = data;
+       pnhi.valid = 0;
+       hash_iterate(pnhgc->nhh,
+                    pbr_nht_individual_nexthop_interface_update_lookup, &pnhi);
+
+       /*
+        * If any of the specified nexthops are valid we are valid
+        */
+       pnhgc->valid = !!pnhi.valid;
+
+       if (old_valid != pnhgc->valid)
+               pbr_map_check_nh_group_change(pnhgc->name);
+}
+
+void pbr_nht_nexthop_interface_update(struct interface *ifp)
+{
+       hash_iterate(pbr_nhg_hash, pbr_nht_nexthop_interface_update_lookup,
+                    ifp);
+}
+
 static uint32_t pbr_nhg_hash_key(void *arg)
 {
        struct pbr_nexthop_group_cache *nhgc =
index d37803fbe32e52fffeb5c0b605715064413254b4..4ef41cede7dd76a2fca02758e336787271cae2ce 100644 (file)
@@ -117,5 +117,10 @@ extern void pbr_nht_show_nexthop_group(struct vty *vty, const char *name);
  */
 extern void pbr_nht_nexthop_update(struct zapi_route *nhr);
 
+/*
+ * When we get a callback from zebra about an interface status update.
+ */
+extern void pbr_nht_nexthop_interface_update(struct interface *ifp);
+
 extern void pbr_nht_init(void);
 #endif
index 425bc04b4d5f3bef918300cdd037ea3217acf107..37209d481942ba2b6035de4ec4f35401d6faca7d 100644 (file)
@@ -75,6 +75,8 @@ static int interface_add(int command, struct zclient *zclient,
        if (!ifp->info)
                pbr_if_new(ifp);
 
+       pbr_nht_nexthop_interface_update(ifp);
+
        return 0;
 }
 
@@ -144,6 +146,8 @@ static int interface_state_up(int command, struct zclient *zclient,
        DEBUGD(&pbr_dbg_zebra,
               "%s: %s is up", __PRETTY_FUNCTION__, ifp->name);
 
+       pbr_nht_nexthop_interface_update(ifp);
+
        return 0;
 }
 
@@ -157,6 +161,8 @@ static int interface_state_down(int command, struct zclient *zclient,
        DEBUGD(&pbr_dbg_zebra,
               "%s: %s is down", __PRETTY_FUNCTION__, ifp->name);
 
+       pbr_nht_nexthop_interface_update(ifp);
+
        return 0;
 }