diff options
-rw-r--r-- | pbrd/pbr_map.c | 25 | ||||
-rw-r--r-- | pbrd/pbr_map.h | 3 | ||||
-rw-r--r-- | pbrd/pbr_nht.c | 65 | ||||
-rw-r--r-- | pbrd/pbr_nht.h | 2 | ||||
-rw-r--r-- | pbrd/pbr_vty.c | 6 | ||||
-rw-r--r-- | pbrd/pbr_zebra.c | 1 |
6 files changed, 100 insertions, 2 deletions
diff --git a/pbrd/pbr_map.c b/pbrd/pbr_map.c index e37110c1c..b0d1e235f 100644 --- a/pbrd/pbr_map.c +++ b/pbrd/pbr_map.c @@ -796,6 +796,31 @@ void pbr_map_check_vrf_nh_group_change(const char *nh_group, } } +void pbr_map_check_interface_nh_group_change(const char *nh_group, + struct interface *ifp, + ifindex_t oldifindex) +{ + struct pbr_map *pbrm; + struct pbr_map_sequence *pbrms; + struct listnode *node; + + RB_FOREACH (pbrm, pbr_map_entry_head, &pbr_maps) { + for (ALL_LIST_ELEMENTS_RO(pbrm->seqnumbers, node, pbrms)) { + if (pbrms->nhgrp_name) + continue; + + if (pbrms->nhg + && strcmp(nh_group, pbrms->internal_nhg_name)) + continue; + + if (pbrms->nhg->nexthop->ifindex != oldifindex) + continue; + + pbrms->nhg->nexthop->ifindex = ifp->ifindex; + } + } +} + void pbr_map_check(struct pbr_map_sequence *pbrms, bool changed) { struct pbr_map *pbrm; diff --git a/pbrd/pbr_map.h b/pbrd/pbr_map.h index 850070911..43266f21e 100644 --- a/pbrd/pbr_map.h +++ b/pbrd/pbr_map.h @@ -209,4 +209,7 @@ extern void pbr_map_policy_delete(struct pbr_map *pbrm, extern void pbr_map_check_vrf_nh_group_change(const char *nh_group, struct pbr_vrf *pbr_vrf, uint32_t old_vrf_id); +extern void pbr_map_check_interface_nh_group_change(const char *nh_group, + struct interface *ifp, + ifindex_t oldifindex); #endif diff --git a/pbrd/pbr_nht.c b/pbrd/pbr_nht.c index e875ea1ce..4d0682300 100644 --- a/pbrd/pbr_nht.c +++ b/pbrd/pbr_nht.c @@ -563,6 +563,15 @@ void pbr_nht_add_individual_nexthop(struct pbr_map_sequence *pbrms, strlcpy(pnhc->vrf_name, vrf->name, sizeof(pnhc->vrf_name)); } + + if (nhop->ifindex != 0) { + struct interface *ifp = + if_lookup_by_index(nhop->ifindex, nhop->vrf_id); + + if (ifp) + strlcpy(pnhc->intf_name, ifp->name, + sizeof(pnhc->intf_name)); + } pbr_nht_install_nexthop_group(pnhgc, *pbrms->nhg); } @@ -947,6 +956,62 @@ 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_handle(struct hash_bucket *b, + void *data) +{ + struct pbr_nexthop_cache *pnhc = b->data; + struct pbr_nht_individual *pnhi = data; + + if (pnhc->nexthop->ifindex == 0) + return; + + if ((strncmp(pnhc->intf_name, pnhi->ifp->name, sizeof(pnhc->intf_name)) + == 0) + && pnhc->nexthop->ifindex != pnhi->ifp->ifindex) + pnhi->pnhc = pnhc; +} + +static void pbr_nht_nexthop_interface_handle(struct hash_bucket *b, void *data) +{ + struct pbr_nexthop_group_cache *pnhgc = b->data; + struct interface *ifp = data; + struct pbr_nht_individual pnhi = {}; + struct nhrc *nhrc; + uint32_t old_ifindex; + + do { + memset(&pnhi, 0, sizeof(pnhi)); + pnhi.ifp = ifp; + hash_iterate(pnhgc->nhh, + pbr_nht_individual_nexthop_interface_handle, + &pnhi); + + if (!pnhi.pnhc) + continue; + + pnhi.pnhc = hash_release(pnhgc->nhh, pnhi.pnhc); + old_ifindex = pnhi.pnhc->nexthop->ifindex; + + nhrc = hash_lookup(pbr_nhrc_hash, pnhi.pnhc->nexthop); + if (nhrc) { + hash_release(pbr_nhrc_hash, nhrc); + nhrc->nexthop.ifindex = ifp->ifindex; + hash_get(pbr_nhrc_hash, nhrc, hash_alloc_intern); + } + pnhi.pnhc->nexthop->ifindex = ifp->ifindex; + + hash_get(pnhgc->nhh, pnhi.pnhc, hash_alloc_intern); + + pbr_map_check_interface_nh_group_change(pnhgc->name, ifp, + old_ifindex); + } while (pnhi.pnhc); +} + +void pbr_nht_interface_update(struct interface *ifp) +{ + hash_iterate(pbr_nhg_hash, pbr_nht_nexthop_interface_handle, ifp); +} + static void pbr_nht_individual_nexthop_interface_update_lookup(struct hash_bucket *b, void *data) diff --git a/pbrd/pbr_nht.h b/pbrd/pbr_nht.h index d1afbaa73..a1099a00c 100644 --- a/pbrd/pbr_nht.h +++ b/pbrd/pbr_nht.h @@ -49,6 +49,7 @@ struct pbr_nexthop_cache { struct pbr_nexthop_group_cache *parent; char vrf_name[VRF_NAMSIZ + 1]; + char intf_name[INTERFACE_NAMSIZ + 1]; struct nexthop *nexthop; @@ -132,4 +133,5 @@ extern void pbr_nht_nexthop_interface_update(struct interface *ifp); extern void pbr_nht_init(void); extern void pbr_nht_vrf_update(struct pbr_vrf *pbr_vrf); +extern void pbr_nht_interface_update(struct interface *ifp); #endif diff --git a/pbrd/pbr_vty.c b/pbrd/pbr_vty.c index 3ed227dd0..cf9185e7c 100644 --- a/pbrd/pbr_vty.c +++ b/pbrd/pbr_vty.c @@ -627,8 +627,6 @@ pbrms_nexthop_group_write_individual_nexthop( struct pbr_nexthop_cache lookup; struct pbr_nexthop_cache *pnhc; - nexthop_group_write_nexthop_simple(vty, pbrms->nhg->nexthop, NULL); - memset(&find, 0, sizeof(find)); strlcpy(find.name, pbrms->internal_nhg_name, sizeof(find.name)); @@ -637,6 +635,10 @@ pbrms_nexthop_group_write_individual_nexthop( lookup.nexthop = pbrms->nhg->nexthop; pnhc = hash_lookup(pnhgc->nhh, &lookup); + + nexthop_group_write_nexthop_simple( + vty, pbrms->nhg->nexthop, + pnhc->nexthop->ifindex != 0 ? pnhc->intf_name : NULL); if (pnhc->nexthop->vrf_id != VRF_DEFAULT) vty_out(vty, " nexthop-vrf %s", pnhc->vrf_name); diff --git a/pbrd/pbr_zebra.c b/pbrd/pbr_zebra.c index d0099a46e..a7420974a 100644 --- a/pbrd/pbr_zebra.c +++ b/pbrd/pbr_zebra.c @@ -67,6 +67,7 @@ int pbr_ifp_create(struct interface *ifp) if (!ifp->info) pbr_if_new(ifp); + pbr_nht_interface_update(ifp); /* Update nexthops tracked from a `set nexthop` command */ pbr_nht_nexthop_interface_update(ifp); |