summaryrefslogtreecommitdiffstats
path: root/zebra
diff options
context:
space:
mode:
authorFeng Lu <lu.feng@6wind.com>2015-05-22 11:40:10 +0200
committerVipin Kumar <vipin@cumulusnetworks.com>2015-10-30 08:57:27 +0100
commitcd80d74fb275fe68247891d071075f450d4ec41c (patch)
treef9d14517c439e1971a11402ef64f832be828271e /zebra
parentzebra: add hooks upon enabling / disabling a VRF (diff)
downloadfrr-cd80d74fb275fe68247891d071075f450d4ec41c.tar.xz
frr-cd80d74fb275fe68247891d071075f450d4ec41c.zip
zebra: maintain RTADV per VRF
This moves the global variable "rtadv" into the "struct zebra_vrf", so that RTADV feature can work per VRF. * rtadv.c/rtadv.h: Add a proper parameter to the functions so that the entity of the "struct zebra_vrf" and interfaces can be obtained from the specified VRF. The old rtadv_init() is splitted into: - rtadv_cmd_init(): it installs the RTADV commands; is called from main(); - new rtadv_init(): it creates the socket; is called from zebra_vrf_enable(). rtadv_terminate() is added to stop the threads, close the socket and clear the counters. It is called from zebra_vrf_disable(). rtadv_make_socket() now calls vrf_socket() to create a socket in the VRF. * interface.h and rib.h: define the macro RTADV. * main.c: according changes, refer to rtadv.c. Signed-off-by: Feng Lu <lu.feng@6wind.com> Reviewed-by: Alain Ritoux <alain.ritoux@6wind.com> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Acked-by: Vincent JARDIN <vincent.jardin@6wind.com> Signed-off-by: David Lamparter <equinox@opensourcerouting.org> Conflicts: zebra/interface.h zebra/rib.h zebra/rtadv.c zebra/rtadv.h
Diffstat (limited to 'zebra')
-rw-r--r--zebra/interface.h2
-rw-r--r--zebra/main.c9
-rw-r--r--zebra/rib.h27
-rw-r--r--zebra/rtadv.c146
-rw-r--r--zebra/rtadv.h5
5 files changed, 121 insertions, 68 deletions
diff --git a/zebra/interface.h b/zebra/interface.h
index e8456ce59..ba76d3e84 100644
--- a/zebra/interface.h
+++ b/zebra/interface.h
@@ -38,11 +38,13 @@
#define IF_ZEBRA_SHUTDOWN_ON 1
/* Router advertisement feature. */
+#ifndef RTADV
#if (defined(LINUX_IPV6) && (defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1)) || defined(KAME)
#ifdef HAVE_RTADV
#define RTADV
#endif
#endif
+#endif
#ifdef RTADV
/* Router advertisement parameter. From RFC4861, RFC6275 and RFC4191. */
diff --git a/zebra/main.c b/zebra/main.c
index 22471d3d0..16a11edea 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -238,6 +238,9 @@ zebra_vrf_enable (vrf_id_t vrf_id, void **info)
assert (zvrf);
+#ifdef RTADV
+ rtadv_init (zvrf);
+#endif
return 0;
}
@@ -262,6 +265,10 @@ zebra_vrf_disable (vrf_id_t vrf_id, void **info)
if_down (ifp);
}
+#ifdef RTADV
+ rtadv_terminate (zvrf);
+#endif
+
list_delete_all_node (zvrf->rid_all_sorted_list);
list_delete_all_node (zvrf->rid_lo_sorted_list);
@@ -406,7 +413,7 @@ main (int argc, char **argv)
access_list_init ();
prefix_list_init ();
#ifdef RTADV
- rtadv_init ();
+ rtadv_cmd_init ();
#endif
#ifdef HAVE_IRDP
irdp_init();
diff --git a/zebra/rib.h b/zebra/rib.h
index 60a39d472..f18b311d4 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -287,6 +287,29 @@ struct static_ipv6
: ((tnexthop) = (nexthop)->next)) \
: (((recursing) = 0),((tnexthop) = (tnexthop)->next)))
+/* Router advertisement feature. */
+#ifndef RTADV
+#if (defined(LINUX_IPV6) && (defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1)) || defined(KAME)
+ #ifdef HAVE_RTADV
+ #define RTADV
+ #endif
+#endif
+#endif
+
+#if defined (HAVE_IPV6) && defined (RTADV)
+/* Structure which hold status of router advertisement. */
+struct rtadv
+{
+ int sock;
+
+ int adv_if_count;
+ int adv_msec_if_count;
+
+ struct thread *ra_read;
+ struct thread *ra_timer;
+};
+#endif /* RTADV && HAVE_IPV6 */
+
/* Routing table instance. */
struct zebra_vrf
{
@@ -325,6 +348,10 @@ struct zebra_vrf
struct list *rid_all_sorted_list;
struct list *rid_lo_sorted_list;
struct prefix rid_user_assigned;
+
+#if defined (HAVE_IPV6) && defined (RTADV)
+ struct rtadv rtadv;
+#endif /* RTADV && HAVE_IPV6 */
};
/*
diff --git a/zebra/rtadv.c b/zebra/rtadv.c
index 67f6ddb4e..d48f804f7 100644
--- a/zebra/rtadv.c
+++ b/zebra/rtadv.c
@@ -31,6 +31,7 @@
#include "linklist.h"
#include "command.h"
#include "privs.h"
+#include "vrf.h"
#include "zebra/interface.h"
#include "zebra/rtadv.h"
@@ -62,31 +63,11 @@ extern struct zebra_t zebrad;
enum rtadv_event {RTADV_START, RTADV_STOP, RTADV_TIMER,
RTADV_TIMER_MSEC, RTADV_READ};
-static void rtadv_event (enum rtadv_event, int);
+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 *);
-/* Structure which hold status of router advertisement. */
-struct rtadv
-{
- int sock;
-
- int adv_if_count;
- int adv_msec_if_count;
-
- struct thread *ra_read;
- struct thread *ra_timer;
-};
-
-struct rtadv *rtadv = NULL;
-
-static struct rtadv *
-rtadv_new (void)
-{
- return XCALLOC (MTYPE_TMP, sizeof (struct rtadv));
-}
-
static int
rtadv_recv_packet (int sock, u_char *buf, int buflen,
struct sockaddr_in6 *from, unsigned int *ifindex,
@@ -389,24 +370,25 @@ rtadv_send_packet (int sock, struct interface *ifp)
static int
rtadv_timer (struct thread *thread)
{
+ struct zebra_vrf *zvrf = THREAD_ARG (thread);
struct listnode *node, *nnode;
struct interface *ifp;
struct zebra_if *zif;
int period;
- rtadv->ra_timer = NULL;
- if (rtadv->adv_msec_if_count == 0)
+ zvrf->rtadv.ra_timer = NULL;
+ if (zvrf->rtadv.adv_msec_if_count == 0)
{
period = 1000; /* 1 s */
- rtadv_event (RTADV_TIMER, 1 /* 1 s */);
+ rtadv_event (zvrf, RTADV_TIMER, 1 /* 1 s */);
}
else
{
period = 10; /* 10 ms */
- rtadv_event (RTADV_TIMER_MSEC, 10 /* 10 ms */);
+ rtadv_event (zvrf, RTADV_TIMER_MSEC, 10 /* 10 ms */);
}
- for (ALL_LIST_ELEMENTS (iflist, node, nnode, ifp))
+ for (ALL_LIST_ELEMENTS (vrf_iflist (zvrf->vrf_id), node, nnode, ifp))
{
if (if_is_loopback (ifp) || ! if_is_operative (ifp))
continue;
@@ -421,7 +403,7 @@ rtadv_timer (struct thread *thread)
/* FIXME: using MaxRtrAdvInterval each time isn't what section
6.2.4 of RFC4861 tells to do. */
zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
- rtadv_send_packet (rtadv->sock, ifp);
+ rtadv_send_packet (zvrf->rtadv.sock, ifp);
}
}
}
@@ -431,9 +413,11 @@ rtadv_timer (struct thread *thread)
static void
rtadv_process_solicit (struct interface *ifp)
{
- zlog_info ("Router solicitation received on %s", ifp->name);
+ struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id);
- rtadv_send_packet (rtadv->sock, ifp);
+ zlog_info ("Router solicitation received on %s vrf %u", ifp->name, zvrf->vrf_id);
+
+ rtadv_send_packet (zvrf->rtadv.sock, ifp);
}
static void
@@ -513,17 +497,17 @@ rtadv_process_advert (u_char *msg, unsigned int len, struct interface *ifp,
static void
rtadv_process_packet (u_char *buf, unsigned int len, unsigned int ifindex, int hoplimit,
- struct sockaddr_in6 *from)
+ struct sockaddr_in6 *from, vrf_id_t vrf_id)
{
struct icmp6_hdr *icmph;
struct interface *ifp;
struct zebra_if *zif;
/* Interface search. */
- ifp = if_lookup_by_index (ifindex);
+ ifp = if_lookup_by_index_vrf (ifindex, vrf_id);
if (ifp == NULL)
{
- zlog_warn ("Unknown interface index: %d", ifindex);
+ zlog_warn ("Unknown interface index: %d, vrf %u", ifindex, vrf_id);
return;
}
@@ -578,12 +562,13 @@ rtadv_read (struct thread *thread)
struct sockaddr_in6 from;
unsigned int ifindex = 0;
int hoplimit = -1;
+ struct zebra_vrf *zvrf = THREAD_ARG (thread);
sock = THREAD_FD (thread);
- rtadv->ra_read = NULL;
+ zvrf->rtadv.ra_read = NULL;
/* Register myself. */
- rtadv_event (RTADV_READ, sock);
+ rtadv_event (zvrf, RTADV_READ, sock);
len = rtadv_recv_packet (sock, buf, BUFSIZ, &from, &ifindex, &hoplimit);
@@ -593,13 +578,13 @@ rtadv_read (struct thread *thread)
return len;
}
- rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit, &from);
+ rtadv_process_packet (buf, (unsigned)len, ifindex, hoplimit, &from, zvrf->vrf_id);
return 0;
}
static int
-rtadv_make_socket (void)
+rtadv_make_socket (vrf_id_t vrf_id)
{
int sock;
int ret;
@@ -609,7 +594,7 @@ rtadv_make_socket (void)
zlog_err ("rtadv_make_socket: could not raise privs, %s",
safe_strerror (errno) );
- sock = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+ sock = vrf_socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6, vrf_id);
if ( zserv_privs.change (ZPRIVS_LOWER) )
zlog_err ("rtadv_make_socket: could not lower privs, %s",
@@ -731,9 +716,11 @@ DEFUN (ipv6_nd_suppress_ra,
{
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))
{
@@ -745,12 +732,12 @@ DEFUN (ipv6_nd_suppress_ra,
{
zif->rtadv.AdvSendAdvertisements = 0;
zif->rtadv.AdvIntervalTimer = 0;
- rtadv->adv_if_count--;
+ zvrf->rtadv.adv_if_count--;
- if_leave_all_router (rtadv->sock, ifp);
+ if_leave_all_router (zvrf->rtadv.sock, ifp);
- if (rtadv->adv_if_count == 0)
- rtadv_event (RTADV_STOP, 0);
+ if (zvrf->rtadv.adv_if_count == 0)
+ rtadv_event (zvrf, RTADV_STOP, 0);
}
return CMD_SUCCESS;
@@ -766,9 +753,11 @@ DEFUN (no_ipv6_nd_suppress_ra,
{
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))
{
@@ -780,12 +769,12 @@ DEFUN (no_ipv6_nd_suppress_ra,
{
zif->rtadv.AdvSendAdvertisements = 1;
zif->rtadv.AdvIntervalTimer = 0;
- rtadv->adv_if_count++;
+ zvrf->rtadv.adv_if_count++;
- if_join_all_router (rtadv->sock, ifp);
+ if_join_all_router (zvrf->rtadv.sock, ifp);
- if (rtadv->adv_if_count == 1)
- rtadv_event (RTADV_START, rtadv->sock);
+ if (zvrf->rtadv.adv_if_count == 1)
+ rtadv_event (zvrf, RTADV_START, zvrf->rtadv.sock);
}
return CMD_SUCCESS;
@@ -802,6 +791,7 @@ DEFUN (ipv6_nd_ra_interval_msec,
unsigned interval;
struct interface *ifp = (struct interface *) vty->index;
struct zebra_if *zif = ifp->info;
+ struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id);
VTY_GET_INTEGER_RANGE ("router advertisement interval", interval, argv[0], 70, 1800000);
if ((zif->rtadv.AdvDefaultLifetime != -1 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime * 1000))
@@ -811,10 +801,10 @@ DEFUN (ipv6_nd_ra_interval_msec,
}
if (zif->rtadv.MaxRtrAdvInterval % 1000)
- rtadv->adv_msec_if_count--;
+ zvrf->rtadv.adv_msec_if_count--;
if (interval % 1000)
- rtadv->adv_msec_if_count++;
+ zvrf->rtadv.adv_msec_if_count++;
zif->rtadv.MaxRtrAdvInterval = interval;
zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
@@ -834,6 +824,7 @@ DEFUN (ipv6_nd_ra_interval,
unsigned interval;
struct interface *ifp = (struct interface *) vty->index;
struct zebra_if *zif = ifp->info;
+ struct zebra_vrf *zvrf = vrf_info_lookup (ifp->vrf_id);
VTY_GET_INTEGER_RANGE ("router advertisement interval", interval, argv[0], 1, 1800);
if ((zif->rtadv.AdvDefaultLifetime != -1 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime))
@@ -843,7 +834,7 @@ DEFUN (ipv6_nd_ra_interval,
}
if (zif->rtadv.MaxRtrAdvInterval % 1000)
- rtadv->adv_msec_if_count--;
+ zvrf->rtadv.adv_msec_if_count--;
/* convert to milliseconds */
interval = interval * 1000;
@@ -865,12 +856,14 @@ DEFUN (no_ipv6_nd_ra_interval,
{
struct interface *ifp;
struct zebra_if *zif;
+ struct zebra_vrf *zvrf;
ifp = (struct interface *) vty->index;
zif = ifp->info;
+ zvrf = vrf_info_lookup (ifp->vrf_id);
if (zif->rtadv.MaxRtrAdvInterval % 1000)
- rtadv->adv_msec_if_count--;
+ zvrf->rtadv.adv_msec_if_count--;
zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
@@ -1609,9 +1602,6 @@ rtadv_config_write (struct vty *vty, struct interface *ifp)
u_char buf[INET6_ADDRSTRLEN];
int interval;
- if (! rtadv)
- return;
-
zif = ifp->info;
if (! if_is_loopback (ifp))
@@ -1696,16 +1686,18 @@ rtadv_config_write (struct vty *vty, struct interface *ifp)
static void
-rtadv_event (enum rtadv_event event, int val)
+rtadv_event (struct zebra_vrf *zvrf, enum rtadv_event event, int val)
{
+ struct rtadv *rtadv = &zvrf->rtadv;
+
switch (event)
{
case RTADV_START:
if (! rtadv->ra_read)
- rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
+ rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, zvrf, val);
if (! rtadv->ra_timer)
rtadv->ra_timer = thread_add_event (zebrad.master, rtadv_timer,
- NULL, 0);
+ zvrf, 0);
break;
case RTADV_STOP:
if (rtadv->ra_timer)
@@ -1721,17 +1713,17 @@ rtadv_event (enum rtadv_event event, int val)
break;
case RTADV_TIMER:
if (! rtadv->ra_timer)
- rtadv->ra_timer = thread_add_timer (zebrad.master, rtadv_timer, NULL,
+ rtadv->ra_timer = thread_add_timer (zebrad.master, rtadv_timer, zvrf,
val);
break;
case RTADV_TIMER_MSEC:
if (! rtadv->ra_timer)
rtadv->ra_timer = thread_add_timer_msec (zebrad.master, rtadv_timer,
- NULL, val);
+ zvrf, val);
break;
case RTADV_READ:
if (! rtadv->ra_read)
- rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, NULL, val);
+ rtadv->ra_read = thread_add_read (zebrad.master, rtadv_read, zvrf, val);
break;
default:
break;
@@ -1740,17 +1732,29 @@ rtadv_event (enum rtadv_event event, int val)
}
void
-rtadv_init (void)
+rtadv_init (struct zebra_vrf *zvrf)
{
- int sock;
+ zvrf->rtadv.sock = rtadv_make_socket (zvrf->vrf_id);
+}
- sock = rtadv_make_socket ();
- if (sock < 0)
- return;
+void
+rtadv_terminate (struct zebra_vrf *zvrf)
+{
+ rtadv_event (zvrf, RTADV_STOP, 0);
+
+ if (zvrf->rtadv.sock >= 0)
+ {
+ close (zvrf->rtadv.sock);
+ zvrf->rtadv.sock = -1;
+ }
- rtadv = rtadv_new ();
- rtadv->sock = sock;
+ zvrf->rtadv.adv_if_count = 0;
+ zvrf->rtadv.adv_msec_if_count = 0;
+}
+void
+rtadv_cmd_init (void)
+{
install_element (INTERFACE_NODE, &ipv6_nd_suppress_ra_cmd);
install_element (INTERFACE_NODE, &no_ipv6_nd_suppress_ra_cmd);
install_element (INTERFACE_NODE, &ipv6_nd_ra_interval_cmd);
@@ -1845,7 +1849,17 @@ if_leave_all_router (int sock, struct interface *ifp)
#else
void
-rtadv_init (void)
+rtadv_init (struct zebra_vrf *zvrf)
+{
+ /* Empty.*/;
+}
+void
+rtadv_terminate (struct zebra_vrf *zvrf)
+{
+ /* Empty.*/;
+}
+void
+rtadv_cmd_init (void)
{
/* Empty.*/;
}
diff --git a/zebra/rtadv.h b/zebra/rtadv.h
index 8cb933e0b..76f98cf2c 100644
--- a/zebra/rtadv.h
+++ b/zebra/rtadv.h
@@ -59,7 +59,6 @@ struct rtadv_prefix
};
extern void rtadv_config_write (struct vty *, struct interface *);
-extern void rtadv_init (void);
/* RFC4584 Extension to Sockets API for Mobile IPv6 */
@@ -101,4 +100,8 @@ extern const char *rtadv_pref_strs[];
#endif /* RTADV */
+extern void rtadv_init (struct zebra_vrf *);
+extern void rtadv_terminate (struct zebra_vrf *);
+extern void rtadv_cmd_init (void);
+
#endif /* _ZEBRA_RTADV_H */