summaryrefslogtreecommitdiffstats
path: root/pbrd
diff options
context:
space:
mode:
authorRenato Westphal <renato@opensourcerouting.org>2019-02-14 23:00:15 +0100
committerRenato Westphal <renato@opensourcerouting.org>2019-02-15 01:57:39 +0100
commita106a4087b47e180e32c66e139449bcf2660578f (patch)
tree42b01877fb3d52999d9fa3049b71c40da10a50a4 /pbrd
parentpbrd: fix detection of inconsistent nexthop groups (diff)
downloadfrr-a106a4087b47e180e32c66e139449bcf2660578f.tar.xz
frr-a106a4087b47e180e32c66e139449bcf2660578f.zip
pbrd: add support for interface nexthops
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>
Diffstat (limited to 'pbrd')
-rw-r--r--pbrd/pbr_nht.c61
-rw-r--r--pbrd/pbr_nht.h5
-rw-r--r--pbrd/pbr_zebra.c6
3 files changed, 71 insertions, 1 deletions
diff --git a/pbrd/pbr_nht.c b/pbrd/pbr_nht.c
index e196b4fe2..b269ce0cd 100644
--- a/pbrd/pbr_nht.c
+++ b/pbrd/pbr_nht.c
@@ -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 =
diff --git a/pbrd/pbr_nht.h b/pbrd/pbr_nht.h
index d37803fbe..4ef41cede 100644
--- a/pbrd/pbr_nht.h
+++ b/pbrd/pbr_nht.h
@@ -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
diff --git a/pbrd/pbr_zebra.c b/pbrd/pbr_zebra.c
index 425bc04b4..37209d481 100644
--- a/pbrd/pbr_zebra.c
+++ b/pbrd/pbr_zebra.c
@@ -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;
}