From 7bcadbaefe8d8e76b8ac054823f0039e1d8e8003 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Tue, 26 Mar 2019 10:23:18 +0100 Subject: [PATCH] bfdd: socket handling per vrf context sockets are created foreach network namespace context enabled. Signed-off-by: Philippe Guibert --- bfdd/bfd.c | 80 +++++++++++++++++++++++++++- bfdd/bfd.h | 21 +++++--- bfdd/bfd_packet.c | 129 ++++++++++++++++++++++++++-------------------- bfdd/bfdd.c | 28 +--------- 4 files changed, 169 insertions(+), 89 deletions(-) diff --git a/bfdd/bfd.c b/bfdd/bfd.c index 196f15d23d..308de24174 100644 --- a/bfdd/bfd.c +++ b/bfdd/bfd.c @@ -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; +} diff --git a/bfdd/bfd.h b/bfdd/bfd.h index f6a5b69396..d194851d7a 100644 --- a/bfdd/bfd.h +++ b/bfdd/bfd.h @@ -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 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); diff --git a/bfdd/bfd_packet.c b/bfdd/bfd_packet.c index 7526ff633a..58ae5bb4f1 100644 --- a/bfdd/bfd_packet.c +++ b/bfdd/bfd_packet.c @@ -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)); diff --git a/bfdd/bfdd.c b/bfdd/bfdd.c index d352f11031..fe4408bc8b 100644 --- a/bfdd/bfdd.c +++ b/bfdd/bfdd.c @@ -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); -- 2.39.5