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>
This commit is contained in:
Renato Westphal 2019-02-14 20:00:15 -02:00
parent 268c24ee9e
commit a106a4087b
3 changed files with 71 additions and 1 deletions

View 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 =

View 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

View 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;
}