bfdd: socket handling per vrf context

sockets are created foreach network namespace context enabled.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This commit is contained in:
Philippe Guibert 2019-03-26 10:23:18 +01:00
parent 9fc0bc5cfc
commit 7bcadbaefe
4 changed files with 170 additions and 90 deletions

View File

@ -1458,15 +1458,72 @@ static int bfd_vrf_delete(struct vrf *vrf)
static int bfd_vrf_enable(struct vrf *vrf)
{
struct bfd_vrf_global *bvrf;
/* a different name */
if (!vrf->info) {
bvrf = XCALLOC(MTYPE_BFDD_VRF, sizeof(struct bfd_vrf_global));
bvrf->vrf = vrf;
vrf->info = (void *)bvrf;
} else
bvrf = vrf->info;
log_debug("VRF enable add %s id %u", vrf->name, vrf->vrf_id);
/* create sockets if needed */
if (!bvrf->bg_shop)
bvrf->bg_shop = bp_udp_shop(vrf->vrf_id);
if (!bvrf->bg_mhop)
bvrf->bg_mhop = bp_udp_mhop(vrf->vrf_id);
if (!bvrf->bg_shop6)
bvrf->bg_shop6 = bp_udp6_shop(vrf->vrf_id);
if (!bvrf->bg_mhop6)
bvrf->bg_mhop6 = bp_udp6_mhop(vrf->vrf_id);
if (!bvrf->bg_echo)
bvrf->bg_echo = bp_echo_socket(vrf->vrf_id);
if (!bvrf->bg_echov6)
bvrf->bg_echov6 = bp_echov6_socket(vrf->vrf_id);
/* Add descriptors to the event loop. */
if (!bvrf->bg_ev[0])
thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_shop,
&bvrf->bg_ev[0]);
if (!bvrf->bg_ev[1])
thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_mhop,
&bvrf->bg_ev[1]);
if (!bvrf->bg_ev[2])
thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_shop6,
&bvrf->bg_ev[2]);
if (!bvrf->bg_ev[3])
thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_mhop6,
&bvrf->bg_ev[3]);
if (!bvrf->bg_ev[4])
thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_echo,
&bvrf->bg_ev[4]);
if (!bvrf->bg_ev[5])
thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_echov6,
&bvrf->bg_ev[5]);
return 0;
}
static int bfd_vrf_disable(struct vrf *vrf)
{
if (vrf->vrf_id == VRF_DEFAULT)
struct bfd_vrf_global *bvrf;
if (!vrf->info)
return 0;
bvrf = vrf->info;
log_debug("VRF disable %s id %d", vrf->name, vrf->vrf_id);
/* Close all descriptors. */
socket_close(&bvrf->bg_echo);
socket_close(&bvrf->bg_shop);
socket_close(&bvrf->bg_mhop);
socket_close(&bvrf->bg_shop6);
socket_close(&bvrf->bg_mhop6);
/* free context */
XFREE(MTYPE_BFDD_VRF, bvrf);
vrf->info = NULL;
return 0;
}
@ -1476,3 +1533,24 @@ void bfd_vrf_init(void)
bfd_vrf_delete, NULL);
}
void bfd_vrf_terminate(void)
{
vrf_terminate();
}
struct bfd_vrf_global *bfd_vrf_look_by_session(struct bfd_session *bfd)
{
struct vrf *vrf;
if (!vrf_is_backend_netns()) {
vrf = vrf_lookup_by_id(VRF_DEFAULT);
if (vrf)
return (struct bfd_vrf_global *)vrf->info;
return NULL;
}
if (!bfd)
return NULL;
if (!bfd->vrf)
return NULL;
return bfd->vrf->info;
}

View File

@ -48,6 +48,7 @@ DECLARE_MTYPE(BFDD_LABEL);
DECLARE_MTYPE(BFDD_CONTROL);
DECLARE_MTYPE(BFDD_SESSION_OBSERVER);
DECLARE_MTYPE(BFDD_NOTIFICATION);
DECLARE_MTYPE(BFDD_VRF);
extern struct zebra_privs_t bfdd_privs;
@ -381,15 +382,19 @@ int control_accept(struct thread *t);
*
* Daemon specific code.
*/
struct bfd_global {
struct bfd_vrf_global {
int bg_shop;
int bg_mhop;
int bg_shop6;
int bg_mhop6;
int bg_echo;
int bg_echov6;
struct thread *bg_ev[6];
struct vrf *vrf;
struct thread *bg_ev[6];
};
struct bfd_global {
int bg_csock;
struct thread *bg_csockev;
struct bcslist bg_bcslist;
@ -461,14 +466,14 @@ int bp_set_tosv6(int sd, uint8_t value);
int bp_set_tos(int sd, uint8_t value);
int bp_bind_dev(int sd, const char *dev);
int bp_udp_shop(void);
int bp_udp_mhop(void);
int bp_udp6_shop(void);
int bp_udp6_mhop(void);
int bp_udp_shop(vrf_id_t vrf_id);
int bp_udp_mhop(vrf_id_t vrf_id);
int bp_udp6_shop(vrf_id_t vrf_id);
int bp_udp6_mhop(vrf_id_t vrf_id);
int bp_peer_socket(const struct bfd_session *bs);
int bp_peer_socketv6(const struct bfd_session *bs);
int bp_echo_socket(void);
int bp_echov6_socket(void);
int bp_echo_socket(vrf_id_t vrf_id);
int bp_echov6_socket(vrf_id_t vrf_id);
void ptm_bfd_snd(struct bfd_session *bfd, int fbit);
void ptm_bfd_echo_snd(struct bfd_session *bfd);
@ -542,6 +547,8 @@ void bs_to_bpc(struct bfd_session *bs, struct bfd_peer_cfg *bpc);
void bfd_initialize(void);
void bfd_shutdown(void);
void bfd_vrf_init(void);
void bfd_vrf_terminate(void);
struct bfd_vrf_global *bfd_vrf_look_by_session(struct bfd_session *bfd);
struct bfd_session *bfd_id_lookup(uint32_t id);
struct bfd_session *bfd_key_lookup(struct bfd_key key);

View File

@ -40,11 +40,11 @@
/*
* Prototypes
*/
static int ptm_bfd_process_echo_pkt(int s);
static int ptm_bfd_process_echo_pkt(struct bfd_vrf_global *bvrf, int s);
int _ptm_bfd_send(struct bfd_session *bs, uint16_t *port, const void *data,
size_t datalen);
static void bfd_sd_reschedule(int sd);
static void bfd_sd_reschedule(struct bfd_vrf_global *bvrf, int sd);
ssize_t bfd_recv_ipv4(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl,
ifindex_t *ifindex, struct sockaddr_any *local,
struct sockaddr_any *peer);
@ -53,7 +53,8 @@ ssize_t bfd_recv_ipv6(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl,
struct sockaddr_any *peer);
int bp_udp_send(int sd, uint8_t ttl, uint8_t *data, size_t datalen,
struct sockaddr *to, socklen_t tolen);
int bp_bfd_echo_in(int sd, uint8_t *ttl, uint32_t *my_discr);
int bp_bfd_echo_in(struct bfd_vrf_global *bvrf, int sd,
uint8_t *ttl, uint32_t *my_discr);
/* socket related prototypes */
static void bp_set_ipopts(int sd);
@ -128,7 +129,10 @@ void ptm_bfd_echo_snd(struct bfd_session *bfd)
struct bfd_echo_pkt bep;
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
struct bfd_vrf_global *bvrf = bfd_vrf_look_by_session(bfd);
if (!bvrf)
return;
if (!BFD_CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_ECHO_ACTIVE))
BFD_SET_FLAG(bfd->flags, BFD_SESS_FLAG_ECHO_ACTIVE);
@ -138,7 +142,7 @@ void ptm_bfd_echo_snd(struct bfd_session *bfd)
bep.my_discr = htonl(bfd->discrs.my_discr);
if (BFD_CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_IPV6)) {
sd = bglobal.bg_echov6;
sd = bvrf->bg_echov6;
memset(&sin6, 0, sizeof(sin6));
sin6.sin6_family = AF_INET6;
memcpy(&sin6.sin6_addr, &bfd->key.peer, sizeof(sin6.sin6_addr));
@ -153,7 +157,7 @@ void ptm_bfd_echo_snd(struct bfd_session *bfd)
sa = (struct sockaddr *)&sin6;
salen = sizeof(sin6);
} else {
sd = bglobal.bg_echo;
sd = bvrf->bg_echo;
memset(&sin6, 0, sizeof(sin6));
sin.sin_family = AF_INET;
memcpy(&sin.sin_addr, &bfd->key.peer, sizeof(sin.sin_addr));
@ -173,14 +177,14 @@ void ptm_bfd_echo_snd(struct bfd_session *bfd)
bfd->stats.tx_echo_pkt++;
}
static int ptm_bfd_process_echo_pkt(int s)
static int ptm_bfd_process_echo_pkt(struct bfd_vrf_global *bvrf, int s)
{
struct bfd_session *bfd;
uint32_t my_discr = 0;
uint8_t ttl = 0;
/* Receive and parse echo packet. */
if (bp_bfd_echo_in(s, &ttl, &my_discr) == -1)
if (bp_bfd_echo_in(bvrf, s, &ttl, &my_discr) == -1)
return 0;
/* Your discriminator not zero - use it to find session */
@ -440,32 +444,32 @@ ssize_t bfd_recv_ipv6(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl,
return mlen;
}
static void bfd_sd_reschedule(int sd)
static void bfd_sd_reschedule(struct bfd_vrf_global *bvrf, int sd)
{
if (sd == bglobal.bg_shop) {
THREAD_OFF(bglobal.bg_ev[0]);
thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_shop,
&bglobal.bg_ev[0]);
} else if (sd == bglobal.bg_mhop) {
THREAD_OFF(bglobal.bg_ev[1]);
thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_mhop,
&bglobal.bg_ev[1]);
} else if (sd == bglobal.bg_shop6) {
THREAD_OFF(bglobal.bg_ev[2]);
thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_shop6,
&bglobal.bg_ev[2]);
} else if (sd == bglobal.bg_mhop6) {
THREAD_OFF(bglobal.bg_ev[3]);
thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_mhop6,
&bglobal.bg_ev[3]);
} else if (sd == bglobal.bg_echo) {
THREAD_OFF(bglobal.bg_ev[4]);
thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_echo,
&bglobal.bg_ev[4]);
} else if (sd == bglobal.bg_echov6) {
THREAD_OFF(bglobal.bg_ev[5]);
thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_echov6,
&bglobal.bg_ev[5]);
if (sd == bvrf->bg_shop) {
THREAD_OFF(bvrf->bg_ev[0]);
thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_shop,
&bvrf->bg_ev[0]);
} else if (sd == bvrf->bg_mhop) {
THREAD_OFF(bvrf->bg_ev[1]);
thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_mhop,
&bvrf->bg_ev[1]);
} else if (sd == bvrf->bg_shop6) {
THREAD_OFF(bvrf->bg_ev[2]);
thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_shop6,
&bvrf->bg_ev[2]);
} else if (sd == bvrf->bg_mhop6) {
THREAD_OFF(bvrf->bg_ev[3]);
thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_mhop6,
&bvrf->bg_ev[3]);
} else if (sd == bvrf->bg_echo) {
THREAD_OFF(bvrf->bg_ev[4]);
thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_echo,
&bvrf->bg_ev[4]);
} else if (sd == bvrf->bg_echov6) {
THREAD_OFF(bvrf->bg_ev[5]);
thread_add_read(master, bfd_recv_cb, bvrf, bvrf->bg_echov6,
&bvrf->bg_ev[5]);
}
}
@ -517,13 +521,16 @@ int bfd_recv_cb(struct thread *t)
ifindex_t ifindex = IFINDEX_INTERNAL;
struct sockaddr_any local, peer;
uint8_t msgbuf[1516];
struct bfd_vrf_global *bvrf = THREAD_ARG(t);
if (bvrf)
vrfid = bvrf->vrf->vrf_id;
/* Schedule next read. */
bfd_sd_reschedule(sd);
bfd_sd_reschedule(bvrf, sd);
/* Handle echo packets. */
if (sd == bglobal.bg_echo || sd == bglobal.bg_echov6) {
ptm_bfd_process_echo_pkt(sd);
if (sd == bvrf->bg_echo || sd == bvrf->bg_echov6) {
ptm_bfd_process_echo_pkt(bvrf, sd);
return 0;
}
@ -533,12 +540,12 @@ int bfd_recv_cb(struct thread *t)
/* Handle control packets. */
is_mhop = false;
if (sd == bglobal.bg_shop || sd == bglobal.bg_mhop) {
is_mhop = sd == bglobal.bg_mhop;
if (sd == bvrf->bg_shop || sd == bvrf->bg_mhop) {
is_mhop = sd == bvrf->bg_mhop;
mlen = bfd_recv_ipv4(sd, msgbuf, sizeof(msgbuf), &ttl, &ifindex,
&local, &peer);
} else if (sd == bglobal.bg_shop6 || sd == bglobal.bg_mhop6) {
is_mhop = sd == bglobal.bg_mhop6;
} else if (sd == bvrf->bg_shop6 || sd == bvrf->bg_mhop6) {
is_mhop = sd == bvrf->bg_mhop6;
mlen = bfd_recv_ipv6(sd, msgbuf, sizeof(msgbuf), &ttl, &ifindex,
&local, &peer);
}
@ -681,7 +688,8 @@ int bfd_recv_cb(struct thread *t)
*
* Returns -1 on error or loopback or 0 on success.
*/
int bp_bfd_echo_in(int sd, uint8_t *ttl, uint32_t *my_discr)
int bp_bfd_echo_in(struct bfd_vrf_global *bvrf, int sd,
uint8_t *ttl, uint32_t *my_discr)
{
struct bfd_echo_pkt *bep;
ssize_t rlen;
@ -690,7 +698,7 @@ int bp_bfd_echo_in(int sd, uint8_t *ttl, uint32_t *my_discr)
vrf_id_t vrfid = VRF_DEFAULT;
uint8_t msgbuf[1516];
if (sd == bglobal.bg_echo)
if (sd == bvrf->bg_echo)
rlen = bfd_recv_ipv4(sd, msgbuf, sizeof(msgbuf), ttl, &ifindex,
&local, &peer);
else
@ -708,7 +716,7 @@ int bp_bfd_echo_in(int sd, uint8_t *ttl, uint32_t *my_discr)
if (*ttl == BFD_TTL_VAL) {
bp_udp_send(sd, *ttl - 1, msgbuf, rlen,
(struct sockaddr *)&peer,
(sd == bglobal.bg_echo) ? sizeof(peer.sa_sin)
(sd == bvrf->bg_echo) ? sizeof(peer.sa_sin)
: sizeof(peer.sa_sin6));
return -1;
}
@ -871,25 +879,28 @@ static void bp_bind_ip(int sd, uint16_t port)
log_fatal("bind-ip: bind: %s", strerror(errno));
}
int bp_udp_shop(void)
int bp_udp_shop(vrf_id_t vrf_id)
{
int sd;
sd = socket(AF_INET, SOCK_DGRAM, PF_UNSPEC);
frr_elevate_privs(&bfdd_privs) {
sd = vrf_socket(AF_INET, SOCK_DGRAM, PF_UNSPEC, vrf_id, NULL);
}
if (sd == -1)
log_fatal("udp-shop: socket: %s", strerror(errno));
bp_set_ipopts(sd);
bp_bind_ip(sd, BFD_DEFDESTPORT);
return sd;
}
int bp_udp_mhop(void)
int bp_udp_mhop(vrf_id_t vrf_id)
{
int sd;
sd = socket(AF_INET, SOCK_DGRAM, PF_UNSPEC);
frr_elevate_privs(&bfdd_privs) {
sd = vrf_socket(AF_INET, SOCK_DGRAM, PF_UNSPEC, vrf_id, NULL);
}
if (sd == -1)
log_fatal("udp-mhop: socket: %s", strerror(errno));
@ -1095,11 +1106,13 @@ static void bp_bind_ipv6(int sd, uint16_t port)
log_fatal("bind-ipv6: bind: %s", strerror(errno));
}
int bp_udp6_shop(void)
int bp_udp6_shop(vrf_id_t vrf_id)
{
int sd;
sd = socket(AF_INET6, SOCK_DGRAM, PF_UNSPEC);
frr_elevate_privs(&bfdd_privs) {
sd = vrf_socket(AF_INET6, SOCK_DGRAM, PF_UNSPEC, vrf_id, NULL);
}
if (sd == -1)
log_fatal("udp6-shop: socket: %s", strerror(errno));
@ -1109,11 +1122,13 @@ int bp_udp6_shop(void)
return sd;
}
int bp_udp6_mhop(void)
int bp_udp6_mhop(vrf_id_t vrf_id)
{
int sd;
sd = socket(AF_INET6, SOCK_DGRAM, PF_UNSPEC);
frr_elevate_privs(&bfdd_privs) {
sd = vrf_socket(AF_INET6, SOCK_DGRAM, PF_UNSPEC, vrf_id, NULL);
}
if (sd == -1)
log_fatal("udp6-mhop: socket: %s", strerror(errno));
@ -1123,11 +1138,13 @@ int bp_udp6_mhop(void)
return sd;
}
int bp_echo_socket(void)
int bp_echo_socket(vrf_id_t vrf_id)
{
int s;
s = socket(AF_INET, SOCK_DGRAM, 0);
frr_elevate_privs(&bfdd_privs) {
s = vrf_socket(AF_INET, SOCK_DGRAM, 0, vrf_id, NULL);
}
if (s == -1)
log_fatal("echo-socket: socket: %s", strerror(errno));
@ -1137,11 +1154,13 @@ int bp_echo_socket(void)
return s;
}
int bp_echov6_socket(void)
int bp_echov6_socket(vrf_id_t vrf_id)
{
int s;
s = socket(AF_INET6, SOCK_DGRAM, 0);
frr_elevate_privs(&bfdd_privs) {
s = vrf_socket(AF_INET6, SOCK_DGRAM, 0, vrf_id, NULL);
}
if (s == -1)
log_fatal("echov6-socket: socket: %s", strerror(errno));

View File

@ -34,6 +34,7 @@ DEFINE_MTYPE(BFDD, BFDD_LABEL, "long-lived label memory");
DEFINE_MTYPE(BFDD, BFDD_CONTROL, "long-lived control socket memory");
DEFINE_MTYPE(BFDD, BFDD_SESSION_OBSERVER, "Session observer");
DEFINE_MTYPE(BFDD, BFDD_NOTIFICATION, "short-lived control notification data");
DEFINE_MTYPE(BFDD, BFDD_VRF, "BFD VRF");
/* Master of threads. */
struct thread_master *master;
@ -85,12 +86,7 @@ static void sigterm_handler(void)
/* Shutdown and free all protocol related memory. */
bfd_shutdown();
/* Close all descriptors. */
socket_close(&bglobal.bg_echo);
socket_close(&bglobal.bg_shop);
socket_close(&bglobal.bg_mhop);
socket_close(&bglobal.bg_shop6);
socket_close(&bglobal.bg_mhop6);
bfd_vrf_terminate();
/* Terminate and free() FRR related memory. */
frr_fini();
@ -155,13 +151,6 @@ static void bg_init(void)
{
TAILQ_INIT(&bglobal.bg_bcslist);
TAILQ_INIT(&bglobal.bg_obslist);
bglobal.bg_shop = bp_udp_shop();
bglobal.bg_mhop = bp_udp_mhop();
bglobal.bg_shop6 = bp_udp6_shop();
bglobal.bg_mhop6 = bp_udp6_mhop();
bglobal.bg_echo = bp_echo_socket();
bglobal.bg_echov6 = bp_echov6_socket();
}
int main(int argc, char *argv[])
@ -213,19 +202,6 @@ int main(int argc, char *argv[])
/* Initialize zebra connection. */
bfdd_zclient_init(&bfdd_privs);
/* Add descriptors to the event loop. */
thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_shop,
&bglobal.bg_ev[0]);
thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_mhop,
&bglobal.bg_ev[1]);
thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_shop6,
&bglobal.bg_ev[2]);
thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_mhop6,
&bglobal.bg_ev[3]);
thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_echo,
&bglobal.bg_ev[4]);
thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_echov6,
&bglobal.bg_ev[5]);
thread_add_read(master, control_accept, NULL, bglobal.bg_csock,
&bglobal.bg_csockev);