Merge pull request #5462 from dslicenc/ipv6-ra-lifetime-0

zebra: send RA lifetime of 0 before ceasing to advertise RAs
This commit is contained in:
David Lamparter 2019-12-06 18:23:39 +01:00 committed by GitHub
commit 0d26af1203
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 50 additions and 5 deletions

View File

@ -1977,6 +1977,8 @@ DEFUN (shutdown_if,
struct zebra_if *if_data;
if (ifp->ifindex != IFINDEX_INTERNAL) {
/* send RA lifetime of 0 before stopping. rfc4861/6.2.5 */
rtadv_stop_ra(ifp);
ret = if_unset_flags(ifp, IFF_UP);
if (ret < 0) {
vty_out(vty, "Can't shutdown interface\n");

View File

@ -145,6 +145,9 @@ static void sigint(void)
atomic_store_explicit(&zrouter.in_shutdown, true,
memory_order_relaxed);
/* send RA lifetime of 0 before stopping. rfc4861/6.2.5 */
rtadv_stop_ra_all();
frr_early_fini();
zebra_dplane_pre_finish();

View File

@ -166,7 +166,8 @@ static int rtadv_recv_packet(struct zebra_vrf *zvrf, int sock, uint8_t *buf,
#define RTADV_MSG_SIZE 4096
/* Send router advertisement packet. */
static void rtadv_send_packet(int sock, struct interface *ifp)
static void rtadv_send_packet(int sock, struct interface *ifp,
ipv6_nd_suppress_ra_status stop)
{
struct msghdr msg;
struct iovec iov;
@ -252,7 +253,10 @@ static void rtadv_send_packet(int sock, struct interface *ifp)
zif->rtadv.AdvDefaultLifetime != -1
? zif->rtadv.AdvDefaultLifetime
: MAX(1, 0.003 * zif->rtadv.MaxRtrAdvInterval);
rtadv->nd_ra_router_lifetime = htons(pkt_RouterLifetime);
/* send RA lifetime of 0 before stopping. rfc4861/6.2.5 */
rtadv->nd_ra_router_lifetime =
(stop == RA_SUPPRESS) ? htons(0) : htons(pkt_RouterLifetime);
rtadv->nd_ra_reachable = htonl(zif->rtadv.AdvReachableTime);
rtadv->nd_ra_retransmit = htonl(0);
@ -512,7 +516,7 @@ static int rtadv_timer(struct thread *thread)
ifp->name);
rtadv_send_packet(rtadv_get_socket(zvrf),
ifp);
ifp, RA_ENABLE);
} else {
zif->rtadv.AdvIntervalTimer -= period;
if (zif->rtadv.AdvIntervalTimer <= 0) {
@ -526,7 +530,7 @@ static int rtadv_timer(struct thread *thread)
.MaxRtrAdvInterval;
rtadv_send_packet(
rtadv_get_socket(zvrf),
ifp);
ifp, RA_ENABLE);
}
}
}
@ -556,7 +560,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);
rtadv_send_packet(rtadv_get_socket(zvrf), ifp, RA_ENABLE);
zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
} else
zif->rtadv.AdvIntervalTimer = MIN_DELAY_BETWEEN_RAS;
@ -911,6 +915,8 @@ static void ipv6_nd_suppress_ra_set(struct interface *ifp,
if (status == RA_SUPPRESS) {
/* RA is currently enabled */
if (zif->rtadv.AdvSendAdvertisements) {
rtadv_send_packet(rtadv_get_socket(zvrf), ifp,
RA_SUPPRESS);
zif->rtadv.AdvSendAdvertisements = 0;
zif->rtadv.AdvIntervalTimer = 0;
zvrf->rtadv.adv_if_count--;
@ -1012,6 +1018,38 @@ stream_failure:
return;
}
/*
* send router lifetime value of zero in RAs on this interface since we're
* ceasing to advertise and want to let our neighbors know.
* RFC 4861 secion 6.2.5
*/
void rtadv_stop_ra(struct interface *ifp)
{
struct zebra_if *zif;
struct zebra_vrf *zvrf;
zif = ifp->info;
zvrf = vrf_info_lookup(ifp->vrf_id);
if (zif->rtadv.AdvSendAdvertisements)
rtadv_send_packet(rtadv_get_socket(zvrf), ifp, RA_SUPPRESS);
}
/*
* send router lifetime value of zero in RAs on all interfaces since we're
* ceasing to advertise globally and want to let all of our neighbors know
* RFC 4861 secion 6.2.5
*/
void rtadv_stop_ra_all(void)
{
struct vrf *vrf;
struct interface *ifp;
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
FOR_ALL_INTERFACES (vrf, ifp)
rtadv_stop_ra(ifp);
}
void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS)
{
zebra_interface_radv_set(client, hdr, msg, zvrf, 0);

View File

@ -140,6 +140,8 @@ typedef enum {
extern void rtadv_init(struct zebra_vrf *zvrf);
extern void rtadv_terminate(struct zebra_vrf *zvrf);
extern void rtadv_stop_ra(struct interface *ifp);
extern void rtadv_stop_ra_all(void);
extern void rtadv_cmd_init(void);
extern void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS);
extern void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS);