]> git.proxmox.com Git - mirror_frr.git/blobdiff - zebra/rtadv.c
Merge pull request #5793 from ton31337/fix/formatting_show_bgp_summary_failed
[mirror_frr.git] / zebra / rtadv.c
index 0adf654aaf72718098c64ba21c5550e3378c5914..e9a97d4b152cd704726bcf695588854c4466486f 100644 (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--;
@@ -959,16 +965,25 @@ static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int enable)
        ifindex_t ifindex;
        struct interface *ifp;
        struct zebra_if *zif;
-       int ra_interval;
+       int ra_interval_rxd;
 
        s = msg;
 
        /* Get interface index and RA interval. */
        STREAM_GETL(s, ifindex);
-       STREAM_GETL(s, ra_interval);
+       STREAM_GETL(s, ra_interval_rxd);
+
+       if (ra_interval_rxd < 0) {
+               zlog_warn(
+                       "Requested RA interval %d is garbage; ignoring request",
+                       ra_interval_rxd);
+               return;
+       }
+
+       unsigned int ra_interval = ra_interval_rxd;
 
        if (IS_ZEBRA_DEBUG_EVENT)
-               zlog_debug("%u: IF %u RA %s from client %s, interval %ds",
+               zlog_debug("%u: IF %u RA %s from client %s, interval %ums",
                           zvrf_id(zvrf), ifindex,
                           enable ? "enable" : "disable",
                           zebra_route_string(client->proto), ra_interval);
@@ -995,7 +1010,7 @@ static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int enable)
                SET_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED);
                ipv6_nd_suppress_ra_set(ifp, RA_ENABLE);
                if (ra_interval
-                   && (ra_interval * 1000) < zif->rtadv.MaxRtrAdvInterval
+                   && (ra_interval * 1000) < (unsigned int) zif->rtadv.MaxRtrAdvInterval
                    && !CHECK_FLAG(zif->rtadv.ra_configured,
                                   VTY_RA_INTERVAL_CONFIGURED))
                        zif->rtadv.MaxRtrAdvInterval = ra_interval * 1000;
@@ -1012,6 +1027,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);