Merge pull request #4027 from pguibert6WIND/fix_interface_rtadv

Fix interface rtadv
This commit is contained in:
David Lamparter 2019-05-14 15:53:04 +02:00 committed by GitHub
commit 366760c459
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 96 additions and 72 deletions

View File

@ -42,7 +42,6 @@
#include "zebra/debug.h" #include "zebra/debug.h"
#include "zebra/rib.h" #include "zebra/rib.h"
#include "zebra/zapi_msg.h" #include "zebra/zapi_msg.h"
#include "zebra/zebra_ns.h"
#include "zebra/zebra_vrf.h" #include "zebra/zebra_vrf.h"
#include "zebra/zebra_errors.h" #include "zebra/zebra_errors.h"
#include "zebra/zebra_router.h" #include "zebra/zebra_router.h"
@ -81,18 +80,25 @@ enum rtadv_event {
RTADV_READ 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_join_all_router(int, struct interface *);
static int if_leave_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_get_socket(struct zebra_vrf *zvrf)
{
if (zvrf->rtadv.sock >= 0)
return zvrf->rtadv.sock;
return zrouter.rtadv_sock;
}
static int rtadv_increment_received(struct zebra_vrf *zvrf, ifindex_t *ifindex)
{ {
int ret = -1; int ret = -1;
struct interface *iface; struct interface *iface;
struct zebra_if *zif; 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) { if (iface && iface->info) {
zif = iface->info; zif = iface->info;
zif->ra_rcvd++; zif->ra_rcvd++;
@ -101,7 +107,7 @@ static int rtadv_increment_received(struct zebra_ns *zns, ifindex_t *ifindex)
return ret; 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, int buflen, struct sockaddr_in6 *from,
ifindex_t *ifindex, int *hoplimit) ifindex_t *ifindex, int *hoplimit)
{ {
@ -149,7 +155,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; return ret;
} }
@ -461,19 +467,19 @@ no_more_opts:
static int rtadv_timer(struct thread *thread) 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 vrf *vrf;
struct interface *ifp; struct interface *ifp;
struct zebra_if *zif; struct zebra_if *zif;
int period; int period;
zrouter.rtadv.ra_timer = NULL; zvrf->rtadv.ra_timer = NULL;
if (zrouter.rtadv.adv_msec_if_count == 0) { if (zvrf->rtadv.adv_msec_if_count == 0) {
period = 1000; /* 1 s */ period = 1000; /* 1 s */
rtadv_event(zns, RTADV_TIMER, 1 /* 1 s */); rtadv_event(zvrf, RTADV_TIMER, 1 /* 1 s */);
} else { } else {
period = 10; /* 10 ms */ 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) RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id)
@ -500,7 +506,7 @@ static int rtadv_timer(struct thread *thread)
"Fast RA Rexmit on interface %s", "Fast RA Rexmit on interface %s",
ifp->name); ifp->name);
rtadv_send_packet(zrouter.rtadv.sock, rtadv_send_packet(rtadv_get_socket(zvrf),
ifp); ifp);
} else { } else {
zif->rtadv.AdvIntervalTimer -= period; zif->rtadv.AdvIntervalTimer -= period;
@ -514,8 +520,8 @@ static int rtadv_timer(struct thread *thread)
zif->rtadv zif->rtadv
.MaxRtrAdvInterval; .MaxRtrAdvInterval;
rtadv_send_packet( rtadv_send_packet(
zrouter.rtadv.sock, rtadv_get_socket(zvrf),
ifp); ifp);
} }
} }
} }
@ -527,10 +533,9 @@ static int rtadv_timer(struct thread *thread)
static void rtadv_process_solicit(struct interface *ifp) static void rtadv_process_solicit(struct interface *ifp)
{ {
struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id); struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
struct zebra_ns *zns = zvrf->zns;
assert(zns); assert(zvrf);
rtadv_send_packet(zrouter.rtadv.sock, ifp); rtadv_send_packet(rtadv_get_socket(zvrf), ifp);
} }
/* /*
@ -652,7 +657,7 @@ static void rtadv_process_advert(uint8_t *msg, unsigned int len,
static void rtadv_process_packet(uint8_t *buf, unsigned int len, static void rtadv_process_packet(uint8_t *buf, unsigned int len,
ifindex_t ifindex, int hoplimit, ifindex_t ifindex, int hoplimit,
struct sockaddr_in6 *from, struct sockaddr_in6 *from,
struct zebra_ns *zns) struct zebra_vrf *zvrf)
{ {
struct icmp6_hdr *icmph; struct icmp6_hdr *icmph;
struct interface *ifp; struct interface *ifp;
@ -662,7 +667,7 @@ static void rtadv_process_packet(uint8_t *buf, unsigned int len,
inet_ntop(AF_INET6, &from->sin6_addr, addr_str, INET6_ADDRSTRLEN); inet_ntop(AF_INET6, &from->sin6_addr, addr_str, INET6_ADDRSTRLEN);
/* Interface search. */ /* Interface search. */
ifp = if_lookup_by_index_per_ns(zns, ifindex); ifp = if_lookup_by_index(ifindex, zvrf->vrf->vrf_id);
if (ifp == NULL) { if (ifp == NULL) {
flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE, flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE,
"RA/RS received on unknown IF %u from %s", ifindex, "RA/RS received on unknown IF %u from %s", ifindex,
@ -724,15 +729,15 @@ static int rtadv_read(struct thread *thread)
struct sockaddr_in6 from; struct sockaddr_in6 from;
ifindex_t ifindex = 0; ifindex_t ifindex = 0;
int hoplimit = -1; int hoplimit = -1;
struct zebra_ns *zns = THREAD_ARG(thread); struct zebra_vrf *zvrf = THREAD_ARG(thread);
sock = THREAD_FD(thread); sock = THREAD_FD(thread);
zrouter.rtadv.ra_read = NULL; zvrf->rtadv.ra_read = NULL;
/* Register myself. */ /* 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); &hoplimit);
if (len < 0) { if (len < 0) {
@ -742,7 +747,7 @@ static int rtadv_read(struct thread *thread)
return len; return len;
} }
rtadv_process_packet(buf, (unsigned)len, ifindex, hoplimit, &from, zns); rtadv_process_packet(buf, (unsigned)len, ifindex, hoplimit, &from, zvrf);
return 0; return 0;
} }
@ -875,29 +880,27 @@ static void ipv6_nd_suppress_ra_set(struct interface *ifp,
{ {
struct zebra_if *zif; struct zebra_if *zif;
struct zebra_vrf *zvrf; struct zebra_vrf *zvrf;
struct zebra_ns *zns;
zif = ifp->info; zif = ifp->info;
zvrf = vrf_info_lookup(ifp->vrf_id); zvrf = vrf_info_lookup(ifp->vrf_id);
zns = zvrf->zns;
if (status == RA_SUPPRESS) { if (status == RA_SUPPRESS) {
/* RA is currently enabled */ /* RA is currently enabled */
if (zif->rtadv.AdvSendAdvertisements) { if (zif->rtadv.AdvSendAdvertisements) {
zif->rtadv.AdvSendAdvertisements = 0; zif->rtadv.AdvSendAdvertisements = 0;
zif->rtadv.AdvIntervalTimer = 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(rtadv_get_socket(zvrf), ifp);
if (zrouter.rtadv.adv_if_count == 0) if (zvrf->rtadv.adv_if_count == 0)
rtadv_event(zns, RTADV_STOP, 0); rtadv_event(zvrf, RTADV_STOP, 0);
} }
} else { } else {
if (!zif->rtadv.AdvSendAdvertisements) { if (!zif->rtadv.AdvSendAdvertisements) {
zif->rtadv.AdvSendAdvertisements = 1; zif->rtadv.AdvSendAdvertisements = 1;
zif->rtadv.AdvIntervalTimer = 0; zif->rtadv.AdvIntervalTimer = 0;
zrouter.rtadv.adv_if_count++; zvrf->rtadv.adv_if_count++;
if (zif->rtadv.MaxRtrAdvInterval >= 1000) { if (zif->rtadv.MaxRtrAdvInterval >= 1000) {
/* Enable Fast RA only when RA interval is in /* Enable Fast RA only when RA interval is in
@ -907,11 +910,11 @@ static void ipv6_nd_suppress_ra_set(struct interface *ifp,
RTADV_NUM_FAST_REXMITS; RTADV_NUM_FAST_REXMITS;
} }
if_join_all_router(zrouter.rtadv.sock, ifp); if_join_all_router(rtadv_get_socket(zvrf), ifp);
if (zrouter.rtadv.adv_if_count == 1) if (zvrf->rtadv.adv_if_count == 1)
rtadv_event(zns, RTADV_START, rtadv_event(zvrf, RTADV_START,
zrouter.rtadv.sock); rtadv_get_socket(zvrf));
} }
} }
} }
@ -944,7 +947,7 @@ static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int enable)
zebra_route_string(client->proto), ra_interval); zebra_route_string(client->proto), ra_interval);
/* Locate interface and check VRF match. */ /* 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) { if (!ifp) {
flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE, flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE,
"%u: IF %u RA %s client %s - interface unknown", "%u: IF %u RA %s client %s - interface unknown",
@ -1051,6 +1054,9 @@ DEFUN (ipv6_nd_ra_interval_msec,
VTY_DECLVAR_CONTEXT(interface, ifp); VTY_DECLVAR_CONTEXT(interface, ifp);
unsigned interval; unsigned interval;
struct zebra_if *zif = ifp->info; 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); interval = strtoul(argv[idx_number]->arg, NULL, 10);
if ((zif->rtadv.AdvDefaultLifetime != -1 if ((zif->rtadv.AdvDefaultLifetime != -1
@ -1061,10 +1067,10 @@ DEFUN (ipv6_nd_ra_interval_msec,
} }
if (zif->rtadv.MaxRtrAdvInterval % 1000) if (zif->rtadv.MaxRtrAdvInterval % 1000)
zrouter.rtadv.adv_msec_if_count--; zvrf->rtadv.adv_msec_if_count--;
if (interval % 1000) 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); SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
zif->rtadv.MaxRtrAdvInterval = interval; zif->rtadv.MaxRtrAdvInterval = interval;
@ -1086,6 +1092,9 @@ DEFUN (ipv6_nd_ra_interval,
VTY_DECLVAR_CONTEXT(interface, ifp); VTY_DECLVAR_CONTEXT(interface, ifp);
unsigned interval; unsigned interval;
struct zebra_if *zif = ifp->info; 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); interval = strtoul(argv[idx_number]->arg, NULL, 10);
if ((zif->rtadv.AdvDefaultLifetime != -1 if ((zif->rtadv.AdvDefaultLifetime != -1
@ -1096,7 +1105,7 @@ DEFUN (ipv6_nd_ra_interval,
} }
if (zif->rtadv.MaxRtrAdvInterval % 1000) if (zif->rtadv.MaxRtrAdvInterval % 1000)
zrouter.rtadv.adv_msec_if_count--; zvrf->rtadv.adv_msec_if_count--;
/* convert to milliseconds */ /* convert to milliseconds */
interval = interval * 1000; interval = interval * 1000;
@ -1122,9 +1131,12 @@ DEFUN (no_ipv6_nd_ra_interval,
{ {
VTY_DECLVAR_CONTEXT(interface, ifp); VTY_DECLVAR_CONTEXT(interface, ifp);
struct zebra_if *zif = ifp->info; struct zebra_if *zif = ifp->info;
struct zebra_vrf *zvrf = NULL;
zvrf = vrf_info_lookup(ifp->vrf_id);
if (zif->rtadv.MaxRtrAdvInterval % 1000) 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); UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
@ -2094,15 +2106,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) { switch (event) {
case RTADV_START: case RTADV_START:
thread_add_read(zrouter.master, rtadv_read, zns, val, thread_add_read(zrouter.master, rtadv_read, zvrf, val,
&rtadv->ra_read); &rtadv->ra_read);
thread_add_event(zrouter.master, rtadv_timer, zns, 0, thread_add_event(zrouter.master, rtadv_timer, zvrf, 0,
&rtadv->ra_timer); &rtadv->ra_timer);
break; break;
case RTADV_STOP: case RTADV_STOP:
@ -2116,15 +2128,15 @@ static void rtadv_event(struct zebra_ns *zns, enum rtadv_event event, int val)
} }
break; break;
case RTADV_TIMER: case RTADV_TIMER:
thread_add_timer(zrouter.master, rtadv_timer, zns, val, thread_add_timer(zrouter.master, rtadv_timer, zvrf, val,
&rtadv->ra_timer); &rtadv->ra_timer);
break; break;
case RTADV_TIMER_MSEC: 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); &rtadv->ra_timer);
break; break;
case RTADV_READ: case RTADV_READ:
thread_add_read(zrouter.master, rtadv_read, zns, val, thread_add_read(zrouter.master, rtadv_read, zvrf, val,
&rtadv->ra_read); &rtadv->ra_read);
break; break;
default: default:
@ -2133,21 +2145,29 @@ static void rtadv_event(struct zebra_ns *zns, enum rtadv_event event, int val)
return; return;
} }
void rtadv_init(struct zebra_ns *zns) void rtadv_init(struct zebra_vrf *zvrf)
{ {
zrouter.rtadv.sock = rtadv_make_socket(zns->ns_id); if (vrf_is_backend_netns()) {
zvrf->rtadv.sock = rtadv_make_socket(zvrf->zns->ns_id);
zrouter.rtadv_sock = -1;
} else if (!zrouter.rtadv_sock) {
zvrf->rtadv.sock = -1;
zrouter.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); rtadv_event(zvrf, RTADV_STOP, 0);
if (zrouter.rtadv.sock >= 0) { if (zvrf->rtadv.sock >= 0) {
close(zrouter.rtadv.sock); close(zvrf->rtadv.sock);
zrouter.rtadv.sock = -1; zvrf->rtadv.sock = -1;
} else if (zrouter.rtadv_sock >= 0) {
close(zrouter.rtadv_sock);
zrouter.rtadv_sock = -1;
} }
zvrf->rtadv.adv_if_count = 0;
zrouter.rtadv.adv_if_count = 0; zvrf->rtadv.adv_msec_if_count = 0;
zrouter.rtadv.adv_msec_if_count = 0;
} }
void rtadv_cmd_init(void) void rtadv_cmd_init(void)
@ -2243,11 +2263,11 @@ static int if_leave_all_router(int sock, struct interface *ifp)
} }
#else #else
void rtadv_init(struct zebra_ns *zns) void rtadv_init(struct zebra_vrf *zvrf)
{ {
/* Empty.*/; /* Empty.*/;
} }
void rtadv_terminate(struct zebra_ns *zns) void rtadv_terminate(struct zebra_vrf *zvrf)
{ {
/* Empty.*/; /* Empty.*/;
} }

View File

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

View File

@ -27,7 +27,6 @@
#include "lib/prefix.h" #include "lib/prefix.h"
#include "lib/memory.h" #include "lib/memory.h"
#include "rtadv.h"
#include "zebra_ns.h" #include "zebra_ns.h"
#include "zebra_vrf.h" #include "zebra_vrf.h"
#include "zebra_memory.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; zns->ns_id = ns_id;
#if defined(HAVE_RTADV)
rtadv_init(zns);
#endif
kernel_init(zns); kernel_init(zns);
interface_list(zns); interface_list(zns);
route_read(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) static int zebra_ns_disable_internal(struct zebra_ns *zns, bool complete)
{ {
route_table_finish(zns->if_table); route_table_finish(zns->if_table);
#if defined(HAVE_RTADV)
rtadv_terminate(zns);
#endif
kernel_terminate(zns, complete); kernel_terminate(zns, complete);

View File

@ -82,9 +82,8 @@ struct zebra_router {
struct hash *iptable_hash; struct hash *iptable_hash;
#if defined(HAVE_RTADV) /* used if vrf backend is not network namespace */
struct rtadv rtadv; int rtadv_sock;
#endif /* HAVE_RTADV */
/* A sequence number used for tracking routes */ /* A sequence number used for tracking routes */
_Atomic uint32_t sequence_num; _Atomic uint32_t sequence_num;

View File

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

View File

@ -155,6 +155,10 @@ struct zebra_vrf {
uint64_t lsp_removals_queued; uint64_t lsp_removals_queued;
uint64_t lsp_installs; uint64_t lsp_installs;
uint64_t lsp_removals; 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 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 #define NHT_RM_NAME(zvrf, afi, rtype) zvrf->nht_rm[afi][rtype].name