From b6120505946e08951fdd9adf8539940777cdb635 Mon Sep 17 00:00:00 2001 From: Daniel Walton Date: Mon, 7 Dec 2015 13:05:34 -0800 Subject: [PATCH] Enable IPv6 ND RA for interfaces that have an IPv6 address Signed-off-by: Daniel Walton Reviewed-by: Donald Sharp Ticket: CM-7932 --- zebra/Makefile.am | 2 +- zebra/connected.c | 8 +++++ zebra/interface.c | 20 +++++++++++ zebra/interface.h | 1 + zebra/rtadv.c | 87 +++++++++++++++++++++++++++------------------- zebra/rtadv.h | 6 ++++ zebra/rtadv_null.c | 27 ++++++++++++++ 7 files changed, 115 insertions(+), 36 deletions(-) create mode 100644 zebra/rtadv_null.c diff --git a/zebra/Makefile.am b/zebra/Makefile.am index 1526a9772a..8246e0b88c 100644 --- a/zebra/Makefile.am +++ b/zebra/Makefile.am @@ -39,7 +39,7 @@ zebra_SOURCES = \ testzebra_SOURCES = test_main.c zebra_rib.c interface.c connected.c debug.c \ zebra_vty.c zebra_ptm.c zebra_routemap.c \ kernel_null.c redistribute_null.c ioctl_null.c misc_null.c zebra_rnh_null.c \ - zebra_ptm_null.c + zebra_ptm_null.c rtadv_null.c noinst_HEADERS = \ connected.h ioctl.h rib.h rt.h zserv.h redistribute.h debug.h rtadv.h \ diff --git a/zebra/connected.c b/zebra/connected.c index 41b68d1564..f67b44ba80 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -36,6 +36,7 @@ #include "zebra/redistribute.h" #include "zebra/interface.h" #include "zebra/connected.h" +#include "zebra/rtadv.h" extern struct zebra_t zebrad; /* communicate the withdrawal of a connected address */ @@ -71,6 +72,10 @@ connected_withdraw (struct connected *ifc) listnode_delete (ifc->ifp->connected, ifc); connected_free (ifc); } + + /* Enable RA suppression if there are no IPv6 addresses on this interface */ + if (! ipv6_address_configured(ifc->ifp)) + ipv6_nd_suppress_ra_set (ifc->ifp, RA_SUPPRESS); } static void @@ -93,6 +98,9 @@ connected_announce (struct interface *ifp, struct connected *ifc) if (ifc->address->family == AF_INET) if_subnet_add (ifp, ifc); + else if (ifc->address->family == AF_INET6) + ipv6_nd_suppress_ra_set (ifp, RA_ENABLE); + zebra_interface_address_add_update (ifp, ifc); if (if_is_operative(ifp)) diff --git a/zebra/interface.c b/zebra/interface.c index bd1e404d23..2768e69a6d 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -1730,6 +1730,8 @@ ipv6_address_install (struct vty *vty, struct interface *ifp, /* Add to linked list. */ listnode_add (ifp->connected, ifc); + + ipv6_nd_suppress_ra_set (ifp, RA_ENABLE); } /* This address is configured from zebra. */ @@ -1765,6 +1767,20 @@ ipv6_address_install (struct vty *vty, struct interface *ifp, return CMD_SUCCESS; } +/* Return true if an ipv6 address is configured on ifp */ +int +ipv6_address_configured (struct interface *ifp) +{ + struct connected *connected; + struct listnode *node; + + for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, connected)) + if (CHECK_FLAG (connected->conf, ZEBRA_IFC_REAL) && (connected->address->family == AF_INET6)) + return 1; + + return 0; +} + static int ipv6_address_uninstall (struct vty *vty, struct interface *ifp, const char *addr_str, const char *peer_str, @@ -1814,6 +1830,10 @@ ipv6_address_uninstall (struct vty *vty, struct interface *ifp, return CMD_WARNING; } + /* Enable RA suppression if there are no IPv6 addresses on this interface */ + if (! ipv6_address_configured(ifp)) + ipv6_nd_suppress_ra_set (ifp, RA_SUPPRESS); + UNSET_FLAG (ifc->conf, ZEBRA_IFC_QUEUED); /* This information will be propagated to the zclients when the * kernel notification is received. */ diff --git a/zebra/interface.h b/zebra/interface.h index 650b62a458..6f253a467e 100644 --- a/zebra/interface.h +++ b/zebra/interface.h @@ -217,6 +217,7 @@ extern void if_refresh (struct interface *); extern void if_flags_update (struct interface *, uint64_t); extern int if_subnet_add (struct interface *, struct connected *); extern int if_subnet_delete (struct interface *, struct connected *); +extern int ipv6_address_configured (struct interface *ifp); #ifdef HAVE_PROC_NET_DEV extern void ifstat_update_proc (void); diff --git a/zebra/rtadv.c b/zebra/rtadv.c index 30b4d749bd..69bd566408 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -707,6 +707,46 @@ rtadv_prefix_reset (struct zebra_if *zif, struct rtadv_prefix *rp) return 0; } +void +ipv6_nd_suppress_ra_set (struct interface *ifp, ipv6_nd_suppress_ra_status status) +{ + struct zebra_if *zif; + struct zebra_vrf *zvrf; + + zif = ifp->info; + zvrf = vrf_info_lookup (ifp->vrf_id); + + if (status == RA_SUPPRESS) + { + /* RA is currently enabled */ + if (zif->rtadv.AdvSendAdvertisements) + { + zif->rtadv.AdvSendAdvertisements = 0; + zif->rtadv.AdvIntervalTimer = 0; + zvrf->rtadv.adv_if_count--; + + if_leave_all_router (zvrf->rtadv.sock, ifp); + + if (zvrf->rtadv.adv_if_count == 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_join_all_router (zvrf->rtadv.sock, ifp); + + if (zvrf->rtadv.adv_if_count == 1) + rtadv_event (zvrf, RTADV_START, zvrf->rtadv.sock); + } + } +} + DEFUN (ipv6_nd_suppress_ra, ipv6_nd_suppress_ra_cmd, "ipv6 nd suppress-ra", @@ -715,12 +755,8 @@ DEFUN (ipv6_nd_suppress_ra, "Suppress Router Advertisement\n") { struct interface *ifp; - struct zebra_if *zif; - struct zebra_vrf *zvrf; ifp = vty->index; - zif = ifp->info; - zvrf = vrf_info_lookup (ifp->vrf_id); if (if_is_loopback (ifp)) { @@ -728,18 +764,7 @@ DEFUN (ipv6_nd_suppress_ra, return CMD_WARNING; } - if (zif->rtadv.AdvSendAdvertisements) - { - zif->rtadv.AdvSendAdvertisements = 0; - zif->rtadv.AdvIntervalTimer = 0; - zvrf->rtadv.adv_if_count--; - - if_leave_all_router (zvrf->rtadv.sock, ifp); - - if (zvrf->rtadv.adv_if_count == 0) - rtadv_event (zvrf, RTADV_STOP, 0); - } - + ipv6_nd_suppress_ra_set (ifp, RA_SUPPRESS); return CMD_SUCCESS; } @@ -752,12 +777,8 @@ DEFUN (no_ipv6_nd_suppress_ra, "Suppress Router Advertisement\n") { struct interface *ifp; - struct zebra_if *zif; - struct zebra_vrf *zvrf; ifp = vty->index; - zif = ifp->info; - zvrf = vrf_info_lookup (ifp->vrf_id); if (if_is_loopback (ifp)) { @@ -765,18 +786,7 @@ DEFUN (no_ipv6_nd_suppress_ra, return CMD_WARNING; } - if (! zif->rtadv.AdvSendAdvertisements) - { - zif->rtadv.AdvSendAdvertisements = 1; - zif->rtadv.AdvIntervalTimer = 0; - zvrf->rtadv.adv_if_count++; - - if_join_all_router (zvrf->rtadv.sock, ifp); - - if (zvrf->rtadv.adv_if_count == 1) - rtadv_event (zvrf, RTADV_START, zvrf->rtadv.sock); - } - + ipv6_nd_suppress_ra_set (ifp, RA_ENABLE); return CMD_SUCCESS; } @@ -1760,10 +1770,17 @@ rtadv_config_write (struct vty *vty, struct interface *ifp) if (! if_is_loopback (ifp)) { - if (zif->rtadv.AdvSendAdvertisements) - vty_out (vty, " no ipv6 nd suppress-ra%s", VTY_NEWLINE); + if (ipv6_address_configured(ifp)) + { + if (! zif->rtadv.AdvSendAdvertisements) + vty_out (vty, " ipv6 nd suppress-ra%s", VTY_NEWLINE); + } + else + { + if (zif->rtadv.AdvSendAdvertisements) + vty_out (vty, " no ipv6 nd suppress-ra%s", VTY_NEWLINE); + } } - interval = zif->rtadv.MaxRtrAdvInterval; if (interval % 1000) diff --git a/zebra/rtadv.h b/zebra/rtadv.h index 160814b209..46b282aed6 100644 --- a/zebra/rtadv.h +++ b/zebra/rtadv.h @@ -100,8 +100,14 @@ extern const char *rtadv_pref_strs[]; #endif /* HAVE_RTADV */ +typedef enum { + RA_ENABLE = 0, + RA_SUPPRESS, +} ipv6_nd_suppress_ra_status; + extern void rtadv_init (struct zebra_vrf *); extern void rtadv_terminate (struct zebra_vrf *); extern void rtadv_cmd_init (void); +extern void ipv6_nd_suppress_ra_set (struct interface *ifp, ipv6_nd_suppress_ra_status status); #endif /* _ZEBRA_RTADV_H */ diff --git a/zebra/rtadv_null.c b/zebra/rtadv_null.c new file mode 100644 index 0000000000..d4678d5751 --- /dev/null +++ b/zebra/rtadv_null.c @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2015 Cumulus Networks, Inc. + * + * This file is part of Quagga. + * + * Quagga is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * Quagga is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Quagga; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include +#include +#include + +void ipv6_nd_suppress_ra_set (struct interface *ifp, ipv6_nd_suppress_ra_status status) +{ return; } -- 2.39.5