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 \
#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 */
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
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))
/* Add to linked list. */
listnode_add (ifp->connected, ifc);
+
+ ipv6_nd_suppress_ra_set (ifp, RA_ENABLE);
}
/* This address is configured from zebra. */
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,
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. */
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);
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",
"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))
{
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;
}
"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))
{
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;
}
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)
#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 */
--- /dev/null
+/*
+ * 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 <zebra.h>
+#include <lib/prefix.h>
+#include <rtadv.h>
+
+void ipv6_nd_suppress_ra_set (struct interface *ifp, ipv6_nd_suppress_ra_status status)
+{ return; }