diff options
author | Rafael Zalamena <rzalamena@opensourcerouting.org> | 2018-06-27 16:29:02 +0200 |
---|---|---|
committer | Rafael Zalamena <rzalamena@opensourcerouting.org> | 2018-08-08 23:24:53 +0200 |
commit | e9e2c950d7423071e8577a12c072a5309f02f8c1 (patch) | |
tree | 6d89f3c28fc3829affb30484aa41be57ba925d05 /bfdd/bfdd.c | |
parent | lib: import new JSON iteration macro (diff) | |
download | frr-e9e2c950d7423071e8577a12c072a5309f02f8c1.tar.xz frr-e9e2c950d7423071e8577a12c072a5309f02f8c1.zip |
bfdd: imported new daemon source code
Import source code from external `bfdd` daemon ported from Cumulus PTM.
Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>
Diffstat (limited to 'bfdd/bfdd.c')
-rw-r--r-- | bfdd/bfdd.c | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/bfdd/bfdd.c b/bfdd/bfdd.c new file mode 100644 index 000000000..3313c8137 --- /dev/null +++ b/bfdd/bfdd.c @@ -0,0 +1,234 @@ +/* + * BFD daemon code + * Copyright (C) 2018 Network Device Education Foundation, Inc. ("NetDEF") + * + * FRR is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * FRR is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with FRR; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include <zebra.h> + +#include <err.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "bfd.h" +#include "lib/version.h" +#include "lib/libfrr.h" + +/* + * FRR related code. + */ +DEFINE_MGROUP(BFDD, "Bidirectional Forwarding Detection Daemon"); +DEFINE_MTYPE(BFDD, BFDD_TMP, "short-lived temporary memory"); +DEFINE_MTYPE(BFDD, BFDD_CONFIG, "long-lived configuration memory"); +DEFINE_MTYPE(BFDD, BFDD_LABEL, "long-lived label memory"); +DEFINE_MTYPE(BFDD, BFDD_CONTROL, "long-lived control socket memory"); +DEFINE_MTYPE(BFDD, BFDD_NOTIFICATION, "short-lived control notification data"); + +/* Master of threads. */ +struct thread_master *master; + +/* BFDd privileges */ +static zebra_capabilities_t _caps_p[] = {ZCAP_BIND}; + +struct zebra_privs_t bfdd_privs = { +#if defined(FRR_USER) && defined(FRR_GROUP) + .user = FRR_USER, + .group = FRR_GROUP, +#endif +#if defined(VTY_GROUP) + .vty_group = VTY_GROUP, +#endif + .caps_p = _caps_p, + .cap_num_p = array_size(_caps_p), + .cap_num_i = 0, +}; + +void socket_close(int *s) +{ + if (*s <= 0) + return; + + if (close(*s) != 0) + log_error("%s: close(%d): (%d) %s", __func__, *s, errno, + strerror(errno)); + + *s = -1; +} + +static void sigusr1_handler(void) +{ + zlog_rotate(); +} + +static void sigterm_handler(void) +{ + /* Signalize shutdown. */ + frr_early_fini(); + + /* Shutdown controller to avoid receiving anymore commands. */ + control_shutdown(); + + /* 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); + socket_close(&bglobal.bg_vxlan); + + /* Terminate and free() FRR related memory. */ + frr_fini(); + + exit(0); +} + +static struct quagga_signal_t bfd_signals[] = { + { + .signal = SIGUSR1, + .handler = &sigusr1_handler, + }, + { + .signal = SIGTERM, + .handler = &sigterm_handler, + }, + { + .signal = SIGINT, + .handler = &sigterm_handler, + }, +}; + +FRR_DAEMON_INFO(bfdd, BFD, .vty_port = 2617, + .proghelp = "Implementation of the BFD protocol.", + .signals = bfd_signals, .n_signals = array_size(bfd_signals), + .privs = &bfdd_privs) + +#define OPTION_CTLSOCK 1001 +static struct option longopts[] = { + {"bfdctl", required_argument, NULL, OPTION_CTLSOCK}, + {0} +}; + + +/* + * BFD daemon related code. + */ +struct bfd_global bglobal; + +struct bfd_diag_str_list diag_list[] = { + {.str = "NeighDown", .type = BFD_DIAGNEIGHDOWN}, + {.str = "DetectTime", .type = BFD_DIAGDETECTTIME}, + {.str = "AdminDown", .type = BFD_DIAGADMINDOWN}, + {.str = NULL}, +}; + +struct bfd_state_str_list state_list[] = { + {.str = "AdminDown", .type = PTM_BFD_ADM_DOWN}, + {.str = "Down", .type = PTM_BFD_DOWN}, + {.str = "Init", .type = PTM_BFD_INIT}, + {.str = "Up", .type = PTM_BFD_UP}, + {.str = NULL}, +}; + + +static void bg_init(void) +{ + TAILQ_INIT(&bglobal.bg_bcslist); + + 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 = ptm_bfd_echo_sock_init(); + bglobal.bg_vxlan = ptm_bfd_vxlan_sock_init(); +} + +int main(int argc, char *argv[]) +{ + const char *ctl_path = BFDD_CONTROL_SOCKET; + int opt; + + frr_preinit(&bfdd_di, argc, argv); + frr_opt_add("", longopts, + " --bfdctl Specify bfdd control socket\n"); + + while (true) { + opt = frr_getopt(argc, argv, NULL); + if (opt == EOF) + break; + + switch (opt) { + case OPTION_CTLSOCK: + ctl_path = optarg; + break; + + default: + frr_help_exit(1); + break; + } + } + +#if 0 /* TODO add support for JSON configuration files. */ + parse_config(conf); +#endif + + /* Initialize logging API. */ + log_init(1, BLOG_DEBUG, &bfdd_di); + + /* Initialize system sockets. */ + bg_init(); + + /* Initialize control socket. */ + control_init(ctl_path); + + /* Initialize FRR infrastructure. */ + master = frr_init(); + + /* Initialize BFD data structures. */ + bfd_initialize(); + + /* 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]); +#if 0 /* TODO VxLAN support. */ + thread_add_read(master, bfd_recv_cb, NULL, bglobal.bg_vxlan, + &bglobal.bg_ev[5]); +#endif + thread_add_read(master, control_accept, NULL, bglobal.bg_csock, + &bglobal.bg_csockev); + + /* read configuration file and daemonize */ + frr_config_fork(); + + frr_run(master); + /* NOTREACHED */ + + return 0; +} |