zebra: stop sending invalid nexthops to clients

Found that zebra_rnh_apply_nht_rmap would set the
NEXTHOP_FLAG_ACTIVE if not blocked by the route-map, even
if the flag was not active prior to the check.  This fix
changes the flag used to denote the nexthop is filtered so
that proper active state can be retained. Additionally,
found two cases where we would send invalid nexthops via
send_client, which would also cause this crash.  All three
fixed in this commit.

Signed-off-by: Don Slice <dslice@cumulusnetworks.com>
This commit is contained in:
Don Slice 2019-04-15 18:27:00 +00:00
parent fd3938ac3d
commit e47c4d3cfe
2 changed files with 27 additions and 5 deletions

View File

@ -82,6 +82,7 @@ struct nexthop {
#define NEXTHOP_FLAG_ONLINK (1 << 3) /* Nexthop should be installed onlink. */ #define NEXTHOP_FLAG_ONLINK (1 << 3) /* Nexthop should be installed onlink. */
#define NEXTHOP_FLAG_MATCHED (1 << 4) /* Already matched vs a nexthop */ #define NEXTHOP_FLAG_MATCHED (1 << 4) /* Already matched vs a nexthop */
#define NEXTHOP_FLAG_DUPLICATE (1 << 5) /* nexthop duplicates another active one */ #define NEXTHOP_FLAG_DUPLICATE (1 << 5) /* nexthop duplicates another active one */
#define NEXTHOP_FLAG_RNH_FILTERED (1 << 6) /* rmap filtered, used by rnh */
#define NEXTHOP_IS_ACTIVE(flags) \ #define NEXTHOP_IS_ACTIVE(flags) \
(CHECK_FLAG(flags, NEXTHOP_FLAG_ACTIVE) \ (CHECK_FLAG(flags, NEXTHOP_FLAG_ACTIVE) \
&& !CHECK_FLAG(flags, NEXTHOP_FLAG_DUPLICATE)) && !CHECK_FLAG(flags, NEXTHOP_FLAG_DUPLICATE))

View File

@ -377,6 +377,20 @@ void zebra_deregister_rnh_pseudowire(vrf_id_t vrf_id, struct zebra_pw *pw)
zebra_delete_rnh(rnh, RNH_NEXTHOP_TYPE); zebra_delete_rnh(rnh, RNH_NEXTHOP_TYPE);
} }
/* Clear the NEXTHOP_FLAG_RNH_FILTERED flags on all nexthops
*/
static void zebra_rnh_clear_nexthop_rnh_filters(struct route_entry *re)
{
struct nexthop *nexthop;
if (re) {
for (nexthop = re->ng.nexthop; nexthop;
nexthop = nexthop->next) {
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_RNH_FILTERED);
}
}
}
/* Apply the NHT route-map for a client to the route (and nexthops) /* Apply the NHT route-map for a client to the route (and nexthops)
* resolving a NH. * resolving a NH.
*/ */
@ -393,11 +407,11 @@ static int zebra_rnh_apply_nht_rmap(afi_t afi, struct zebra_vrf *zvrf,
nexthop = nexthop->next) { nexthop = nexthop->next) {
ret = zebra_nht_route_map_check( ret = zebra_nht_route_map_check(
afi, proto, &prn->p, zvrf, re, nexthop); afi, proto, &prn->p, zvrf, re, nexthop);
if (ret != RMAP_DENYMATCH) { if (ret != RMAP_DENYMATCH)
SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
at_least_one++; /* at least one valid NH */ at_least_one++; /* at least one valid NH */
} else { else {
UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); SET_FLAG(nexthop->flags,
NEXTHOP_FLAG_RNH_FILTERED);
} }
} }
} }
@ -546,6 +560,7 @@ static void zebra_rnh_notify_protocol_clients(struct zebra_vrf *zvrf, afi_t afi,
* this * this
* nexthop to see if it is filtered or not. * nexthop to see if it is filtered or not.
*/ */
zebra_rnh_clear_nexthop_rnh_filters(re);
num_resolving_nh = zebra_rnh_apply_nht_rmap( num_resolving_nh = zebra_rnh_apply_nht_rmap(
afi, zvrf, prn, re, client->proto); afi, zvrf, prn, re, client->proto);
if (num_resolving_nh) if (num_resolving_nh)
@ -572,6 +587,9 @@ static void zebra_rnh_notify_protocol_clients(struct zebra_vrf *zvrf, afi_t afi,
send_client(rnh, client, RNH_NEXTHOP_TYPE, zvrf->vrf->vrf_id); send_client(rnh, client, RNH_NEXTHOP_TYPE, zvrf->vrf->vrf_id);
} }
if (re)
zebra_rnh_clear_nexthop_rnh_filters(re);
} }
static void zebra_rnh_process_pbr_tables(afi_t afi, struct route_node *nrn, static void zebra_rnh_process_pbr_tables(afi_t afi, struct route_node *nrn,
@ -631,7 +649,10 @@ static bool rnh_nexthop_valid(const struct route_entry *re,
const struct nexthop *nh) const struct nexthop *nh)
{ {
return (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED) return (CHECK_FLAG(re->status, ROUTE_ENTRY_INSTALLED)
&& CHECK_FLAG(nh->flags, NEXTHOP_FLAG_ACTIVE)); && CHECK_FLAG(nh->flags, NEXTHOP_FLAG_ACTIVE)
&& !CHECK_FLAG(nh->flags, NEXTHOP_FLAG_RECURSIVE)
&& !CHECK_FLAG(nh->flags, NEXTHOP_FLAG_DUPLICATE)
&& !CHECK_FLAG(nh->flags, NEXTHOP_FLAG_RNH_FILTERED));
} }
/* /*