diff options
author | Feng Lu <lu.feng@6wind.com> | 2015-05-22 11:40:10 +0200 |
---|---|---|
committer | Vipin Kumar <vipin@cumulusnetworks.com> | 2015-10-30 08:57:27 +0100 |
commit | cd80d74fb275fe68247891d071075f450d4ec41c (patch) | |
tree | f9d14517c439e1971a11402ef64f832be828271e /zebra | |
parent | zebra: add hooks upon enabling / disabling a VRF (diff) | |
download | frr-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.h | 2 | ||||
-rw-r--r-- | zebra/main.c | 9 | ||||
-rw-r--r-- | zebra/rib.h | 27 | ||||
-rw-r--r-- | zebra/rtadv.c | 146 | ||||
-rw-r--r-- | zebra/rtadv.h | 5 |
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 */ |