diff options
| author | Philippe Guibert <philippe.guibert@6wind.com> | 2021-06-29 19:20:54 +0200 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-06-29 19:20:54 +0200 | 
| commit | eed936b334c1d9a7e94c276c117aa63c54629a48 (patch) | |
| tree | c002175668418abb606953407d7929e0ee5c6391 | |
| parent | 55a02e1ed4033da0344a41961a7f4f264bfd59ac (diff) | |
| parent | 0bcf7589a6c638b7ab64d74fcc3e7a228b4ab632 (diff) | |
Merge pull request #8744 from sworleys/RTADV-Fix-Upstream
zebra: rework RA handling for vrf-lite
| -rw-r--r-- | doc/user/ipv6.rst | 5 | ||||
| -rw-r--r-- | zebra/main.c | 1 | ||||
| -rw-r--r-- | zebra/rib.h | 18 | ||||
| -rw-r--r-- | zebra/rtadv.c | 409 | ||||
| -rw-r--r-- | zebra/rtadv.h | 3 | ||||
| -rw-r--r-- | zebra/zebra_router.c | 2 | ||||
| -rw-r--r-- | zebra/zebra_router.h | 3 | ||||
| -rw-r--r-- | zebra/zebra_vrf.c | 2 | 
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  | 
