diff options
| author | Donald Sharp <sharpd@cumulusnetworks.com> | 2020-08-20 10:34:38 -0400 | 
|---|---|---|
| committer | Donald Sharp <sharpd@cumulusnetworks.com> | 2020-08-28 07:51:06 -0400 | 
| commit | fcf29c6919853416a86f72c510d488490bdd208f (patch) | |
| tree | 6139235c54cd706137aa25728cc49d52298b7027 /pbrd/pbr_nht.c | |
| parent | 79924520085ec6a7ac368e62226e3ad5ff9cc025 (diff) | |
pbrd: Properly hook back up when vrf is destroyed than recreated
Currently when a vrf is deleted than added back in PBR was
not going through and touching up all the data structures
that needed to be massaged to allow it to start working again.
This includes:
a) Search through the nexthop groups to find any nexthop
that references the old nexthop id and set it right again.
b) Search through the nexthop cache for nht and reset
those nexthops to the right vrf as well as re-register
Signed-off-by: Stephen Worley <sworley@cumulusnetworks.com>
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
Diffstat (limited to 'pbrd/pbr_nht.c')
| -rw-r--r-- | pbrd/pbr_nht.c | 72 | 
1 files changed, 71 insertions, 1 deletions
diff --git a/pbrd/pbr_nht.c b/pbrd/pbr_nht.c index 31da656793..e875ea1ceb 100644 --- a/pbrd/pbr_nht.c +++ b/pbrd/pbr_nht.c @@ -37,7 +37,7 @@  DEFINE_MTYPE_STATIC(PBRD, PBR_NHG, "PBR Nexthop Groups") -static struct hash *pbr_nhg_hash; +struct hash *pbr_nhg_hash;  static struct hash *pbr_nhrc_hash;  static uint32_t pbr_nhg_low_table; @@ -556,6 +556,13 @@ void pbr_nht_add_individual_nexthop(struct pbr_map_sequence *pbrms,  	lookup.nexthop = pbrms->nhg->nexthop;  	pnhc = hash_get(pnhgc->nhh, &lookup, pbr_nh_alloc);  	pnhc->parent = pnhgc; +	if (nhop->vrf_id != VRF_DEFAULT) { +		struct vrf *vrf = vrf_lookup_by_id(nhop->vrf_id); + +		if (vrf) +			strlcpy(pnhc->vrf_name, vrf->name, +				sizeof(pnhc->vrf_name)); +	}  	pbr_nht_install_nexthop_group(pnhgc, *pbrms->nhg);  } @@ -689,8 +696,12 @@ bool pbr_nht_nexthop_group_valid(const char *name)  struct pbr_nht_individual {  	struct zapi_route *nhr;  	struct interface *ifp; +	struct pbr_vrf *pbr_vrf; +	struct pbr_nexthop_cache *pnhc;  	uint32_t valid; + +	bool nhr_matched;  };  static bool @@ -877,6 +888,65 @@ 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_vrf_handle(struct hash_bucket *b, +						  void *data) +{ +	struct pbr_nexthop_cache *pnhc = b->data; +	struct pbr_nht_individual *pnhi = data; + +	if (pnhc->nexthop->vrf_id == VRF_DEFAULT) +		return; + +	if ((strncmp(pnhc->vrf_name, pbr_vrf_name(pnhi->pbr_vrf), +		     sizeof(pnhc->vrf_name)) +	     == 0) +	    && pnhc->nexthop->vrf_id != pbr_vrf_id(pnhi->pbr_vrf)) { +		pnhi->pnhc = pnhc; +		pnhi->nhr_matched = true; +	} +} + +static void pbr_nht_nexthop_vrf_handle(struct hash_bucket *b, void *data) +{ +	struct pbr_nexthop_group_cache *pnhgc = b->data; +	struct pbr_vrf *pbr_vrf = data; +	struct pbr_nht_individual pnhi = {}; +	struct nhrc *nhrc; +	uint32_t old_vrf_id; + +	do { +		memset(&pnhi, 0, sizeof(pnhi)); +		pnhi.pbr_vrf = pbr_vrf; +		hash_iterate(pnhgc->nhh, pbr_nht_individual_nexthop_vrf_handle, +			     &pnhi); + +		if (!pnhi.pnhc) +			continue; + +		pnhi.pnhc = hash_release(pnhgc->nhh, pnhi.pnhc); +		old_vrf_id = pnhi.pnhc->nexthop->vrf_id; + +		nhrc = hash_lookup(pbr_nhrc_hash, pnhi.pnhc->nexthop); +		if (nhrc) { +			hash_release(pbr_nhrc_hash, nhrc); +			nhrc->nexthop.vrf_id = pbr_vrf_id(pbr_vrf); +			hash_get(pbr_nhrc_hash, nhrc, hash_alloc_intern); +			pbr_send_rnh(pnhi.pnhc->nexthop, true); +		} +		pnhi.pnhc->nexthop->vrf_id = pbr_vrf_id(pbr_vrf); + +		hash_get(pnhgc->nhh, pnhi.pnhc, hash_alloc_intern); + +		pbr_map_check_vrf_nh_group_change(pnhgc->name, pbr_vrf, +						  old_vrf_id); +	} while (pnhi.pnhc); +} + +void pbr_nht_vrf_update(struct pbr_vrf *pbr_vrf) +{ +	hash_iterate(pbr_nhg_hash, pbr_nht_nexthop_vrf_handle, pbr_vrf); +} +  static void  pbr_nht_individual_nexthop_interface_update_lookup(struct hash_bucket *b,  						   void *data)  | 
