}
}
+void pbr_map_check_vrf_nh_group_change(const char *nh_group,
+ struct pbr_vrf *pbr_vrf,
+ uint32_t old_vrf_id)
+{
+ 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->vrf_id != old_vrf_id)
+ continue;
+
+ pbrms->nhg->nexthop->vrf_id = pbr_vrf_id(pbr_vrf);
+ }
+ }
+}
+
void pbr_map_check(struct pbr_map_sequence *pbrms, bool changed)
{
struct pbr_map *pbrm;
extern void pbr_map_policy_install(const char *name);
extern void pbr_map_policy_delete(struct pbr_map *pbrm,
struct pbr_map_interface *pmi);
+
+extern void pbr_map_check_vrf_nh_group_change(const char *nh_group,
+ struct pbr_vrf *pbr_vrf,
+ uint32_t old_vrf_id);
#endif
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;
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);
}
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
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)
#define PBR_NHC_NAMELEN PBR_MAP_NAMELEN + 10
+extern struct hash *pbr_nhg_hash;
+
struct pbr_nexthop_group_cache {
char name[PBR_NHC_NAMELEN];
struct pbr_nexthop_cache {
struct pbr_nexthop_group_cache *parent;
+ char vrf_name[VRF_NAMSIZ + 1];
+
struct nexthop *nexthop;
bool valid;
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);
#endif
#include "pbr_memory.h"
#include "pbr_map.h"
#include "pbr_debug.h"
+#include "pbr_nht.h"
DEFINE_MTYPE_STATIC(PBRD, PBR_MAP_VRF, "PBR Map VRF")
{
DEBUGD(&pbr_dbg_event, "%s: %u (%s)", __func__, vrf->vrf_id, vrf->name);
+ pbr_nht_vrf_update(vrf->info);
pbr_map_vrf_update(vrf->info);
return 0;
return CMD_SUCCESS;
}
+static void
+pbrms_nexthop_group_write_individual_nexthop(
+ struct vty *vty, const struct pbr_map_sequence *pbrms)
+{
+ struct pbr_nexthop_group_cache find;
+ struct pbr_nexthop_group_cache *pnhgc;
+ struct pbr_nexthop_cache lookup;
+ struct pbr_nexthop_cache *pnhc;
+
+ nexthop_group_write_nexthop_simple(vty, pbrms->nhg->nexthop);
+
+ memset(&find, 0, sizeof(find));
+ strlcpy(find.name, pbrms->internal_nhg_name, sizeof(find.name));
+
+ pnhgc = hash_lookup(pbr_nhg_hash, &find);
+ assert(pnhgc);
+
+ lookup.nexthop = pbrms->nhg->nexthop;
+ pnhc = hash_lookup(pnhgc->nhh, &lookup);
+ if (pnhc->nexthop->vrf_id != VRF_DEFAULT)
+ vty_out(vty, " nexthop-vrf %s", pnhc->vrf_name);
+
+ vty_out(vty, "\n");
+}
+
static void vty_show_pbrms(struct vty *vty,
const struct pbr_map_sequence *pbrms, bool detail)
{
} else if (pbrms->nhg) {
vty_out(vty, " ");
- nexthop_group_write_nexthop(vty, pbrms->nhg->nexthop);
+ pbrms_nexthop_group_write_individual_nexthop(vty, pbrms);
if (detail)
vty_out(vty,
" Installed: %u(%d) Tableid: %d\n",
if (pbrms->nhg) {
vty_out(vty, " set ");
- nexthop_group_write_nexthop(vty, pbrms->nhg->nexthop);
+ pbrms_nexthop_group_write_individual_nexthop(vty, pbrms);
}
vty_out(vty, "!\n");