summaryrefslogtreecommitdiff
path: root/zebra
diff options
context:
space:
mode:
Diffstat (limited to 'zebra')
-rw-r--r--zebra/fpm_listener.c61
-rw-r--r--zebra/interface.c19
-rw-r--r--zebra/interface.h4
-rw-r--r--zebra/rtadv.c61
-rw-r--r--zebra/zebra_neigh.c10
-rw-r--r--zebra/zebra_nhg.c62
-rw-r--r--zebra/zebra_nhg.h1
-rw-r--r--zebra/zebra_rib.c11
-rw-r--r--zebra/zebra_srv6.c4
-rw-r--r--zebra/zebra_vrf.c106
-rw-r--r--zebra/zebra_vrf.h2
-rw-r--r--zebra/zebra_vxlan_if.c29
12 files changed, 305 insertions, 65 deletions
diff --git a/zebra/fpm_listener.c b/zebra/fpm_listener.c
index 140cfa77cf..43ca6e47b8 100644
--- a/zebra/fpm_listener.c
+++ b/zebra/fpm_listener.c
@@ -44,6 +44,7 @@ struct glob {
int sock;
bool reflect;
bool dump_hex;
+ FILE *output_file;
};
struct glob glob_space;
@@ -123,13 +124,13 @@ static int accept_conn(int listen_sock)
while (1) {
char buf[120];
- fprintf(stdout, "Waiting for client connection...\n");
+ fprintf(glob->output_file, "Waiting for client connection...\n");
client_len = sizeof(client_addr);
sock = accept(listen_sock, (struct sockaddr *)&client_addr,
&client_len);
if (sock >= 0) {
- fprintf(stdout, "Accepted client %s\n",
+ fprintf(glob->output_file, "Accepted client %s\n",
inet_ntop(AF_INET, &client_addr.sin_addr, buf, sizeof(buf)));
return sock;
}
@@ -172,8 +173,7 @@ read_fpm_msg(char *buf, size_t buf_len)
bytes_read = read(glob->sock, cur, need_len);
if (bytes_read == 0) {
- fprintf(stdout,
- "Socket closed as that read returned 0\n");
+ fprintf(glob->output_file, "Socket closed as that read returned 0\n");
return NULL;
}
@@ -567,7 +567,7 @@ addr_to_s(unsigned char family, void *addr)
}
/*
- * netlink_msg_ctx_print
+ * netlink_msg_ctx_snprint
*/
static int netlink_msg_ctx_snprint(struct netlink_msg_ctx *ctx, char *buf,
size_t buf_len)
@@ -628,7 +628,7 @@ static void print_netlink_msg_ctx(struct netlink_msg_ctx *ctx)
char buf[1024];
netlink_msg_ctx_snprint(ctx, buf, sizeof(buf));
- printf("%s\n", buf);
+ fprintf(glob->output_file, "%s\n", buf);
}
static void fpm_listener_hexdump(const void *mem, size_t len)
@@ -641,7 +641,7 @@ static void fpm_listener_hexdump(const void *mem, size_t len)
return;
if (len == 0) {
- printf("%016lx: (zero length / no data)\n", (long)src);
+ fprintf(glob->output_file, "%016lx: (zero length / no data)\n", (long)src);
return;
}
@@ -654,14 +654,14 @@ static void fpm_listener_hexdump(const void *mem, size_t len)
const uint8_t *lineend = src + 8;
uint32_t line_bytes = 0;
- printf("%016lx: ", (long)src);
+ fprintf(glob->output_file, "%016lx: ", (long)src);
while (src < lineend && src < end) {
- printf("%02x ", *src++);
+ fprintf(glob->output_file, "%02x ", *src++);
line_bytes++;
}
if (line_bytes < 8)
- printf("%*s", (8 - line_bytes) * 3, "");
+ fprintf(glob->output_file, "%*s", (8 - line_bytes) * 3, "");
src -= line_bytes;
while (src < lineend && src < end && fb.pos < fb.buf + fb.len) {
@@ -672,7 +672,7 @@ static void fpm_listener_hexdump(const void *mem, size_t len)
else
*fb.pos++ = '.';
}
- printf("\n");
+ fprintf(glob->output_file, "\n");
}
}
@@ -711,20 +711,17 @@ static void parse_netlink_msg(char *buf, size_t buf_len, fpm_msg_hdr_t *fpm)
if (glob->reflect && hdr->nlmsg_type == RTM_NEWROUTE &&
ctx->rtmsg->rtm_protocol > RTPROT_STATIC) {
- printf(" Route %s(%u) reflecting back\n",
- netlink_prot_to_s(
- ctx->rtmsg->rtm_protocol),
- ctx->rtmsg->rtm_protocol);
+ fprintf(glob->output_file, " Route %s(%u) reflecting back\n",
+ netlink_prot_to_s(ctx->rtmsg->rtm_protocol),
+ ctx->rtmsg->rtm_protocol);
ctx->rtmsg->rtm_flags |= RTM_F_OFFLOAD;
write(glob->sock, fpm, fpm_msg_len(fpm));
}
break;
default:
- fprintf(stdout,
- "Ignoring netlink message - Type: %s(%d)\n",
- netlink_msg_type_to_s(hdr->nlmsg_type),
- hdr->nlmsg_type);
+ fprintf(glob->output_file, "Ignoring netlink message - Type: %s(%d)\n",
+ netlink_msg_type_to_s(hdr->nlmsg_type), hdr->nlmsg_type);
}
}
}
@@ -734,8 +731,8 @@ static void parse_netlink_msg(char *buf, size_t buf_len, fpm_msg_hdr_t *fpm)
*/
static void process_fpm_msg(fpm_msg_hdr_t *hdr)
{
- fprintf(stdout, "FPM message - Type: %d, Length %d\n", hdr->msg_type,
- ntohs(hdr->msg_len));
+ fprintf(glob->output_file, "FPM message - Type: %d, Length %d\n", hdr->msg_type,
+ ntohs(hdr->msg_len));
if (hdr->msg_type != FPM_MSG_TYPE_NETLINK) {
fprintf(stderr, "Unknown fpm message type %u\n", hdr->msg_type);
@@ -770,12 +767,12 @@ int main(int argc, char **argv)
pid_t daemon;
int r;
bool fork_daemon = false;
-
- setbuf(stdout, NULL);
+ const char *output_file = NULL;
memset(glob, 0, sizeof(*glob));
+ glob->output_file = stdout;
- while ((r = getopt(argc, argv, "rdv")) != -1) {
+ while ((r = getopt(argc, argv, "rdvo:")) != -1) {
switch (r) {
case 'r':
glob->reflect = true;
@@ -786,9 +783,23 @@ int main(int argc, char **argv)
case 'v':
glob->dump_hex = true;
break;
+ case 'o':
+ output_file = optarg;
+ break;
}
}
+ if (output_file) {
+ glob->output_file = fopen(output_file, "w");
+ if (!glob->output_file) {
+ fprintf(stderr, "Failed to open output file %s: %s\n", output_file,
+ strerror(errno));
+ exit(1);
+ }
+ }
+
+ setbuf(glob->output_file, NULL);
+
if (fork_daemon) {
daemon = fork();
@@ -805,7 +816,7 @@ int main(int argc, char **argv)
while (1) {
glob->sock = accept_conn(glob->server_sock);
fpm_serve();
- fprintf(stdout, "Done serving client");
+ fprintf(glob->output_file, "Done serving client\n");
}
}
#else
diff --git a/zebra/interface.c b/zebra/interface.c
index b7a790382d..fd1ea380a5 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -40,8 +40,8 @@ DEFINE_MTYPE_STATIC(ZEBRA, ZINFO, "Zebra Interface Information");
#define ZEBRA_PTM_SUPPORT
-DEFINE_HOOK(zebra_if_extra_info, (struct vty * vty, struct interface *ifp),
- (vty, ifp));
+DEFINE_HOOK(zebra_if_extra_info, (struct vty * vty, json_object *json_if, struct interface *ifp),
+ (vty, json_if, ifp));
DEFINE_MTYPE_STATIC(ZEBRA, ZIF_DESC, "Intf desc");
@@ -1728,7 +1728,7 @@ interface_bridge_vxlan_vlan_vni_map_update(struct zebra_dplane_ctx *ctx,
dplane_ctx_get_ifp_vxlan_vni_array(ctx);
struct zebra_vxlan_vni vni_start, vni_end;
struct hash *vni_table = NULL;
- struct zebra_vxlan_vni vni, *vnip;
+ struct zebra_vxlan_vni vni;
vni_t vni_id;
vlanid_t vid;
int i;
@@ -1762,11 +1762,8 @@ interface_bridge_vxlan_vlan_vni_map_update(struct zebra_dplane_ctx *ctx,
vni_start.vni, vni_end.vni, ifp->name,
ifp->ifindex);
- if (!vni_table) {
+ if (!vni_table)
vni_table = zebra_vxlan_vni_table_create();
- if (!vni_table)
- return;
- }
for (vid = vni_start.access_vlan, vni_id = vni_start.vni;
vid <= vni_end.access_vlan; vid++, vni_id++) {
@@ -1774,9 +1771,7 @@ interface_bridge_vxlan_vlan_vni_map_update(struct zebra_dplane_ctx *ctx,
memset(&vni, 0, sizeof(vni));
vni.vni = vni_id;
vni.access_vlan = vid;
- vnip = hash_get(vni_table, &vni, zebra_vxlan_vni_alloc);
- if (!vnip)
- return;
+ (void)hash_get(vni_table, &vni, zebra_vxlan_vni_alloc);
}
memset(&vni_start, 0, sizeof(vni_start));
@@ -2851,7 +2846,7 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp)
&iflp->rmt_ip, iflp->rmt_as);
}
- hook_call(zebra_if_extra_info, vty, ifp);
+ hook_call(zebra_if_extra_info, vty, NULL, ifp);
if (listhead(ifp->nbr_connected))
vty_out(vty, " Neighbor address(s):\n");
@@ -3257,6 +3252,8 @@ static void if_dump_vty_json(struct vty *vty, struct interface *ifp,
json_object_int_add(json_te, "neighborAsbrAs", iflp->rmt_as);
}
+ hook_call(zebra_if_extra_info, vty, json_if, ifp);
+
if (listhead(ifp->nbr_connected)) {
json_object *json_nbr_addrs;
diff --git a/zebra/interface.h b/zebra/interface.h
index 0f5c997403..5b45656bd5 100644
--- a/zebra/interface.h
+++ b/zebra/interface.h
@@ -223,8 +223,8 @@ struct zebra_if {
char *desc;
};
-DECLARE_HOOK(zebra_if_extra_info, (struct vty * vty, struct interface *ifp),
- (vty, ifp));
+DECLARE_HOOK(zebra_if_extra_info, (struct vty * vty, json_object *json_if, struct interface *ifp),
+ (vty, json_if, ifp));
#define IS_ZEBRA_IF_VRF(ifp) \
(((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_VRF)
diff --git a/zebra/rtadv.c b/zebra/rtadv.c
index 467bcb6b16..a767bda72e 100644
--- a/zebra/rtadv.c
+++ b/zebra/rtadv.c
@@ -1726,7 +1726,7 @@ int rtadv_dnssl_encode(uint8_t *out, const char *in)
}
/* Dump interface ND information to vty. */
-static int nd_dump_vty(struct vty *vty, struct interface *ifp)
+static int nd_dump_vty(struct vty *vty, json_object *json_if, struct interface *ifp)
{
struct zebra_if *zif;
struct rtadvconf *rtadv;
@@ -1735,7 +1735,7 @@ static int nd_dump_vty(struct vty *vty, struct interface *ifp)
zif = (struct zebra_if *)ifp->info;
rtadv = &zif->rtadv;
- if (rtadv->AdvSendAdvertisements) {
+ if (!json_if && rtadv->AdvSendAdvertisements) {
vty_out(vty,
" ND advertised reachable time is %d milliseconds\n",
rtadv->AdvReachableTime);
@@ -1792,6 +1792,63 @@ static int nd_dump_vty(struct vty *vty, struct interface *ifp)
vty_out(vty,
" ND router advertisements with Adv. Interval option.\n");
}
+
+ if (json_if && rtadv->AdvSendAdvertisements) {
+ json_object_int_add(json_if, "ndAdvertisedReachableTimeMsecs",
+ rtadv->AdvReachableTime);
+ json_object_int_add(json_if, "ndAdvertisedRetransmitIntervalMsecs",
+ rtadv->AdvRetransTimer);
+ json_object_int_add(json_if, "ndAdvertisedHopCountLimitHops", rtadv->AdvCurHopLimit);
+ json_object_int_add(json_if, "ndRouterAdvertisementsSent", zif->ra_sent);
+ json_object_int_add(json_if, "ndRouterAdvertisementsRcvd", zif->ra_rcvd);
+
+ interval = rtadv->MaxRtrAdvInterval;
+ if (interval % 1000)
+ json_object_int_add(json_if, "ndRouterAdvertisementsIntervalMsecs",
+ interval);
+ else
+ json_object_int_add(json_if, "ndRouterAdvertisementsIntervalSecs",
+ interval / 1000);
+
+ json_object_boolean_add(json_if, "ndRouterAdvertisementsDoNotUseFastRetransmit",
+ !rtadv->UseFastRexmit);
+
+ if (rtadv->AdvDefaultLifetime != -1)
+ json_object_int_add(json_if, "ndRouterAdvertisementsLiveForSecs",
+ rtadv->AdvDefaultLifetime);
+ else
+ json_object_boolean_add(json_if,
+ "ndRouterAdvertisementsLifetimeTracksRaInterval",
+ true);
+
+ json_object_string_add(json_if, "ndRouterAdvertisementDefaultRouterPreference",
+ rtadv_pref_strs[rtadv->DefaultPreference]);
+
+ if (rtadv->AdvManagedFlag)
+ json_object_boolean_add(json_if, "hostsUseDhcpToObtainRoutableAddresses",
+ true);
+ else
+ json_object_boolean_add(json_if, "hostsUseStatelessAutoconfigForAddresses",
+ true);
+
+ if (rtadv->AdvHomeAgentFlag) {
+ json_object_boolean_add(json_if,
+ "ndRouterAdvertisementsWithHomeAgentFlagBit", true);
+ if (rtadv->HomeAgentLifetime != -1)
+ json_object_int_add(json_if, "homeAgentLifetimeSecs",
+ rtadv->HomeAgentLifetime);
+ else
+ json_object_boolean_add(json_if,
+ "homeAgentLifetimeTracksRaLifetime", true);
+
+ json_object_int_add(json_if, "homeAgentPreference",
+ rtadv->HomeAgentLifetime);
+ }
+ if (rtadv->AdvIntervalOption)
+ json_object_boolean_add(json_if,
+ "ndRouterAdvertisementsWithAdvIntervalOption", true);
+ }
+
return 0;
}
diff --git a/zebra/zebra_neigh.c b/zebra/zebra_neigh.c
index a222e7f6e8..8a91f2719b 100644
--- a/zebra/zebra_neigh.c
+++ b/zebra/zebra_neigh.c
@@ -153,14 +153,18 @@ void zebra_neigh_del(struct interface *ifp, struct ipaddr *ip)
/* kernel neigh delete all for a given interface */
void zebra_neigh_del_all(struct interface *ifp)
{
- struct zebra_neigh_ent *n, *nn;
+ struct zebra_neigh_ent *n, *next;
if (IS_ZEBRA_DEBUG_NEIGH)
zlog_debug("zebra neigh delete all for interface %s/%d",
ifp->name, ifp->ifindex);
- RB_FOREACH_SAFE (n, zebra_neigh_rb_head, &zneigh_info->neigh_rb_tree, nn)
- zebra_neigh_del(ifp, &n->ip);
+ RB_FOREACH_SAFE (n, zebra_neigh_rb_head, &zneigh_info->neigh_rb_tree, next) {
+ if (n->ifindex == ifp->ifindex) {
+ /* Free the neighbor directly instead of looking it up again */
+ zebra_neigh_free(n);
+ }
+ }
}
/* kernel neigh add */
diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c
index f5141c8f23..5b7452a79e 100644
--- a/zebra/zebra_nhg.c
+++ b/zebra/zebra_nhg.c
@@ -2930,6 +2930,68 @@ static uint32_t proto_nhg_nexthop_active_update(struct nexthop_group *nhg)
return curr_active;
}
+void nexthop_vrf_update(struct route_node *rn, struct route_entry *re, vrf_id_t vrf_id)
+{
+ struct nhg_hash_entry *curr_nhe, *new_nhe;
+ afi_t rt_afi = family2afi(rn->p.family);
+ struct nexthop *nexthop;
+
+ re->vrf_id = vrf_id;
+
+ /* Make a local copy of the existing nhe, so we don't work on/modify
+ * the shared nhe.
+ */
+ curr_nhe = zebra_nhe_copy(re->nhe, re->nhe->id);
+
+ if (IS_ZEBRA_DEBUG_NHG_DETAIL)
+ zlog_debug("%s: re %p nhe %p (%pNG), curr_nhe %p", __func__, re, re->nhe, re->nhe,
+ curr_nhe);
+
+ /* Clear the existing id, if any: this will avoid any confusion
+ * if the id exists, and will also force the creation
+ * of a new nhe reflecting the changes we may make in this local copy.
+ */
+ curr_nhe->id = 0;
+
+ curr_nhe->vrf_id = vrf_id;
+ for (ALL_NEXTHOPS(curr_nhe->nhg, nexthop)) {
+ if (!nexthop->ifindex)
+ /* change VRF ID of nexthop without interfaces
+ * (eg. blackhole)
+ */
+ nexthop->vrf_id = vrf_id;
+ }
+
+ if (zebra_nhg_get_backup_nhg(curr_nhe)) {
+ for (ALL_NEXTHOPS(curr_nhe->backup_info->nhe->nhg, nexthop)) {
+ if (!nexthop->ifindex)
+ /* change VRF ID of nexthop without interfaces
+ * (eg. blackhole)
+ */
+ nexthop->vrf_id = vrf_id;
+ }
+ }
+
+ /*
+ * Ref or create an nhe that matches the current state of the
+ * nexthop(s).
+ */
+ new_nhe = zebra_nhg_rib_find_nhe(curr_nhe, rt_afi);
+
+ if (IS_ZEBRA_DEBUG_NHG_DETAIL)
+ zlog_debug("%s: re %p CHANGED: nhe %p (%pNG) => new_nhe %p (%pNG)", __func__, re,
+ re->nhe, re->nhe, new_nhe, new_nhe);
+
+ route_entry_update_nhe(re, new_nhe);
+
+ /*
+ * Do not need the old / copied nhe anymore since it
+ * was either copied over into a new nhe or not
+ * used at all.
+ */
+ zebra_nhg_free(curr_nhe);
+}
+
/*
* This function takes the start of two comparable nexthops from two different
* nexthop groups and walks them to see if they can be considered the same
diff --git a/zebra/zebra_nhg.h b/zebra/zebra_nhg.h
index 0f90627a0d..de6f6123aa 100644
--- a/zebra/zebra_nhg.h
+++ b/zebra/zebra_nhg.h
@@ -401,6 +401,7 @@ extern void zebra_nhg_mark_keep(void);
/* Nexthop resolution processing */
struct route_entry; /* Forward ref to avoid circular includes */
+extern void nexthop_vrf_update(struct route_node *rn, struct route_entry *re, vrf_id_t vrf_id);
extern int nexthop_active_update(struct route_node *rn, struct route_entry *re,
struct route_entry *old_re);
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index 8cea605f41..20ec25a431 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -903,6 +903,11 @@ void zebra_rtable_node_cleanup(struct route_table *table,
rib_unlink(node, re);
}
+ zebra_node_info_cleanup(node);
+}
+
+void zebra_node_info_cleanup(struct route_node *node)
+{
if (node->info) {
rib_dest_t *dest = node->info;
@@ -4498,6 +4503,12 @@ rib_update_handle_kernel_route_down_possibility(struct route_node *rn,
bool alive = false;
for (ALL_NEXTHOPS(re->nhe->nhg, nexthop)) {
+ if (!nexthop->ifindex) {
+ /* blackhole nexthops have no interfaces */
+ alive = true;
+ break;
+ }
+
struct interface *ifp = if_lookup_by_index(nexthop->ifindex,
nexthop->vrf_id);
diff --git a/zebra/zebra_srv6.c b/zebra/zebra_srv6.c
index 51efcceb75..f9b5dd8808 100644
--- a/zebra/zebra_srv6.c
+++ b/zebra/zebra_srv6.c
@@ -1236,7 +1236,7 @@ static bool alloc_srv6_sid_func_explicit(struct zebra_srv6_sid_block *block,
zlog_warn("%s: function %u is outside ELIB [%u/%u] and EWLIB alloc ranges [%u/%u]",
__func__, sid_func, elib_start,
elib_end, ewlib_start, ewlib_end);
- return -1;
+ return false;
}
} else if (format->type == SRV6_SID_FORMAT_TYPE_UNCOMPRESSED) {
uint32_t explicit_start =
@@ -1395,7 +1395,7 @@ static bool alloc_srv6_sid_func_dynamic(struct zebra_srv6_sid_block *block,
dynamic_end) {
zlog_warn("%s: SRv6: Warning, SRv6 SID Dynamic alloc space is depleted",
__func__);
- return NULL;
+ return false;
}
/*
diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c
index 7bfe07b4cf..d652c57388 100644
--- a/zebra/zebra_vrf.c
+++ b/zebra/zebra_vrf.c
@@ -162,6 +162,69 @@ static int zebra_vrf_enable(struct vrf *vrf)
return 0;
}
+/* update the VRF ID of a routing table and their routing entries */
+static void zebra_vrf_disable_update_vrfid(struct zebra_vrf *zvrf, afi_t afi, safi_t safi)
+{
+ struct rib_table_info *info;
+ struct route_entry *re, *nre;
+ struct route_node *rn, *nrn;
+ bool empty_table = true;
+ bool rn_delete;
+
+ /* Assign the table to the default VRF.
+ * Although the table is not technically owned by the default VRF,
+ * the code assumes that unassigned routing tables are
+ * associated with the default VRF.
+ */
+ info = route_table_get_info(zvrf->table[afi][safi]);
+ info->zvrf = vrf_info_lookup(VRF_DEFAULT);
+
+ rn = route_top(zvrf->table[afi][safi]);
+ if (rn)
+ empty_table = false;
+ while (rn) {
+ if (!rn->info) {
+ rn = route_next(rn);
+ continue;
+ }
+
+ /* Assign the kernel route entries to the default VRF,
+ * even though they are not actually owned by it.
+ *
+ * Remove route nodes that were created by FRR daemons,
+ * unless they are associated with the table rather than the VRF.
+ * Routes associated with the VRF are not needed once the VRF is
+ * disabled.
+ */
+ rn_delete = true;
+ RNODE_FOREACH_RE_SAFE (rn, re, nre) {
+ if (re->type == ZEBRA_ROUTE_KERNEL ||
+ CHECK_FLAG(re->flags, ZEBRA_FLAG_TABLEID)) {
+ nexthop_vrf_update(rn, re, VRF_DEFAULT);
+ if (CHECK_FLAG(re->flags, ZEBRA_FLAG_TABLEID))
+ /* reinstall routes */
+ rib_install_kernel(rn, re, NULL);
+ rn_delete = false;
+ } else
+ rib_unlink(rn, re);
+ }
+ if (rn_delete) {
+ nrn = route_next(rn);
+ zebra_node_info_cleanup(rn);
+ rn->info = NULL;
+ route_unlock_node(rn);
+ rn = nrn;
+ } else {
+ empty_table = false;
+ rn = route_next(rn);
+ }
+ }
+
+ if (empty_table)
+ zebra_router_release_table(zvrf, zvrf->table_id, afi, safi);
+ zvrf->table[afi][safi] = NULL;
+}
+
/* Callback upon disabling a VRF. */
static int zebra_vrf_disable(struct vrf *vrf)
{
@@ -224,9 +287,13 @@ static int zebra_vrf_disable(struct vrf *vrf)
* we no-longer need this pointer.
*/
for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) {
- zebra_router_release_table(zvrf, zvrf->table_id, afi,
- safi);
- zvrf->table[afi][safi] = NULL;
+ if (!zvrf->table[afi][safi] || vrf->vrf_id == VRF_DEFAULT) {
+ zebra_router_release_table(zvrf, zvrf->table_id, afi, safi);
+ zvrf->table[afi][safi] = NULL;
+ continue;
+ }
+
+ zebra_vrf_disable_update_vrfid(zvrf, afi, safi);
}
}
@@ -357,19 +424,50 @@ static void zebra_rnhtable_node_cleanup(struct route_table *table,
static void zebra_vrf_table_create(struct zebra_vrf *zvrf, afi_t afi,
safi_t safi)
{
+ vrf_id_t vrf_id = zvrf->vrf->vrf_id;
+ struct rib_table_info *info;
+ struct route_entry *re;
struct route_node *rn;
struct prefix p;
assert(!zvrf->table[afi][safi]);
+ /* Attempt to retrieve the Linux routing table using zvrf->table_id.
+ * If the table was created before the VRF, it will already exist.
+ * Otherwise, create a new table.
+ */
zvrf->table[afi][safi] =
zebra_router_get_table(zvrf, zvrf->table_id, afi, safi);
+ /* If the table existed before the VRF was created, info->zvrf was
+ * referring to the default VRF.
+ * Assign the table to the new VRF.
+ * Note: FRR does not allow multiple VRF interfaces to be created with the
+ * same table ID.
+ */
+ info = route_table_get_info(zvrf->table[afi][safi]);
+ info->zvrf = zvrf;
+
+ /* If the table existed before the VRF was created, their routing entries
+ * was owned by the default VRF.
+ * Re-assign all the routing entries to the new VRF.
+ */
+ for (rn = route_top(zvrf->table[afi][safi]); rn; rn = route_next(rn)) {
+ if (!rn->info)
+ continue;
+
+ RNODE_FOREACH_RE (rn, re)
+ nexthop_vrf_update(rn, re, vrf_id);
+ }
+
memset(&p, 0, sizeof(p));
p.family = afi2family(afi);
+ /* create a fake default route or get the existing one */
rn = srcdest_rnode_get(zvrf->table[afi][safi], &p, NULL);
- zebra_rib_create_dest(rn);
+ if (!rn->info)
+ /* do not override the existing default route */
+ zebra_rib_create_dest(rn);
}
/* Allocate new zebra VRF. */
diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h
index 334bb93684..289a8fcc47 100644
--- a/zebra/zebra_vrf.h
+++ b/zebra/zebra_vrf.h
@@ -263,6 +263,8 @@ extern void zebra_vrf_init(void);
extern void zebra_rtable_node_cleanup(struct route_table *table,
struct route_node *node);
+extern void zebra_node_info_cleanup(struct route_node *node);
+
#ifdef __cplusplus
}
diff --git a/zebra/zebra_vxlan_if.c b/zebra/zebra_vxlan_if.c
index ea0be2f644..4fd9cb6587 100644
--- a/zebra/zebra_vxlan_if.c
+++ b/zebra/zebra_vxlan_if.c
@@ -54,6 +54,8 @@
#include "zebra/zebra_evpn_vxlan.h"
#include "zebra/zebra_router.h"
+DEFINE_MTYPE_STATIC(ZEBRA, L2_VNI, "L2 VNI");
+
static unsigned int zebra_vxlan_vni_hash_keymake(const void *p)
{
const struct zebra_vxlan_vni *vni;
@@ -527,11 +529,7 @@ static int zebra_vxlan_if_add_update_vni(struct zebra_if *zif,
old_vni->access_vlan, vni->vni,
vni->access_vlan);
- zebra_evpn_vl_vxl_deref(old_vni->access_vlan, old_vni->vni,
- zif);
- zebra_evpn_vl_vxl_ref(vni->access_vlan, vni->vni, zif);
- zebra_vxlan_if_update_vni(zif->ifp, vni, ctx);
- zebra_vxlan_vni_free(old_vni);
+
} else {
int ret;
@@ -544,19 +542,20 @@ static int zebra_vxlan_if_add_update_vni(struct zebra_if *zif,
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug("%s vxlan %s vni %u has error accessing bridge table.",
__func__, zif->ifp->name, vni->vni);
+
+ return 0;
} else if (ret == 0) {
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug("%s vxlan %s vni (%u, %u) not present in bridge table",
- __func__, zif->ifp->name, vni->vni,
- vni->access_vlan);
- zebra_evpn_vl_vxl_deref(old_vni->access_vlan,
- old_vni->vni, zif);
- zebra_evpn_vl_vxl_ref(vni->access_vlan, vni->vni, zif);
- zebra_vxlan_if_update_vni(zif->ifp, vni, ctx);
- zebra_vxlan_vni_free(old_vni);
+ __func__, zif->ifp->name, vni->vni, vni->access_vlan);
}
}
+ zebra_evpn_vl_vxl_deref(old_vni->access_vlan, old_vni->vni, zif);
+ zebra_evpn_vl_vxl_ref(vni->access_vlan, vni->vni, zif);
+ zebra_vxlan_if_update_vni(zif->ifp, vni, ctx);
+ zebra_vxlan_vni_free(old_vni);
+
return 0;
}
@@ -608,7 +607,7 @@ void zebra_vxlan_vni_free(void *arg)
vni = (struct zebra_vxlan_vni *)arg;
- XFREE(MTYPE_TMP, vni);
+ XFREE(MTYPE_L2_VNI, vni);
}
void *zebra_vxlan_vni_alloc(void *p)
@@ -617,7 +616,7 @@ void *zebra_vxlan_vni_alloc(void *p)
const struct zebra_vxlan_vni *vnip;
vnip = (const struct zebra_vxlan_vni *)p;
- vni = XCALLOC(MTYPE_TMP, sizeof(*vni));
+ vni = XCALLOC(MTYPE_L2_VNI, sizeof(*vni));
vni->vni = vnip->vni;
vni->access_vlan = vnip->access_vlan;
vni->mcast_grp = vnip->mcast_grp;
@@ -659,8 +658,6 @@ int zebra_vxlan_if_vni_table_create(struct zebra_if *zif)
vni_info = VNI_INFO_FROM_ZEBRA_IF(zif);
vni_info->vni_table = zebra_vxlan_vni_table_create();
- if (!vni_info->vni_table)
- return -ENOMEM;
return 0;
}