zebra: move rtadv service from zrouter to zvrf

when network namespace is used as vrf backend, there is need to have
separate contexts for rtadv contexts.
route advertisements have to look for appropriate interface based on
zvrf context.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This commit is contained in:
Philippe Guibert 2019-03-27 10:25:13 +01:00
parent 230dec1398
commit df9c8c5742
6 changed files with 77 additions and 71 deletions

View File

@ -42,7 +42,6 @@
#include "zebra/debug.h"
#include "zebra/rib.h"
#include "zebra/zapi_msg.h"
#include "zebra/zebra_ns.h"
#include "zebra/zebra_vrf.h"
#include "zebra/zebra_errors.h"
#include "zebra/zebra_router.h"
@ -81,18 +80,18 @@ enum rtadv_event {
RTADV_READ
};
static void rtadv_event(struct zebra_ns *, 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 *);
static int rtadv_increment_received(struct zebra_ns *zns, ifindex_t *ifindex)
static int rtadv_increment_received(struct zebra_vrf *zvrf, ifindex_t *ifindex)
{
int ret = -1;
struct interface *iface;
struct zebra_if *zif;
iface = if_lookup_by_index_per_ns(zns, *ifindex);
iface = if_lookup_by_index(*ifindex, zvrf->vrf->vrf_id);
if (iface && iface->info) {
zif = iface->info;
zif->ra_rcvd++;
@ -101,7 +100,7 @@ static int rtadv_increment_received(struct zebra_ns *zns, ifindex_t *ifindex)
return ret;
}
static int rtadv_recv_packet(struct zebra_ns *zns, int sock, uint8_t *buf,
static int rtadv_recv_packet(struct zebra_vrf *zvrf, int sock, uint8_t *buf,
int buflen, struct sockaddr_in6 *from,
ifindex_t *ifindex, int *hoplimit)
{
@ -149,7 +148,7 @@ static int rtadv_recv_packet(struct zebra_ns *zns, int sock, uint8_t *buf,
}
}
rtadv_increment_received(zns, ifindex);
rtadv_increment_received(zvrf, ifindex);
return ret;
}
@ -461,19 +460,19 @@ no_more_opts:
static int rtadv_timer(struct thread *thread)
{
struct zebra_ns *zns = THREAD_ARG(thread);
struct zebra_vrf *zvrf = THREAD_ARG(thread);
struct vrf *vrf;
struct interface *ifp;
struct zebra_if *zif;
int period;
zrouter.rtadv.ra_timer = NULL;
if (zrouter.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(zns, RTADV_TIMER, 1 /* 1 s */);
rtadv_event(zvrf, RTADV_TIMER, 1 /* 1 s */);
} else {
period = 10; /* 10 ms */
rtadv_event(zns, RTADV_TIMER_MSEC, 10 /* 10 ms */);
rtadv_event(zvrf, RTADV_TIMER_MSEC, 10 /* 10 ms */);
}
RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id)
@ -500,7 +499,7 @@ static int rtadv_timer(struct thread *thread)
"Fast RA Rexmit on interface %s",
ifp->name);
rtadv_send_packet(zrouter.rtadv.sock,
rtadv_send_packet(zvrf->rtadv.sock,
ifp);
} else {
zif->rtadv.AdvIntervalTimer -= period;
@ -514,7 +513,7 @@ static int rtadv_timer(struct thread *thread)
zif->rtadv
.MaxRtrAdvInterval;
rtadv_send_packet(
zrouter.rtadv.sock,
zvrf->rtadv.sock,
ifp);
}
}
@ -527,10 +526,9 @@ static int rtadv_timer(struct thread *thread)
static void rtadv_process_solicit(struct interface *ifp)
{
struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
struct zebra_ns *zns = zvrf->zns;
assert(zns);
rtadv_send_packet(zrouter.rtadv.sock, ifp);
assert(zvrf);
rtadv_send_packet(zvrf->rtadv.sock, ifp);
}
/*
@ -652,7 +650,7 @@ static void rtadv_process_advert(uint8_t *msg, unsigned int len,
static void rtadv_process_packet(uint8_t *buf, unsigned int len,
ifindex_t ifindex, int hoplimit,
struct sockaddr_in6 *from,
struct zebra_ns *zns)
struct zebra_vrf *zvrf)
{
struct icmp6_hdr *icmph;
struct interface *ifp;
@ -662,7 +660,7 @@ static void rtadv_process_packet(uint8_t *buf, unsigned int len,
inet_ntop(AF_INET6, &from->sin6_addr, addr_str, INET6_ADDRSTRLEN);
/* Interface search. */
ifp = if_lookup_by_index_per_ns(zns, ifindex);
ifp = if_lookup_by_index(ifindex, zvrf->vrf->vrf_id);
if (ifp == NULL) {
flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE,
"RA/RS received on unknown IF %u from %s", ifindex,
@ -724,15 +722,15 @@ static int rtadv_read(struct thread *thread)
struct sockaddr_in6 from;
ifindex_t ifindex = 0;
int hoplimit = -1;
struct zebra_ns *zns = THREAD_ARG(thread);
struct zebra_vrf *zvrf = THREAD_ARG(thread);
sock = THREAD_FD(thread);
zrouter.rtadv.ra_read = NULL;
zvrf->rtadv.ra_read = NULL;
/* Register myself. */
rtadv_event(zns, RTADV_READ, sock);
rtadv_event(zvrf, RTADV_READ, sock);
len = rtadv_recv_packet(zns, sock, buf, sizeof(buf), &from, &ifindex,
len = rtadv_recv_packet(zvrf, sock, buf, sizeof(buf), &from, &ifindex,
&hoplimit);
if (len < 0) {
@ -742,7 +740,7 @@ static int rtadv_read(struct thread *thread)
return len;
}
rtadv_process_packet(buf, (unsigned)len, ifindex, hoplimit, &from, zns);
rtadv_process_packet(buf, (unsigned)len, ifindex, hoplimit, &from, zvrf);
return 0;
}
@ -875,29 +873,27 @@ static void ipv6_nd_suppress_ra_set(struct interface *ifp,
{
struct zebra_if *zif;
struct zebra_vrf *zvrf;
struct zebra_ns *zns;
zif = ifp->info;
zvrf = vrf_info_lookup(ifp->vrf_id);
zns = zvrf->zns;
if (status == RA_SUPPRESS) {
/* RA is currently enabled */
if (zif->rtadv.AdvSendAdvertisements) {
zif->rtadv.AdvSendAdvertisements = 0;
zif->rtadv.AdvIntervalTimer = 0;
zrouter.rtadv.adv_if_count--;
zvrf->rtadv.adv_if_count--;
if_leave_all_router(zrouter.rtadv.sock, ifp);
if_leave_all_router(zvrf->rtadv.sock, ifp);
if (zrouter.rtadv.adv_if_count == 0)
rtadv_event(zns, RTADV_STOP, 0);
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;
zrouter.rtadv.adv_if_count++;
zvrf->rtadv.adv_if_count++;
if (zif->rtadv.MaxRtrAdvInterval >= 1000) {
/* Enable Fast RA only when RA interval is in
@ -907,11 +903,11 @@ static void ipv6_nd_suppress_ra_set(struct interface *ifp,
RTADV_NUM_FAST_REXMITS;
}
if_join_all_router(zrouter.rtadv.sock, ifp);
if_join_all_router(zvrf->rtadv.sock, ifp);
if (zrouter.rtadv.adv_if_count == 1)
rtadv_event(zns, RTADV_START,
zrouter.rtadv.sock);
if (zvrf->rtadv.adv_if_count == 1)
rtadv_event(zvrf, RTADV_START,
zvrf->rtadv.sock);
}
}
}
@ -944,7 +940,7 @@ static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int enable)
zebra_route_string(client->proto), ra_interval);
/* Locate interface and check VRF match. */
ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), ifindex);
ifp = if_lookup_by_index(ifindex, zvrf->vrf->vrf_id);
if (!ifp) {
flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE,
"%u: IF %u RA %s client %s - interface unknown",
@ -1051,6 +1047,9 @@ DEFUN (ipv6_nd_ra_interval_msec,
VTY_DECLVAR_CONTEXT(interface, ifp);
unsigned interval;
struct zebra_if *zif = ifp->info;
struct zebra_vrf *zvrf;
zvrf = vrf_info_lookup(ifp->vrf_id);
interval = strtoul(argv[idx_number]->arg, NULL, 10);
if ((zif->rtadv.AdvDefaultLifetime != -1
@ -1061,10 +1060,10 @@ DEFUN (ipv6_nd_ra_interval_msec,
}
if (zif->rtadv.MaxRtrAdvInterval % 1000)
zrouter.rtadv.adv_msec_if_count--;
zvrf->rtadv.adv_msec_if_count--;
if (interval % 1000)
zrouter.rtadv.adv_msec_if_count++;
zvrf->rtadv.adv_msec_if_count++;
SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
zif->rtadv.MaxRtrAdvInterval = interval;
@ -1086,6 +1085,9 @@ DEFUN (ipv6_nd_ra_interval,
VTY_DECLVAR_CONTEXT(interface, ifp);
unsigned interval;
struct zebra_if *zif = ifp->info;
struct zebra_vrf *zvrf;
zvrf = vrf_info_lookup(ifp->vrf_id);
interval = strtoul(argv[idx_number]->arg, NULL, 10);
if ((zif->rtadv.AdvDefaultLifetime != -1
@ -1096,7 +1098,7 @@ DEFUN (ipv6_nd_ra_interval,
}
if (zif->rtadv.MaxRtrAdvInterval % 1000)
zrouter.rtadv.adv_msec_if_count--;
zvrf->rtadv.adv_msec_if_count--;
/* convert to milliseconds */
interval = interval * 1000;
@ -1122,9 +1124,12 @@ DEFUN (no_ipv6_nd_ra_interval,
{
VTY_DECLVAR_CONTEXT(interface, ifp);
struct zebra_if *zif = ifp->info;
struct zebra_vrf *zvrf = NULL;
zvrf = vrf_info_lookup(ifp->vrf_id);
if (zif->rtadv.MaxRtrAdvInterval % 1000)
zrouter.rtadv.adv_msec_if_count--;
zvrf->rtadv.adv_msec_if_count--;
UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
@ -2094,15 +2099,15 @@ static int rtadv_config_write(struct vty *vty, struct interface *ifp)
}
static void rtadv_event(struct zebra_ns *zns, enum rtadv_event event, int val)
static void rtadv_event(struct zebra_vrf *zvrf, enum rtadv_event event, int val)
{
struct rtadv *rtadv = &zrouter.rtadv;
struct rtadv *rtadv = &zvrf->rtadv;
switch (event) {
case RTADV_START:
thread_add_read(zrouter.master, rtadv_read, zns, val,
thread_add_read(zrouter.master, rtadv_read, zvrf, val,
&rtadv->ra_read);
thread_add_event(zrouter.master, rtadv_timer, zns, 0,
thread_add_event(zrouter.master, rtadv_timer, zvrf, 0,
&rtadv->ra_timer);
break;
case RTADV_STOP:
@ -2116,15 +2121,15 @@ static void rtadv_event(struct zebra_ns *zns, enum rtadv_event event, int val)
}
break;
case RTADV_TIMER:
thread_add_timer(zrouter.master, rtadv_timer, zns, val,
thread_add_timer(zrouter.master, rtadv_timer, zvrf, val,
&rtadv->ra_timer);
break;
case RTADV_TIMER_MSEC:
thread_add_timer_msec(zrouter.master, rtadv_timer, zns, val,
thread_add_timer_msec(zrouter.master, rtadv_timer, zvrf, val,
&rtadv->ra_timer);
break;
case RTADV_READ:
thread_add_read(zrouter.master, rtadv_read, zns, val,
thread_add_read(zrouter.master, rtadv_read, zvrf, val,
&rtadv->ra_read);
break;
default:
@ -2133,21 +2138,21 @@ static void rtadv_event(struct zebra_ns *zns, enum rtadv_event event, int val)
return;
}
void rtadv_init(struct zebra_ns *zns)
void rtadv_init(struct zebra_vrf *zvrf)
{
zrouter.rtadv.sock = rtadv_make_socket(zns->ns_id);
zvrf->rtadv.sock = rtadv_make_socket(zvrf->zns->ns_id);
}
void rtadv_terminate(struct zebra_ns *zns)
void rtadv_terminate(struct zebra_vrf *zvrf)
{
rtadv_event(zns, RTADV_STOP, 0);
if (zrouter.rtadv.sock >= 0) {
close(zrouter.rtadv.sock);
zrouter.rtadv.sock = -1;
rtadv_event(zvrf, RTADV_STOP, 0);
if (zvrf->rtadv.sock >= 0) {
close(zvrf->rtadv.sock);
zvrf->rtadv.sock = -1;
}
zrouter.rtadv.adv_if_count = 0;
zrouter.rtadv.adv_msec_if_count = 0;
zvrf->rtadv.adv_if_count = 0;
zvrf->rtadv.adv_msec_if_count = 0;
}
void rtadv_cmd_init(void)
@ -2243,11 +2248,11 @@ static int if_leave_all_router(int sock, struct interface *ifp)
}
#else
void rtadv_init(struct zebra_ns *zns)
void rtadv_init(struct zebra_vrf *zvrf)
{
/* Empty.*/;
}
void rtadv_terminate(struct zebra_ns *zns)
void rtadv_terminate(struct zebra_vrf *zvrf)
{
/* Empty.*/;
}

View File

@ -135,8 +135,8 @@ typedef enum {
RA_SUPPRESS,
} ipv6_nd_suppress_ra_status;
extern void rtadv_init(struct zebra_ns *);
extern void rtadv_terminate(struct zebra_ns *);
extern void rtadv_init(struct zebra_vrf *zvrf);
extern void rtadv_terminate(struct zebra_vrf *zvrf);
extern void rtadv_cmd_init(void);
extern void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS);
extern void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS);

View File

@ -27,7 +27,6 @@
#include "lib/prefix.h"
#include "lib/memory.h"
#include "rtadv.h"
#include "zebra_ns.h"
#include "zebra_vrf.h"
#include "zebra_memory.h"
@ -122,10 +121,6 @@ int zebra_ns_enable(ns_id_t ns_id, void **info)
zns->ns_id = ns_id;
#if defined(HAVE_RTADV)
rtadv_init(zns);
#endif
kernel_init(zns);
interface_list(zns);
route_read(zns);
@ -142,9 +137,6 @@ int zebra_ns_enable(ns_id_t ns_id, void **info)
static int zebra_ns_disable_internal(struct zebra_ns *zns, bool complete)
{
route_table_finish(zns->if_table);
#if defined(HAVE_RTADV)
rtadv_terminate(zns);
#endif
kernel_terminate(zns, complete);

View File

@ -93,10 +93,6 @@ struct zebra_router {
struct hash *iptable_hash;
#if defined(HAVE_RTADV)
struct rtadv rtadv;
#endif /* HAVE_RTADV */
/* A sequence number used for tracking routes */
_Atomic uint32_t sequence_num;

View File

@ -29,6 +29,7 @@
#include "vty.h"
#include "zebra/zebra_router.h"
#include "zebra/rtadv.h"
#include "zebra/debug.h"
#include "zebra/zapi_msg.h"
#include "zebra/rib.h"
@ -119,6 +120,10 @@ static int zebra_vrf_enable(struct vrf *vrf)
zvrf->zns = zebra_ns_lookup((ns_id_t)vrf->vrf_id);
else
zvrf->zns = zebra_ns_lookup(NS_DEFAULT);
#if defined(HAVE_RTADV)
rtadv_init(zvrf);
#endif
/* Inform clients that the VRF is now active. This is an
* add for the clients.
*/
@ -161,6 +166,10 @@ static int zebra_vrf_disable(struct vrf *vrf)
/* Stop any VxLAN-EVPN processing. */
zebra_vxlan_vrf_disable(zvrf);
#if defined(HAVE_RTADV)
rtadv_terminate(zvrf);
#endif
/* Inform clients that the VRF is now inactive. This is a
* delete for the clients.
*/

View File

@ -169,6 +169,10 @@ struct zebra_vrf {
uint64_t lsp_removals_queued;
uint64_t lsp_installs;
uint64_t lsp_removals;
#if defined(HAVE_RTADV)
struct rtadv rtadv;
#endif /* HAVE_RTADV */
};
#define PROTO_RM_NAME(zvrf, afi, rtype) zvrf->proto_rm[afi][rtype].name
#define NHT_RM_NAME(zvrf, afi, rtype) zvrf->nht_rm[afi][rtype].name