summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilippe Guibert <philippe.guibert@6wind.com>2021-06-29 19:20:54 +0200
committerGitHub <noreply@github.com>2021-06-29 19:20:54 +0200
commiteed936b334c1d9a7e94c276c117aa63c54629a48 (patch)
treec002175668418abb606953407d7929e0ee5c6391
parent55a02e1ed4033da0344a41961a7f4f264bfd59ac (diff)
parent0bcf7589a6c638b7ab64d74fcc3e7a228b4ab632 (diff)
Merge pull request #8744 from sworleys/RTADV-Fix-Upstream
zebra: rework RA handling for vrf-lite
-rw-r--r--doc/user/ipv6.rst5
-rw-r--r--zebra/main.c1
-rw-r--r--zebra/rib.h18
-rw-r--r--zebra/rtadv.c409
-rw-r--r--zebra/rtadv.h3
-rw-r--r--zebra/zebra_router.c2
-rw-r--r--zebra/zebra_router.h3
-rw-r--r--zebra/zebra_vrf.c2
8 files changed, 367 insertions, 76 deletions
diff --git a/doc/user/ipv6.rst b/doc/user/ipv6.rst
index 089fae39b1..4f01061e7b 100644
--- a/doc/user/ipv6.rst
+++ b/doc/user/ipv6.rst
@@ -17,6 +17,11 @@ no longer possible.
Router Advertisement
====================
+.. clicmd:: show ipv6 nd ra-interfaces [vrf <VRFNAME|all>]
+
+ Show configured route advertisement interfaces. VRF subcommand only
+ applicable for netns-based vrfs.
+
.. clicmd:: ipv6 nd suppress-ra
Don't send router advertisement messages. The ``no`` form of this command
diff --git a/zebra/main.c b/zebra/main.c
index e36af51005..bded50149f 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -186,7 +186,6 @@ static void sigint(void)
work_queue_free_and_null(&zrouter.lsp_process_q);
vrf_terminate();
- rtadv_terminate();
ns_walk_func(zebra_ns_early_shutdown, NULL, NULL);
zebra_ns_notify_close();
diff --git a/zebra/rib.h b/zebra/rib.h
index 957f38602a..b7ffb9ce8d 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -288,16 +288,30 @@ DECLARE_LIST(re_list, struct route_entry, next);
#define RNODE_NEXT_RE(rn, re) RE_DEST_NEXT_ROUTE(rib_dest_from_rnode(rn), re)
#if defined(HAVE_RTADV)
+PREDECL_SORTLIST_UNIQ(adv_if_list);
/* Structure which hold status of router advertisement. */
struct rtadv {
int sock;
- int adv_if_count;
- int adv_msec_if_count;
+ struct adv_if_list_head adv_if;
+ struct adv_if_list_head adv_msec_if;
struct thread *ra_read;
struct thread *ra_timer;
};
+
+/* adv list node */
+struct adv_if {
+ char name[INTERFACE_NAMSIZ];
+ struct adv_if_list_item list_item;
+};
+
+static int adv_if_cmp(const struct adv_if *a, const struct adv_if *b)
+{
+ return if_cmp_name_func(a->name, b->name);
+}
+
+DECLARE_SORTLIST_UNIQ(adv_if_list, struct adv_if, list_item, adv_if_cmp);
#endif /* HAVE_RTADV */
/*
diff --git a/zebra/rtadv.c b/zebra/rtadv.c
index 1e06b3e0e9..8cb0223a46 100644
--- a/zebra/rtadv.c
+++ b/zebra/rtadv.c
@@ -54,6 +54,7 @@ extern struct zebra_privs_t zserv_privs;
#endif
DEFINE_MTYPE_STATIC(ZEBRA, RTADV_PREFIX, "Router Advertisement Prefix");
+DEFINE_MTYPE_STATIC(ZEBRA, ADV_IF, "Advertised Interface");
#ifdef OPEN_BSD
#include <netinet/icmp6.h>
@@ -92,11 +93,13 @@ static void rtadv_event(struct zebra_vrf *, enum rtadv_event, int);
static int if_join_all_router(int, struct interface *);
static int if_leave_all_router(int, struct interface *);
-static int rtadv_get_socket(struct zebra_vrf *zvrf)
+static struct zebra_vrf *rtadv_interface_get_zvrf(const struct interface *ifp)
{
- if (zvrf->rtadv.sock > 0)
- return zvrf->rtadv.sock;
- return zrouter.rtadv_sock;
+ /* We use the default vrf for rtadv handling except in netns */
+ if (!vrf_is_backend_netns())
+ return vrf_info_lookup(VRF_DEFAULT);
+
+ return vrf_info_lookup(ifp->vrf_id);
}
static int rtadv_increment_received(struct zebra_vrf *zvrf, ifindex_t *ifindex)
@@ -480,7 +483,7 @@ static int rtadv_timer(struct thread *thread)
int period;
zvrf->rtadv.ra_timer = NULL;
- if (zvrf->rtadv.adv_msec_if_count == 0) {
+ if (adv_if_list_count(&zvrf->rtadv.adv_msec_if) == 0) {
period = 1000; /* 1 s */
rtadv_event(zvrf, RTADV_TIMER, 1 /* 1 s */);
} else {
@@ -520,8 +523,8 @@ static int rtadv_timer(struct thread *thread)
ifp->ifindex);
}
- rtadv_send_packet(rtadv_get_socket(zvrf),
- ifp, RA_ENABLE);
+ rtadv_send_packet(zvrf->rtadv.sock, ifp,
+ RA_ENABLE);
} else {
zif->rtadv.AdvIntervalTimer -= period;
if (zif->rtadv.AdvIntervalTimer <= 0) {
@@ -534,8 +537,8 @@ static int rtadv_timer(struct thread *thread)
zif->rtadv
.MaxRtrAdvInterval;
rtadv_send_packet(
- rtadv_get_socket(zvrf),
- ifp, RA_ENABLE);
+ zvrf->rtadv.sock, ifp,
+ RA_ENABLE);
}
}
}
@@ -546,9 +549,10 @@ static int rtadv_timer(struct thread *thread)
static void rtadv_process_solicit(struct interface *ifp)
{
- struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
+ struct zebra_vrf *zvrf;
struct zebra_if *zif;
+ zvrf = rtadv_interface_get_zvrf(ifp);
assert(zvrf);
zif = ifp->info;
@@ -565,7 +569,7 @@ static void rtadv_process_solicit(struct interface *ifp)
if ((zif->rtadv.UseFastRexmit)
|| (zif->rtadv.AdvIntervalTimer <=
(zif->rtadv.MaxRtrAdvInterval - MIN_DELAY_BETWEEN_RAS))) {
- rtadv_send_packet(rtadv_get_socket(zvrf), ifp, RA_ENABLE);
+ rtadv_send_packet(zvrf->rtadv.sock, ifp, RA_ENABLE);
zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
} else
zif->rtadv.AdvIntervalTimer = MIN_DELAY_BETWEEN_RAS;
@@ -788,7 +792,7 @@ static int rtadv_read(struct thread *thread)
zvrf->rtadv.ra_read = NULL;
/* Register myself. */
- rtadv_event(zvrf, RTADV_READ, sock);
+ rtadv_event(zvrf, RTADV_READ, 0);
len = rtadv_recv_packet(zvrf, sock, buf, sizeof(buf), &from, &ifindex,
&hoplimit);
@@ -862,6 +866,201 @@ static int rtadv_make_socket(ns_id_t ns_id)
return sock;
}
+static struct adv_if *adv_if_new(const char *name)
+{
+ struct adv_if *new;
+
+ new = XCALLOC(MTYPE_ADV_IF, sizeof(struct adv_if));
+
+ strlcpy(new->name, name, sizeof(new->name));
+
+ return new;
+}
+
+static void adv_if_free(struct adv_if *adv_if)
+{
+ XFREE(MTYPE_ADV_IF, adv_if);
+}
+
+static bool adv_if_is_empty_internal(const struct adv_if_list_head *adv_if_head)
+{
+ return adv_if_list_count(adv_if_head) ? false : true;
+}
+
+static struct adv_if *adv_if_add_internal(struct adv_if_list_head *adv_if_head,
+ const char *name)
+{
+ struct adv_if adv_if_lookup = {};
+ struct adv_if *adv_if = NULL;
+
+ strlcpy(adv_if_lookup.name, name, sizeof(adv_if_lookup.name));
+ adv_if = adv_if_list_find(adv_if_head, &adv_if_lookup);
+
+ if (adv_if != NULL)
+ return adv_if;
+
+ adv_if = adv_if_new(adv_if_lookup.name);
+ adv_if_list_add(adv_if_head, adv_if);
+
+ return NULL;
+}
+
+static struct adv_if *adv_if_del_internal(struct adv_if_list_head *adv_if_head,
+ const char *name)
+{
+ struct adv_if adv_if_lookup = {};
+ struct adv_if *adv_if = NULL;
+
+ strlcpy(adv_if_lookup.name, name, sizeof(adv_if_lookup.name));
+ adv_if = adv_if_list_find(adv_if_head, &adv_if_lookup);
+
+ if (adv_if == NULL)
+ return NULL;
+
+ adv_if_list_del(adv_if_head, adv_if);
+
+ return adv_if;
+}
+
+static void adv_if_clean_internal(struct adv_if_list_head *adv_if_head)
+{
+ struct adv_if *node = NULL;
+
+ if (!adv_if_is_empty_internal(adv_if_head)) {
+ frr_each_safe (adv_if_list, adv_if_head, node) {
+ adv_if_list_del(adv_if_head, node);
+ adv_if_free(node);
+ }
+ }
+
+ adv_if_list_fini(adv_if_head);
+}
+
+
+/*
+ * Add to list. On Success, return NULL, otherwise return already existing
+ * adv_if.
+ */
+static struct adv_if *adv_if_add(struct zebra_vrf *zvrf, const char *name)
+{
+ struct adv_if *adv_if = NULL;
+
+ adv_if = adv_if_add_internal(&zvrf->rtadv.adv_if, name);
+
+ if (adv_if != NULL)
+ return adv_if;
+
+ if (IS_ZEBRA_DEBUG_EVENT) {
+ struct vrf *vrf = zvrf->vrf;
+
+ zlog_debug("%s: %s:%u IF %s count: %zu", __func__,
+ VRF_LOGNAME(vrf), zvrf_id(zvrf), name,
+ adv_if_list_count(&zvrf->rtadv.adv_if));
+ }
+
+ return NULL;
+}
+
+/*
+ * Del from list. On Success, return the adv_if, otherwise return NULL. Caller
+ * frees.
+ */
+static struct adv_if *adv_if_del(struct zebra_vrf *zvrf, const char *name)
+{
+ struct adv_if *adv_if = NULL;
+
+ adv_if = adv_if_del_internal(&zvrf->rtadv.adv_if, name);
+
+ if (adv_if == NULL)
+ return NULL;
+
+ if (IS_ZEBRA_DEBUG_EVENT) {
+ struct vrf *vrf = zvrf->vrf;
+
+ zlog_debug("%s: %s:%u IF %s count: %zu", __func__,
+ VRF_LOGNAME(vrf), zvrf_id(zvrf), name,
+ adv_if_list_count(&zvrf->rtadv.adv_if));
+ }
+
+ return adv_if;
+}
+
+/*
+ * Add to list. On Success, return NULL, otherwise return already existing
+ * adv_if.
+ */
+static struct adv_if *adv_msec_if_add(struct zebra_vrf *zvrf, const char *name)
+{
+ struct adv_if *adv_if = NULL;
+
+ adv_if = adv_if_add_internal(&zvrf->rtadv.adv_msec_if, name);
+
+ if (adv_if != NULL)
+ return adv_if;
+
+ if (IS_ZEBRA_DEBUG_EVENT) {
+ struct vrf *vrf = zvrf->vrf;
+
+ zlog_debug("%s: %s:%u IF %s count: %zu", __func__,
+ VRF_LOGNAME(vrf), zvrf_id(zvrf), name,
+ adv_if_list_count(&zvrf->rtadv.adv_msec_if));
+ }
+
+ return NULL;
+}
+
+/*
+ * Del from list. On Success, return the adv_if, otherwise return NULL. Caller
+ * frees.
+ */
+static struct adv_if *adv_msec_if_del(struct zebra_vrf *zvrf, const char *name)
+{
+ struct adv_if *adv_if = NULL;
+
+ adv_if = adv_if_del_internal(&zvrf->rtadv.adv_msec_if, name);
+
+ if (adv_if == NULL)
+ return NULL;
+
+ if (IS_ZEBRA_DEBUG_EVENT) {
+ struct vrf *vrf = zvrf->vrf;
+
+ zlog_debug("%s: %s:%u IF %s count: %zu", __func__,
+ VRF_LOGNAME(vrf), zvrf_id(zvrf), name,
+ adv_if_list_count(&zvrf->rtadv.adv_msec_if));
+ }
+
+ return adv_if;
+}
+
+/* Clean adv_if list, called on vrf terminate */
+static void adv_if_clean(struct zebra_vrf *zvrf)
+{
+ if (IS_ZEBRA_DEBUG_EVENT) {
+ struct vrf *vrf = zvrf->vrf;
+
+ zlog_debug("%s: %s:%u count: %zu -> 0", __func__,
+ VRF_LOGNAME(vrf), zvrf_id(zvrf),
+ adv_if_list_count(&zvrf->rtadv.adv_if));
+ }
+
+ adv_if_clean_internal(&zvrf->rtadv.adv_if);
+}
+
+/* Clean adv_msec_if list, called on vrf terminate */
+static void adv_msec_if_clean(struct zebra_vrf *zvrf)
+{
+ if (IS_ZEBRA_DEBUG_EVENT) {
+ struct vrf *vrf = zvrf->vrf;
+
+ zlog_debug("%s: %s:%u count: %zu -> 0", __func__,
+ VRF_LOGNAME(vrf), zvrf_id(zvrf),
+ adv_if_list_count(&zvrf->rtadv.adv_msec_if));
+ }
+
+ adv_if_clean_internal(&zvrf->rtadv.adv_msec_if);
+}
+
static struct rtadv_prefix *rtadv_prefix_new(void)
{
return XCALLOC(MTYPE_RTADV_PREFIX, sizeof(struct rtadv_prefix));
@@ -1006,30 +1205,34 @@ static void ipv6_nd_suppress_ra_set(struct interface *ifp,
{
struct zebra_if *zif;
struct zebra_vrf *zvrf;
+ struct adv_if *adv_if = NULL;
zif = ifp->info;
- zvrf = vrf_info_lookup(ifp->vrf_id);
+
+ zvrf = rtadv_interface_get_zvrf(ifp);
if (status == RA_SUPPRESS) {
/* RA is currently enabled */
if (zif->rtadv.AdvSendAdvertisements) {
- rtadv_send_packet(rtadv_get_socket(zvrf), ifp,
- RA_SUPPRESS);
+ rtadv_send_packet(zvrf->rtadv.sock, ifp, RA_SUPPRESS);
zif->rtadv.AdvSendAdvertisements = 0;
zif->rtadv.AdvIntervalTimer = 0;
- zvrf->rtadv.adv_if_count--;
- if_leave_all_router(rtadv_get_socket(zvrf), ifp);
+ adv_if = adv_if_del(zvrf, ifp->name);
+ if (adv_if == NULL)
+ return; /* Nothing to delete */
+
+ adv_if_free(adv_if);
+
+ if_leave_all_router(zvrf->rtadv.sock, ifp);
- if (zvrf->rtadv.adv_if_count == 0)
+ if (adv_if_list_count(&zvrf->rtadv.adv_if) == 0)
rtadv_event(zvrf, RTADV_STOP, 0);
}
} else {
if (!zif->rtadv.AdvSendAdvertisements) {
zif->rtadv.AdvSendAdvertisements = 1;
zif->rtadv.AdvIntervalTimer = 0;
- zvrf->rtadv.adv_if_count++;
-
if ((zif->rtadv.MaxRtrAdvInterval >= 1000)
&& zif->rtadv.UseFastRexmit) {
/*
@@ -1041,11 +1244,14 @@ static void ipv6_nd_suppress_ra_set(struct interface *ifp,
RTADV_NUM_FAST_REXMITS;
}
- if_join_all_router(rtadv_get_socket(zvrf), ifp);
+ adv_if = adv_if_add(zvrf, ifp->name);
+ if (adv_if != NULL)
+ return; /* Alread added */
+
+ if_join_all_router(zvrf->rtadv.sock, ifp);
- if (zvrf->rtadv.adv_if_count == 1)
- rtadv_event(zvrf, RTADV_START,
- rtadv_get_socket(zvrf));
+ if (adv_if_list_count(&zvrf->rtadv.adv_if) == 1)
+ rtadv_event(zvrf, RTADV_START, 0);
}
}
}
@@ -1092,7 +1298,7 @@ static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int enable)
zebra_route_string(client->proto));
return;
}
- if (ifp->vrf_id != zvrf_id(zvrf)) {
+ if (vrf_is_backend_netns() && ifp->vrf_id != zvrf_id(zvrf)) {
struct vrf *vrf = zvrf->vrf;
zlog_debug(
@@ -1136,10 +1342,10 @@ void rtadv_stop_ra(struct interface *ifp)
struct zebra_vrf *zvrf;
zif = ifp->info;
- zvrf = vrf_info_lookup(ifp->vrf_id);
+ zvrf = rtadv_interface_get_zvrf(ifp);
if (zif->rtadv.AdvSendAdvertisements)
- rtadv_send_packet(rtadv_get_socket(zvrf), ifp, RA_SUPPRESS);
+ rtadv_send_packet(zvrf->rtadv.sock, ifp, RA_SUPPRESS);
}
/*
@@ -1179,6 +1385,76 @@ void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS)
zebra_interface_radv_set(client, hdr, msg, zvrf, 1);
}
+static void show_zvrf_rtadv_adv_if_helper(struct vty *vty,
+ struct adv_if_list_head *adv_if_head)
+{
+ struct adv_if *node = NULL;
+
+ if (!adv_if_is_empty_internal(adv_if_head)) {
+ frr_each (adv_if_list, adv_if_head, node) {
+ vty_out(vty, " %s\n", node->name);
+ }
+ }
+
+ vty_out(vty, "\n");
+}
+
+static void show_zvrf_rtadv_helper(struct vty *vty, struct zebra_vrf *zvrf)
+{
+ vty_out(vty, "VRF: %s\n", zvrf_name(zvrf));
+ vty_out(vty, " Interfaces:\n");
+ show_zvrf_rtadv_adv_if_helper(vty, &zvrf->rtadv.adv_if);
+
+ vty_out(vty, " Interfaces(msec):\n");
+ show_zvrf_rtadv_adv_if_helper(vty, &zvrf->rtadv.adv_msec_if);
+}
+
+DEFPY(show_ipv6_nd_ra_if, show_ipv6_nd_ra_if_cmd,
+ "show ipv6 nd ra-interfaces [vrf<NAME$vrf_name|all$vrf_all>]",
+ SHOW_STR IP6_STR
+ "Neighbor discovery\n"
+ "Route Advertisement Interfaces\n" VRF_FULL_CMD_HELP_STR)
+{
+ struct zebra_vrf *zvrf = NULL;
+
+ if (!vrf_is_backend_netns() && (vrf_name || vrf_all)) {
+ vty_out(vty,
+ "%% VRF subcommand only applicable for netns-based vrfs.\n");
+ return CMD_WARNING;
+ }
+
+ if (vrf_all) {
+ struct vrf *vrf;
+
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+ struct zebra_vrf *zvrf;
+
+ zvrf = vrf->info;
+ if (!zvrf)
+ continue;
+
+ show_zvrf_rtadv_helper(vty, zvrf);
+ }
+
+ return CMD_SUCCESS;
+ }
+
+ if (vrf_name)
+ zvrf = zebra_vrf_lookup_by_name(vrf_name);
+ else
+ zvrf = zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME);
+
+ if (!zvrf) {
+ vty_out(vty, "%% VRF '%s' specified does not exist\n",
+ vrf_name);
+ return CMD_WARNING;
+ }
+
+ show_zvrf_rtadv_helper(vty, zvrf);
+
+ return CMD_SUCCESS;
+}
+
DEFUN (ipv6_nd_ra_fast_retrans,
ipv6_nd_ra_fast_retrans_cmd,
"ipv6 nd ra-fast-retrans",
@@ -1379,8 +1655,9 @@ DEFUN (ipv6_nd_ra_interval_msec,
unsigned interval;
struct zebra_if *zif = ifp->info;
struct zebra_vrf *zvrf;
+ struct adv_if *adv_if;
- zvrf = vrf_info_lookup(ifp->vrf_id);
+ zvrf = rtadv_interface_get_zvrf(ifp);
interval = strtoul(argv[idx_number]->arg, NULL, 10);
if ((zif->rtadv.AdvDefaultLifetime != -1
@@ -1390,11 +1667,14 @@ DEFUN (ipv6_nd_ra_interval_msec,
return CMD_WARNING_CONFIG_FAILED;
}
- if (zif->rtadv.MaxRtrAdvInterval % 1000)
- zvrf->rtadv.adv_msec_if_count--;
+ if (zif->rtadv.MaxRtrAdvInterval % 1000) {
+ adv_if = adv_msec_if_del(zvrf, ifp->name);
+ if (adv_if != NULL)
+ adv_if_free(adv_if);
+ }
if (interval % 1000)
- zvrf->rtadv.adv_msec_if_count++;
+ (void)adv_msec_if_add(zvrf, ifp->name);
SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
zif->rtadv.MaxRtrAdvInterval = interval;
@@ -1417,8 +1697,9 @@ DEFUN (ipv6_nd_ra_interval,
unsigned interval;
struct zebra_if *zif = ifp->info;
struct zebra_vrf *zvrf;
+ struct adv_if *adv_if;
- zvrf = vrf_info_lookup(ifp->vrf_id);
+ zvrf = rtadv_interface_get_zvrf(ifp);
interval = strtoul(argv[idx_number]->arg, NULL, 10);
if ((zif->rtadv.AdvDefaultLifetime != -1
@@ -1428,8 +1709,11 @@ DEFUN (ipv6_nd_ra_interval,
return CMD_WARNING_CONFIG_FAILED;
}
- if (zif->rtadv.MaxRtrAdvInterval % 1000)
- zvrf->rtadv.adv_msec_if_count--;
+ if (zif->rtadv.MaxRtrAdvInterval % 1000) {
+ adv_if = adv_msec_if_del(zvrf, ifp->name);
+ if (adv_if != NULL)
+ adv_if_free(adv_if);
+ }
/* convert to milliseconds */
interval = interval * 1000;
@@ -1456,11 +1740,15 @@ DEFUN (no_ipv6_nd_ra_interval,
VTY_DECLVAR_CONTEXT(interface, ifp);
struct zebra_if *zif = ifp->info;
struct zebra_vrf *zvrf = NULL;
+ struct adv_if *adv_if;
- zvrf = vrf_info_lookup(ifp->vrf_id);
+ zvrf = rtadv_interface_get_zvrf(ifp);
- if (zif->rtadv.MaxRtrAdvInterval % 1000)
- zvrf->rtadv.adv_msec_if_count--;
+ if (zif->rtadv.MaxRtrAdvInterval % 1000) {
+ adv_if = adv_msec_if_del(zvrf, ifp->name);
+ if (adv_if != NULL)
+ adv_if_free(adv_if);
+ }
UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
@@ -2451,7 +2739,7 @@ static int rtadv_config_write(struct vty *vty, struct interface *ifp)
static void rtadv_event(struct zebra_vrf *zvrf, enum rtadv_event event, int val)
{
- struct rtadv *rtadv = &zvrf->rtadv;
+ struct rtadv *rtadv;
if (IS_ZEBRA_DEBUG_EVENT) {
struct vrf *vrf = zvrf->vrf;
@@ -2460,9 +2748,11 @@ static void rtadv_event(struct zebra_vrf *zvrf, enum rtadv_event event, int val)
VRF_LOGNAME(vrf), event, val);
}
+ rtadv = &zvrf->rtadv;
+
switch (event) {
case RTADV_START:
- thread_add_read(zrouter.master, rtadv_read, zvrf, val,
+ thread_add_read(zrouter.master, rtadv_read, zvrf, rtadv->sock,
&rtadv->ra_read);
thread_add_event(zrouter.master, rtadv_timer, zvrf, 0,
&rtadv->ra_timer);
@@ -2480,7 +2770,7 @@ static void rtadv_event(struct zebra_vrf *zvrf, enum rtadv_event event, int val)
&rtadv->ra_timer);
break;
case RTADV_READ:
- thread_add_read(zrouter.master, rtadv_read, zvrf, val,
+ thread_add_read(zrouter.master, rtadv_read, zvrf, rtadv->sock,
&rtadv->ra_read);
break;
default:
@@ -2489,37 +2779,27 @@ static void rtadv_event(struct zebra_vrf *zvrf, enum rtadv_event event, int val)
return;
}
-void rtadv_init(struct zebra_vrf *zvrf)
+void rtadv_vrf_init(struct zebra_vrf *zvrf)
{
- if (vrf_is_backend_netns()) {
- zvrf->rtadv.sock = rtadv_make_socket(zvrf->zns->ns_id);
- zrouter.rtadv_sock = -1;
- } else {
- zvrf->rtadv.sock = -1;
- if (zrouter.rtadv_sock < 0)
- zrouter.rtadv_sock =
- rtadv_make_socket(zvrf->zns->ns_id);
- }
+ if (!vrf_is_backend_netns() && (zvrf_id(zvrf) != VRF_DEFAULT))
+ return;
+
+ zvrf->rtadv.sock = rtadv_make_socket(zvrf->zns->ns_id);
}
void rtadv_vrf_terminate(struct zebra_vrf *zvrf)
{
+ if (!vrf_is_backend_netns() && (zvrf_id(zvrf) != VRF_DEFAULT))
+ return;
+
rtadv_event(zvrf, RTADV_STOP, 0);
if (zvrf->rtadv.sock >= 0) {
close(zvrf->rtadv.sock);
zvrf->rtadv.sock = -1;
}
- zvrf->rtadv.adv_if_count = 0;
- zvrf->rtadv.adv_msec_if_count = 0;
-}
-
-void rtadv_terminate(void)
-{
- if (zrouter.rtadv_sock >= 0) {
- close(zrouter.rtadv_sock);
- zrouter.rtadv_sock = -1;
- }
+ adv_if_clean(zvrf);
+ adv_msec_if_clean(zvrf);
}
void rtadv_cmd_init(void)
@@ -2527,6 +2807,8 @@ void rtadv_cmd_init(void)
hook_register(zebra_if_extra_info, nd_dump_vty);
hook_register(zebra_if_config_wr, rtadv_config_write);
+ install_element(VIEW_NODE, &show_ipv6_nd_ra_if_cmd);
+
install_element(INTERFACE_NODE, &ipv6_nd_ra_fast_retrans_cmd);
install_element(INTERFACE_NODE, &no_ipv6_nd_ra_fast_retrans_cmd);
install_element(INTERFACE_NODE, &ipv6_nd_ra_retrans_interval_cmd);
@@ -2629,14 +2911,11 @@ static int if_leave_all_router(int sock, struct interface *ifp)
}
#else
-void rtadv_init(struct zebra_vrf *zvrf)
-{
- /* Empty.*/;
-}
-void rtadv_terminate(void)
+void rtadv_vrf_init(struct zebra_vrf *zvrf)
{
/* Empty.*/;
}
+
void rtadv_cmd_init(void)
{
/* Empty.*/;
diff --git a/zebra/rtadv.h b/zebra/rtadv.h
index d7a1ccfb29..7b71ee45a2 100644
--- a/zebra/rtadv.h
+++ b/zebra/rtadv.h
@@ -152,9 +152,8 @@ enum ipv6_nd_suppress_ra_status {
RA_SUPPRESS,
};
-extern void rtadv_init(struct zebra_vrf *zvrf);
+extern void rtadv_vrf_init(struct zebra_vrf *zvrf);
extern void rtadv_vrf_terminate(struct zebra_vrf *zvrf);
-extern void rtadv_terminate(void);
extern void rtadv_stop_ra(struct interface *ifp);
extern void rtadv_stop_ra_all(void);
extern void rtadv_cmd_init(void);
diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c
index 5a00f3155d..d930f59866 100644
--- a/zebra/zebra_router.c
+++ b/zebra/zebra_router.c
@@ -268,8 +268,6 @@ void zebra_router_init(bool asic_offload, bool notify_on_ack)
zrouter.packets_to_process = ZEBRA_ZAPI_PACKETS_TO_PROCESS;
- zrouter.rtadv_sock = -1;
-
zebra_vxlan_init();
zebra_mlag_init();
diff --git a/zebra/zebra_router.h b/zebra/zebra_router.h
index 08c5fcaf8d..408f9cbee5 100644
--- a/zebra/zebra_router.h
+++ b/zebra/zebra_router.h
@@ -162,9 +162,6 @@ struct zebra_router {
struct hash *iptable_hash;
- /* used if vrf backend is not network namespace */
- int rtadv_sock;
-
/* A sequence number used for tracking routes */
_Atomic uint32_t sequence_num;
diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c
index a0c63e4202..2430b51989 100644
--- a/zebra/zebra_vrf.c
+++ b/zebra/zebra_vrf.c
@@ -131,7 +131,7 @@ static int zebra_vrf_enable(struct vrf *vrf)
else
zvrf->zns = zebra_ns_lookup(NS_DEFAULT);
#if defined(HAVE_RTADV)
- rtadv_init(zvrf);
+ rtadv_vrf_init(zvrf);
#endif
/* Inform clients that the VRF is now active. This is an