diff options
Diffstat (limited to 'bfdd')
-rw-r--r-- | bfdd/bfd.c | 78 | ||||
-rw-r--r-- | bfdd/bfd.h | 158 | ||||
-rw-r--r-- | bfdd/bfdctl.h | 157 | ||||
-rw-r--r-- | bfdd/bfdd.c | 27 | ||||
-rw-r--r-- | bfdd/bfdd_vty.c | 15 | ||||
-rw-r--r-- | bfdd/config.c | 592 | ||||
-rw-r--r-- | bfdd/control.c | 844 | ||||
-rw-r--r-- | bfdd/dplane.c | 2 | ||||
-rw-r--r-- | bfdd/ptm_adapter.c | 9 | ||||
-rw-r--r-- | bfdd/subdir.am | 3 |
10 files changed, 76 insertions, 1809 deletions
diff --git a/bfdd/bfd.c b/bfdd/bfd.c index b6b437a79..eb9c30031 100644 --- a/bfdd/bfd.c +++ b/bfdd/bfd.c @@ -256,19 +256,8 @@ void gen_bfd_key(struct bfd_key *key, struct sockaddr_any *peer, struct bfd_session *bs_peer_find(struct bfd_peer_cfg *bpc) { - struct bfd_session *bs; - struct peer_label *pl; struct bfd_key key; - /* Try to find label first. */ - if (bpc->bpc_has_label) { - pl = pl_find(bpc->bpc_label); - if (pl != NULL) { - bs = pl->pl_bs; - return bs; - } - } - /* Otherwise fallback to peer/local hash lookup. */ gen_bfd_key(&key, &bpc->bpc_peer, &bpc->bpc_local, bpc->bpc_mhop, bpc->bpc_localif, bpc->bpc_vrfname); @@ -327,10 +316,8 @@ int bfd_session_enable(struct bfd_session *bs) bs->ifp = ifp; /* Attempt to use data plane. */ - if (bglobal.bg_use_dplane && bfd_dplane_add_session(bs) == 0) { - control_notify_config(BCM_NOTIFY_CONFIG_ADD, bs); + if (bglobal.bg_use_dplane && bfd_dplane_add_session(bs) == 0) return 0; - } /* Sanity check: don't leak open sockets. */ if (bs->sock != -1) { @@ -502,7 +489,7 @@ void ptm_bfd_sess_up(struct bfd_session *bfd) /* Start sending control packets with poll bit immediately. */ ptm_bfd_snd(bfd, 0); - control_notify(bfd, bfd->ses_state); + ptm_bfd_notify(bfd, bfd->ses_state); if (old_state != bfd->ses_state) { bfd->stats.session_up++; @@ -538,7 +525,7 @@ void ptm_bfd_sess_dn(struct bfd_session *bfd, uint8_t diag) /* only signal clients when going from up->down state */ if (old_state == PTM_BFD_UP) - control_notify(bfd, PTM_BFD_DOWN); + ptm_bfd_notify(bfd, PTM_BFD_DOWN); /* Stop echo packet transmission if they are active */ if (CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_ECHO_ACTIVE)) @@ -690,38 +677,6 @@ struct bfd_session *bfd_session_new(void) return bs; } -int bfd_session_update_label(struct bfd_session *bs, const char *nlabel) -{ - /* New label treatment: - * - Check if the label is taken; - * - Try to allocate the memory for it and register; - */ - if (bs->pl == NULL) { - if (pl_find(nlabel) != NULL) { - /* Someone is already using it. */ - return -1; - } - - pl_new(nlabel, bs); - - return 0; - } - - /* - * Test label change consistency: - * - Do nothing if it's the same label; - * - Check if the future label is already taken; - * - Change label; - */ - if (strcmp(nlabel, bs->pl->pl_label) == 0) - return -1; - if (pl_find(nlabel) != NULL) - return -1; - - strlcpy(bs->pl->pl_label, nlabel, sizeof(bs->pl->pl_label)); - return 0; -} - static void _bfd_session_update(struct bfd_session *bs, struct bfd_peer_cfg *bpc) { @@ -750,9 +705,6 @@ static void _bfd_session_update(struct bfd_session *bs, bs->peer_profile.min_echo_tx = bs->timers.desired_min_echo_tx; } - if (bpc->bpc_has_label) - bfd_session_update_label(bs, bpc->bpc_label); - if (bpc->bpc_cbit) SET_FLAG(bs->flags, BFD_SESS_FLAG_CBIT); else @@ -792,8 +744,6 @@ static int bfd_session_update(struct bfd_session *bs, struct bfd_peer_cfg *bpc) _bfd_session_update(bs, bpc); - control_notify_config(BCM_NOTIFY_CONFIG_UPDATE, bs); - return 0; } @@ -819,8 +769,6 @@ void bfd_session_free(struct bfd_session *bs) if (bso != NULL) bs_observer_del(bso); - pl_free(bs->pl); - XFREE(MTYPE_BFDD_PROFILE, bs->profile_name); XFREE(MTYPE_BFDD_CONFIG, bs); } @@ -917,8 +865,6 @@ struct bfd_session *bs_registrate(struct bfd_session *bfd) if (bglobal.debug_peer_event) zlog_debug("session-new: %s", bs_to_string(bfd)); - control_notify_config(BCM_NOTIFY_CONFIG_ADD, bfd); - return bfd; } @@ -941,8 +887,6 @@ int ptm_bfd_sess_del(struct bfd_peer_cfg *bpc) if (bglobal.debug_peer_event) zlog_debug("%s: %s", __func__, bs_to_string(bs)); - control_notify_config(BCM_NOTIFY_CONFIG_DELETE, bs); - bfd_session_free(bs); return 0; @@ -1166,11 +1110,8 @@ void bs_final_handler(struct bfd_session *bs) * When using demand mode we must disable the detection timer * for lost control packets. */ - if (bs->demand_mode) { - /* Notify watchers about changed timers. */ - control_notify_config(BCM_NOTIFY_CONFIG_UPDATE, bs); + if (bs->demand_mode) return; - } /* * Calculate transmission time based on new timers. @@ -1189,9 +1130,6 @@ void bs_final_handler(struct bfd_session *bs) /* Apply new transmission timer immediately. */ ptm_bfd_start_xmt_timer(bs, false); - - /* Notify watchers about changed timers. */ - control_notify_config(BCM_NOTIFY_CONFIG_UPDATE, bs); } void bs_set_slow_timers(struct bfd_session *bs) @@ -1261,7 +1199,7 @@ void bfd_set_shutdown(struct bfd_session *bs, bool shutdown) if (bs->bdc) { bs->ses_state = PTM_BFD_ADM_DOWN; bfd_dplane_update_session(bs); - control_notify(bs, bs->ses_state); + ptm_bfd_notify(bs, bs->ses_state); return; } @@ -1273,7 +1211,7 @@ void bfd_set_shutdown(struct bfd_session *bs, bool shutdown) /* Change and notify state change. */ bs->ses_state = PTM_BFD_ADM_DOWN; - control_notify(bs, bs->ses_state); + ptm_bfd_notify(bs, bs->ses_state); /* Don't try to send packets with a disabled session. */ if (bs->sock != -1) @@ -1289,13 +1227,13 @@ void bfd_set_shutdown(struct bfd_session *bs, bool shutdown) if (bs->bdc) { bs->ses_state = PTM_BFD_DOWN; bfd_dplane_update_session(bs); - control_notify(bs, bs->ses_state); + ptm_bfd_notify(bs, bs->ses_state); return; } /* Change and notify state change. */ bs->ses_state = PTM_BFD_DOWN; - control_notify(bs, bs->ses_state); + ptm_bfd_notify(bs, bs->ses_state); /* Enable timers if non passive, otherwise stop them. */ if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_PASSIVE)) { diff --git a/bfdd/bfd.h b/bfdd/bfd.h index be04e655a..2f83b245e 100644 --- a/bfdd/bfd.h +++ b/bfdd/bfd.h @@ -20,19 +20,73 @@ #include "lib/queue.h" #include "lib/vrf.h" -#include "bfdctl.h" - #ifdef BFD_DEBUG #define BFDD_JSON_CONV_OPTIONS (JSON_C_TO_STRING_PRETTY) #else #define BFDD_JSON_CONV_OPTIONS (0) #endif +#ifndef MAXNAMELEN +#define MAXNAMELEN 32 +#endif + +#define BPC_DEF_DETECTMULTIPLIER 3 +#define BPC_DEF_RECEIVEINTERVAL 300 /* milliseconds */ +#define BPC_DEF_TRANSMITINTERVAL 300 /* milliseconds */ +#define BPC_DEF_ECHORECEIVEINTERVAL 50 /* milliseconds */ +#define BPC_DEF_ECHOTRANSMITINTERVAL 50 /* milliseconds */ + DECLARE_MGROUP(BFDD); -DECLARE_MTYPE(BFDD_CONTROL); -DECLARE_MTYPE(BFDD_NOTIFICATION); +DECLARE_MTYPE(BFDD_CLIENT); +DECLARE_MTYPE(BFDD_CLIENT_NOTIFICATION); + +struct sockaddr_any { + union { + struct sockaddr_in sa_sin; + struct sockaddr_in6 sa_sin6; + }; +}; + +struct bfd_peer_cfg { + bool bpc_mhop; + bool bpc_ipv4; + struct sockaddr_any bpc_peer; + struct sockaddr_any bpc_local; + + bool bpc_has_localif; + char bpc_localif[MAXNAMELEN + 1]; + + bool bpc_has_vrfname; + char bpc_vrfname[MAXNAMELEN + 1]; + + bool bpc_has_detectmultiplier; + uint8_t bpc_detectmultiplier; + + bool bpc_has_recvinterval; + uint64_t bpc_recvinterval; + + bool bpc_has_txinterval; + uint64_t bpc_txinterval; -#define BFDD_SOCK_NAME "%s/bfdd.sock", frr_runstatedir + bool bpc_has_echorecvinterval; + uint64_t bpc_echorecvinterval; + + bool bpc_has_echotxinterval; + uint64_t bpc_echotxinterval; + + bool bpc_has_minimum_ttl; + uint8_t bpc_minimum_ttl; + + bool bpc_echo; + bool bpc_createonly; + bool bpc_shutdown; + + bool bpc_cbit; + bool bpc_passive; + + bool bpc_has_profile; + char bpc_profile[64]; +}; /* bfd Authentication Type. */ #define BFD_AUTH_NULL 0 @@ -246,9 +300,6 @@ struct bfd_profile { /** Profile list type. */ TAILQ_HEAD(bfdproflist, bfd_profile); -/* bfd_session shortcut label forwarding. */ -struct peer_label; - struct bfd_config_timers { uint32_t desired_min_tx; uint32_t required_min_rx; @@ -326,14 +377,6 @@ struct bfd_session { uint64_t rtt[BFD_RTT_SAMPLE]; /* RRT in usec for echo to be looped */ }; -struct peer_label { - TAILQ_ENTRY(peer_label) pl_entry; - - struct bfd_session *pl_bs; - char pl_label[MAXNAMELEN]; -}; -TAILQ_HEAD(pllist, peer_label); - struct bfd_diag_str_list { const char *str; int type; @@ -385,64 +428,6 @@ TAILQ_HEAD(obslist, bfd_session_observer); #define BFD_DEF_ECHO_PORT 3785 #define BFD_DEF_MHOP_DEST_PORT 4784 -/* - * control.c - * - * Daemon control code to speak with local consumers. - */ - -/* See 'bfdctrl.h' for client protocol definitions. */ - -struct bfd_control_buffer { - size_t bcb_left; - size_t bcb_pos; - union { - struct bfd_control_msg *bcb_bcm; - uint8_t *bcb_buf; - }; -}; - -struct bfd_control_queue { - TAILQ_ENTRY(bfd_control_queue) bcq_entry; - - struct bfd_control_buffer bcq_bcb; -}; -TAILQ_HEAD(bcqueue, bfd_control_queue); - -struct bfd_notify_peer { - TAILQ_ENTRY(bfd_notify_peer) bnp_entry; - - struct bfd_session *bnp_bs; -}; -TAILQ_HEAD(bnplist, bfd_notify_peer); - -struct bfd_control_socket { - TAILQ_ENTRY(bfd_control_socket) bcs_entry; - - int bcs_sd; - struct event *bcs_ev; - struct event *bcs_outev; - struct bcqueue bcs_bcqueue; - - /* Notification data */ - uint64_t bcs_notify; - struct bnplist bcs_bnplist; - - enum bc_msg_version bcs_version; - enum bc_msg_type bcs_type; - - /* Message buffering */ - struct bfd_control_buffer bcs_bin; - struct bfd_control_buffer *bcs_bout; -}; -TAILQ_HEAD(bcslist, bfd_control_socket); - -int control_init(const char *path); -void control_shutdown(void); -int control_notify(struct bfd_session *bs, uint8_t notify_state); -int control_notify_config(const char *op, struct bfd_session *bs); -void control_accept(struct event *t); - /* * bfdd.c @@ -468,9 +453,6 @@ TAILQ_HEAD(dplane_queue, bfd_dplane_ctx); struct bfd_global { int bg_csock; struct event *bg_csockev; - struct bcslist bg_bcslist; - - struct pllist bg_pllist; struct obslist bg_obslist; @@ -517,27 +499,6 @@ void socket_close(int *s); /* - * config.c - * - * Contains the code related with loading/reloading configuration. - */ -int parse_config(const char *fname); -int config_request_add(const char *jsonstr); -int config_request_del(const char *jsonstr); -char *config_response(const char *status, const char *error); -char *config_notify(struct bfd_session *bs); -char *config_notify_config(const char *op, struct bfd_session *bs); - -typedef int (*bpc_handle)(struct bfd_peer_cfg *, void *arg); -int config_notify_request(struct bfd_control_socket *bcs, const char *jsonstr, - bpc_handle bh); - -struct peer_label *pl_new(const char *label, struct bfd_session *bs); -struct peer_label *pl_find(const char *label); -void pl_free(struct peer_label *pl); - - -/* * logging - alias to zebra log */ #define zlog_fatal(msg, ...) \ @@ -621,7 +582,6 @@ struct bfd_session *ptm_bfd_sess_find(struct bfd_pkt *cp, bool is_mhop); struct bfd_session *bs_peer_find(struct bfd_peer_cfg *bpc); -int bfd_session_update_label(struct bfd_session *bs, const char *nlabel); void bfd_set_polling(struct bfd_session *bs); void bs_state_handler(struct bfd_session *bs, int nstate); void bs_echo_timer_handler(struct bfd_session *bs); diff --git a/bfdd/bfdctl.h b/bfdd/bfdctl.h deleted file mode 100644 index f1f8185c3..000000000 --- a/bfdd/bfdctl.h +++ /dev/null @@ -1,157 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/********************************************************************* - * Copyright 2017-2018 Network Device Education Foundation, Inc. ("NetDEF") - * - * bfdctl.h: all BFDd control socket protocol definitions. - * - * Authors - * ------- - * Rafael Zalamena <rzalamena@opensourcerouting.org> - */ - -#ifndef _BFDCTRL_H_ -#define _BFDCTRL_H_ - -#include <netinet/in.h> - -#include <stdbool.h> -#include <stdint.h> - -/* - * Auxiliary definitions - */ -struct sockaddr_any { - union { - struct sockaddr_in sa_sin; - struct sockaddr_in6 sa_sin6; - }; -}; - -#ifndef MAXNAMELEN -#define MAXNAMELEN 32 -#endif - -#define BPC_DEF_DETECTMULTIPLIER 3 -#define BPC_DEF_RECEIVEINTERVAL 300 /* milliseconds */ -#define BPC_DEF_TRANSMITINTERVAL 300 /* milliseconds */ -#define BPC_DEF_ECHORECEIVEINTERVAL 50 /* milliseconds */ -#define BPC_DEF_ECHOTRANSMITINTERVAL 50 /* milliseconds */ - -/* Peer status */ -enum bfd_peer_status { - BPS_SHUTDOWN = 0, /* == PTM_BFD_ADM_DOWN, "adm-down" */ - BPS_DOWN = 1, /* == PTM_BFD_DOWN, "down" */ - BPS_INIT = 2, /* == PTM_BFD_INIT, "init" */ - BPS_UP = 3, /* == PTM_BFD_UP, "up" */ -}; - -struct bfd_peer_cfg { - bool bpc_mhop; - bool bpc_ipv4; - struct sockaddr_any bpc_peer; - struct sockaddr_any bpc_local; - - bool bpc_has_label; - char bpc_label[MAXNAMELEN]; - - bool bpc_has_localif; - char bpc_localif[MAXNAMELEN + 1]; - - bool bpc_has_vrfname; - char bpc_vrfname[MAXNAMELEN + 1]; - - bool bpc_has_detectmultiplier; - uint8_t bpc_detectmultiplier; - - bool bpc_has_recvinterval; - uint64_t bpc_recvinterval; - - bool bpc_has_txinterval; - uint64_t bpc_txinterval; - - bool bpc_has_echorecvinterval; - uint64_t bpc_echorecvinterval; - - bool bpc_has_echotxinterval; - uint64_t bpc_echotxinterval; - - bool bpc_has_minimum_ttl; - uint8_t bpc_minimum_ttl; - - bool bpc_echo; - bool bpc_createonly; - bool bpc_shutdown; - - bool bpc_cbit; - bool bpc_passive; - - bool bpc_has_profile; - char bpc_profile[64]; - - /* Status information */ - enum bfd_peer_status bpc_bps; - uint32_t bpc_id; - uint32_t bpc_remoteid; - uint8_t bpc_diag; - uint8_t bpc_remotediag; - uint8_t bpc_remote_detectmultiplier; - uint64_t bpc_remote_recvinterval; - uint64_t bpc_remote_txinterval; - uint64_t bpc_remote_echointerval; - uint64_t bpc_lastevent; -}; - - -/* - * Protocol definitions - */ -enum bc_msg_version { - BMV_VERSION_1 = 1, -}; - -enum bc_msg_type { - BMT_RESPONSE = 1, - BMT_REQUEST_ADD = 2, - BMT_REQUEST_DEL = 3, - BMT_NOTIFY = 4, - BMT_NOTIFY_ADD = 5, - BMT_NOTIFY_DEL = 6, -}; - -/* Notify flags to use with bcm_notify. */ -#define BCM_NOTIFY_ALL ((uint64_t)-1) -#define BCM_NOTIFY_PEER_STATE (1ULL << 0) -#define BCM_NOTIFY_CONFIG (1ULL << 1) -#define BCM_NOTIFY_NONE 0 - -/* Response 'status' definitions. */ -#define BCM_RESPONSE_OK "ok" -#define BCM_RESPONSE_ERROR "error" - -/* Notify operation. */ -#define BCM_NOTIFY_PEER_STATUS "status" -#define BCM_NOTIFY_CONFIG_ADD "add" -#define BCM_NOTIFY_CONFIG_DELETE "delete" -#define BCM_NOTIFY_CONFIG_UPDATE "update" - -/* Notification special ID. */ -#define BCM_NOTIFY_ID 0 - -struct bfd_control_msg { - /* Total length without the header. */ - uint32_t bcm_length; - /* - * Message request/response id. - * All requests will have a correspondent response with the - * same id. - */ - uint16_t bcm_id; - /* Message type. */ - uint8_t bcm_type; - /* Message version. */ - uint8_t bcm_ver; - /* Message payload. */ - uint8_t bcm_data[0]; -}; - -#endif diff --git a/bfdd/bfdd.c b/bfdd/bfdd.c index 243cf5c12..c2d8e926b 100644 --- a/bfdd/bfdd.c +++ b/bfdd/bfdd.c @@ -28,8 +28,8 @@ * FRR related code. */ DEFINE_MGROUP(BFDD, "Bidirectional Forwarding Detection Daemon"); -DEFINE_MTYPE(BFDD, BFDD_CONTROL, "control socket memory"); -DEFINE_MTYPE(BFDD, BFDD_NOTIFICATION, "control notification data"); +DEFINE_MTYPE(BFDD, BFDD_CLIENT, "BFD client data"); +DEFINE_MTYPE(BFDD, BFDD_CLIENT_NOTIFICATION, "BFD client notification data"); /* Master of threads. */ struct event_loop *master; @@ -67,9 +67,6 @@ static void sigterm_handler(void) /* Stop receiving message from zebra. */ bfdd_zclient_stop(); - /* Shutdown controller to avoid receiving anymore commands. */ - control_shutdown(); - /* Shutdown and free all protocol related memory. */ bfd_shutdown(); @@ -132,10 +129,8 @@ FRR_DAEMON_INFO(bfdd, BFD, ); /* clang-format on */ -#define OPTION_CTLSOCK 1001 #define OPTION_DPLANEADDR 2000 static const struct option longopts[] = { - {"bfdctl", required_argument, NULL, OPTION_CTLSOCK}, {"dplaneaddr", required_argument, NULL, OPTION_DPLANEADDR}, {0} }; @@ -319,7 +314,6 @@ static void bg_init(void) .cap_num_i = 0, }; - TAILQ_INIT(&bglobal.bg_bcslist); TAILQ_INIT(&bglobal.bg_obslist); memcpy(&bglobal.bfdd_privs, &bfdd_privs, @@ -328,8 +322,7 @@ static void bg_init(void) int main(int argc, char *argv[]) { - char ctl_path[512], dplane_addr[512]; - bool ctlsockused = false; + char dplane_addr[512]; int opt; bglobal.bg_use_dplane = false; @@ -339,7 +332,6 @@ int main(int argc, char *argv[]) frr_preinit(&bfdd_di, argc, argv); frr_opt_add("", longopts, - " --bfdctl Specify bfdd control socket\n" " --dplaneaddr Specify BFD data plane address\n"); while (true) { @@ -348,10 +340,6 @@ int main(int argc, char *argv[]) break; switch (opt) { - case OPTION_CTLSOCK: - strlcpy(ctl_path, optarg, sizeof(ctl_path)); - ctlsockused = true; - break; case OPTION_DPLANEADDR: strlcpy(dplane_addr, optarg, sizeof(dplane_addr)); bglobal.bg_use_dplane = true; @@ -362,15 +350,9 @@ int main(int argc, char *argv[]) } } - if (!ctlsockused) - snprintf(ctl_path, sizeof(ctl_path), BFDD_SOCK_NAME); - /* Initialize FRR infrastructure. */ master = frr_init(); - /* Initialize control socket. */ - control_init(ctl_path); - /* Initialize BFD data structures. */ bfd_initialize(); @@ -381,9 +363,6 @@ int main(int argc, char *argv[]) /* Initialize zebra connection. */ bfdd_zclient_init(&bglobal.bfdd_privs); - event_add_read(master, control_accept, NULL, bglobal.bg_csock, - &bglobal.bg_csockev); - /* Install commands. */ bfdd_vty_init(); diff --git a/bfdd/bfdd_vty.c b/bfdd/bfdd_vty.c index 496d5019b..26554e149 100644 --- a/bfdd/bfdd_vty.c +++ b/bfdd/bfdd_vty.c @@ -84,9 +84,6 @@ static void _display_peer_header(struct vty *vty, struct bfd_session *bs) if (bs->key.ifname[0]) vty_out(vty, " interface %s", bs->key.ifname); vty_out(vty, "\n"); - - if (bs->pl) - vty_out(vty, "\t\tlabel: %s\n", bs->pl->pl_label); } static void _display_peer(struct vty *vty, struct bfd_session *bs) @@ -200,9 +197,6 @@ static struct json_object *_peer_json_header(struct bfd_session *bs) if (bs->key.ifname[0]) json_object_string_add(jo, "interface", bs->key.ifname); - if (bs->pl) - json_object_string_add(jo, "label", bs->pl->pl_label); - return jo; } @@ -561,17 +555,11 @@ _find_peer_or_error(struct vty *vty, int argc, struct cmd_token **argv, int idx; bool mhop; struct bfd_session *bs = NULL; - struct peer_label *pl; struct bfd_peer_cfg bpc; struct sockaddr_any psa, lsa, *lsap; char errormsg[128]; - /* Look up the BFD peer. */ - if (label) { - pl = pl_find(label); - if (pl) - bs = pl->pl_bs; - } else if (peer_str) { + if (peer_str) { strtosa(peer_str, &psa); if (local_str) { strtosa(local_str, &lsa); @@ -879,7 +867,6 @@ static int bfd_configure_peer(struct bfd_peer_cfg *bpc, bool mhop, bpc->bpc_txinterval = BPC_DEF_TRANSMITINTERVAL; bpc->bpc_echorecvinterval = BPC_DEF_ECHORECEIVEINTERVAL; bpc->bpc_echotxinterval = BPC_DEF_ECHOTRANSMITINTERVAL; - bpc->bpc_lastevent = monotime(NULL); /* Safety check: when no error buf is provided len must be zero. */ if (ebuf == NULL) diff --git a/bfdd/config.c b/bfdd/config.c deleted file mode 100644 index 22d7d7dee..000000000 --- a/bfdd/config.c +++ /dev/null @@ -1,592 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/********************************************************************* - * Copyright 2017-2018 Network Device Education Foundation, Inc. ("NetDEF") - * - * config.c: implements the BFD daemon configuration handling. - * - * Authors - * ------- - * Rafael Zalamena <rzalamena@opensourcerouting.org> - */ - -#include <zebra.h> - -#include <string.h> - -#include "lib/json.h" - -#include "bfd.h" - -DEFINE_MTYPE_STATIC(BFDD, BFDD_LABEL, "long-lived label memory"); - -/* - * Definitions - */ -enum peer_list_type { - PLT_IPV4, - PLT_IPV6, - PLT_LABEL, -}; - - -/* - * Prototypes - */ -static int parse_config_json(struct json_object *jo, bpc_handle h, void *arg); -static int parse_list(struct json_object *jo, enum peer_list_type plt, - bpc_handle h, void *arg); -static int parse_peer_config(struct json_object *jo, struct bfd_peer_cfg *bpc); -static int parse_peer_label_config(struct json_object *jo, - struct bfd_peer_cfg *bpc); - -static int config_add(struct bfd_peer_cfg *bpc, void *arg); -static int config_del(struct bfd_peer_cfg *bpc, void *arg); - -static int json_object_add_peer(struct json_object *jo, struct bfd_session *bs); - - -/* - * Implementation - */ -static int config_add(struct bfd_peer_cfg *bpc, - void *arg __attribute__((unused))) -{ - return ptm_bfd_sess_new(bpc) == NULL; -} - -static int config_del(struct bfd_peer_cfg *bpc, - void *arg __attribute__((unused))) -{ - return ptm_bfd_sess_del(bpc) != 0; -} - -static int parse_config_json(struct json_object *jo, bpc_handle h, void *arg) -{ - const char *key, *sval; - struct json_object *jo_val; - struct json_object_iterator joi, join; - int error = 0; - - JSON_FOREACH (jo, joi, join) { - key = json_object_iter_peek_name(&joi); - jo_val = json_object_iter_peek_value(&joi); - - if (strcmp(key, "ipv4") == 0) { - error += parse_list(jo_val, PLT_IPV4, h, arg); - } else if (strcmp(key, "ipv6") == 0) { - error += parse_list(jo_val, PLT_IPV6, h, arg); - } else if (strcmp(key, "label") == 0) { - error += parse_list(jo_val, PLT_LABEL, h, arg); - } else { - sval = json_object_get_string(jo_val); - zlog_warn("%s:%d invalid configuration: %s", __func__, - __LINE__, sval); - error++; - } - } - - /* - * Our callers never call free() on json_object and only expect - * the return value, so lets free() it here. - */ - json_object_put(jo); - - return error; -} - -int parse_config(const char *fname) -{ - struct json_object *jo; - - jo = json_object_from_file(fname); - if (jo == NULL) - return -1; - - return parse_config_json(jo, config_add, NULL); -} - -static int parse_list(struct json_object *jo, enum peer_list_type plt, - bpc_handle h, void *arg) -{ - struct json_object *jo_val; - struct bfd_peer_cfg bpc; - int allen, idx; - int error = 0, result; - - allen = json_object_array_length(jo); - for (idx = 0; idx < allen; idx++) { - jo_val = json_object_array_get_idx(jo, idx); - - /* Set defaults. */ - memset(&bpc, 0, sizeof(bpc)); - bpc.bpc_detectmultiplier = BFD_DEFDETECTMULT; - bpc.bpc_recvinterval = BFD_DEFREQUIREDMINRX; - bpc.bpc_txinterval = BFD_DEFDESIREDMINTX; - bpc.bpc_echorecvinterval = BFD_DEF_REQ_MIN_ECHO_RX; - bpc.bpc_echotxinterval = BFD_DEF_DES_MIN_ECHO_TX; - - switch (plt) { - case PLT_IPV4: - zlog_debug("ipv4 peers %d:", allen); - bpc.bpc_ipv4 = true; - break; - case PLT_IPV6: - zlog_debug("ipv6 peers %d:", allen); - bpc.bpc_ipv4 = false; - break; - case PLT_LABEL: - zlog_debug("label peers %d:", allen); - if (parse_peer_label_config(jo_val, &bpc) != 0) { - error++; - continue; - } - break; - - default: - error++; - zlog_err("%s:%d: unsupported peer type", __func__, - __LINE__); - break; - } - - result = parse_peer_config(jo_val, &bpc); - error += result; - if (result == 0) - error += (h(&bpc, arg) != 0); - } - - return error; -} - -static int parse_peer_config(struct json_object *jo, struct bfd_peer_cfg *bpc) -{ - const char *key, *sval; - struct json_object *jo_val; - struct json_object_iterator joi, join; - int family_type = (bpc->bpc_ipv4) ? AF_INET : AF_INET6; - int error = 0; - - zlog_debug(" peer: %s", bpc->bpc_ipv4 ? "ipv4" : "ipv6"); - - JSON_FOREACH (jo, joi, join) { - key = json_object_iter_peek_name(&joi); - jo_val = json_object_iter_peek_value(&joi); - - if (strcmp(key, "multihop") == 0) { - bpc->bpc_mhop = json_object_get_boolean(jo_val); - zlog_debug(" multihop: %s", - bpc->bpc_mhop ? "true" : "false"); - } else if (strcmp(key, "peer-address") == 0) { - sval = json_object_get_string(jo_val); - if (strtosa(sval, &bpc->bpc_peer) != 0 - || bpc->bpc_peer.sa_sin.sin_family != family_type) { - zlog_debug( - "%s:%d failed to parse peer-address '%s'", - __func__, __LINE__, sval); - error++; - } - zlog_debug(" peer-address: %s", sval); - } else if (strcmp(key, "local-address") == 0) { - sval = json_object_get_string(jo_val); - if (strtosa(sval, &bpc->bpc_local) != 0 - || bpc->bpc_local.sa_sin.sin_family - != family_type) { - zlog_debug( - "%s:%d failed to parse local-address '%s'", - __func__, __LINE__, sval); - error++; - } - zlog_debug(" local-address: %s", sval); - } else if (strcmp(key, "local-interface") == 0) { - bpc->bpc_has_localif = true; - sval = json_object_get_string(jo_val); - if (strlcpy(bpc->bpc_localif, sval, - sizeof(bpc->bpc_localif)) - > sizeof(bpc->bpc_localif)) { - zlog_debug( - " local-interface: %s (truncated)", - sval); - error++; - } else { - zlog_debug(" local-interface: %s", sval); - } - } else if (strcmp(key, "vrf-name") == 0) { - bpc->bpc_has_vrfname = true; - sval = json_object_get_string(jo_val); - if (strlcpy(bpc->bpc_vrfname, sval, - sizeof(bpc->bpc_vrfname)) - > sizeof(bpc->bpc_vrfname)) { - zlog_debug(" vrf-name: %s (truncated)", - sval); - error++; - } else { - zlog_debug(" vrf-name: %s", sval); - } - } else if (strcmp(key, "detect-multiplier") == 0) { - bpc->bpc_detectmultiplier = - json_object_get_int64(jo_val); - bpc->bpc_has_detectmultiplier = true; - zlog_debug(" detect-multiplier: %u", - bpc->bpc_detectmultiplier); - } else if (strcmp(key, "receive-interval") == 0) { - bpc->bpc_recvinterval = json_object_get_int64(jo_val); - bpc->bpc_has_recvinterval = true; - zlog_debug(" receive-interval: %" PRIu64, - bpc->bpc_recvinterval); - } else if (strcmp(key, "transmit-interval") == 0) { - bpc->bpc_txinterval = json_object_get_int64(jo_val); - bpc->bpc_has_txinterval = true; - zlog_debug(" transmit-interval: %" PRIu64, - bpc->bpc_txinterval); - } else if (strcmp(key, "echo-receive-interval") == 0) { - bpc->bpc_echorecvinterval = json_object_get_int64(jo_val); - bpc->bpc_has_echorecvinterval = true; - zlog_debug(" echo-receive-interval: %" PRIu64, - bpc->bpc_echorecvinterval); - } else if (strcmp(key, "echo-transmit-interval") == 0) { - bpc->bpc_echotxinterval = json_object_get_int64(jo_val); - bpc->bpc_has_echotxinterval = true; - zlog_debug(" echo-transmit-interval: %" PRIu64, - bpc->bpc_echotxinterval); - } else if (strcmp(key, "create-only") == 0) { - bpc->bpc_createonly = json_object_get_boolean(jo_val); - zlog_debug(" create-only: %s", - bpc->bpc_createonly ? "true" : "false"); - } else if (strcmp(key, "shutdown") == 0) { - bpc->bpc_shutdown = json_object_get_boolean(jo_val); - zlog_debug(" shutdown: %s", - bpc->bpc_shutdown ? "true" : "false"); - } else if (strcmp(key, "echo-mode") == 0) { - bpc->bpc_echo = json_object_get_boolean(jo_val); - zlog_debug(" echo-mode: %s", - bpc->bpc_echo ? "true" : "false"); - } else if (strcmp(key, "label") == 0) { - bpc->bpc_has_label = true; - sval = json_object_get_string(jo_val); - if (strlcpy(bpc->bpc_label, sval, - sizeof(bpc->bpc_label)) - > sizeof(bpc->bpc_label)) { - zlog_debug(" label: %s (truncated)", - sval); - error++; - } else { - zlog_debug(" label: %s", sval); - } - } else { - sval = json_object_get_string(jo_val); - zlog_warn("%s:%d invalid configuration: '%s: %s'", - __func__, __LINE__, key, sval); - error++; - } - } - - if (bpc->bpc_peer.sa_sin.sin_family == 0) { - zlog_debug("%s:%d no peer address provided", __func__, - __LINE__); - error++; - } - - return error; -} - -static int parse_peer_label_config(struct json_object *jo, - struct bfd_peer_cfg *bpc) -{ - struct peer_label *pl; - struct json_object *label; - const char *sval; - - /* Get label and translate it to BFD daemon key. */ - if (!json_object_object_get_ex(jo, "label", &label)) - return 1; - - sval = json_object_get_string(label); - - pl = pl_find(sval); - if (pl == NULL) - return 1; - - zlog_debug(" peer-label: %s", sval); - - /* Translate the label into BFD address keys. */ - bs_to_bpc(pl->pl_bs, bpc); - - return 0; -} - - -/* - * Control socket JSON parsing. - */ -int config_request_add(const char *jsonstr) -{ - struct json_object *jo; - - jo = json_tokener_parse(jsonstr); - if (jo == NULL) - return -1; - - return parse_config_json(jo, config_add, NULL); -} - -int config_request_del(const char *jsonstr) -{ - struct json_object *jo; - - jo = json_tokener_parse(jsonstr); - if (jo == NULL) - return -1; - - return parse_config_json(jo, config_del, NULL); -} - -char *config_response(const char *status, const char *error) -{ - struct json_object *resp, *jo; - char *jsonstr; - - resp = json_object_new_object(); - if (resp == NULL) - return NULL; - - /* Add 'status' response key. */ - jo = json_object_new_string(status); - if (jo == NULL) { - json_object_put(resp); - return NULL; - } - - json_object_object_add(resp, "status", jo); - - /* Add 'error' response key. */ - if (error != NULL) { - jo = json_object_new_string(error); - if (jo == NULL) { - json_object_put(resp); - return NULL; - } - - json_object_object_add(resp, "error", jo); - } - - /* Generate JSON response. */ - jsonstr = XSTRDUP( - MTYPE_BFDD_NOTIFICATION, - json_object_to_json_string_ext(resp, BFDD_JSON_CONV_OPTIONS)); - json_object_put(resp); - - return jsonstr; -} - -char *config_notify(struct bfd_session *bs) -{ - struct json_object *resp; - char *jsonstr; - time_t now; - - resp = json_object_new_object(); - if (resp == NULL) - return NULL; - - json_object_string_add(resp, "op", BCM_NOTIFY_PEER_STATUS); - - json_object_add_peer(resp, bs); - - /* Add status information */ - json_object_int_add(resp, "id", bs->discrs.my_discr); - json_object_int_add(resp, "remote-id", bs->discrs.my_discr); - - switch (bs->ses_state) { - case PTM_BFD_UP: - json_object_string_add(resp, "state", "up"); - - now = monotime(NULL); - json_object_int_add(resp, "uptime", now - bs->uptime.tv_sec); - break; - case PTM_BFD_ADM_DOWN: - json_object_string_add(resp, "state", "adm-down"); - break; - case PTM_BFD_DOWN: - json_object_string_add(resp, "state", "down"); - - now = monotime(NULL); - json_object_int_add(resp, "downtime", - now - bs->downtime.tv_sec); - break; - case PTM_BFD_INIT: - json_object_string_add(resp, "state", "init"); - break; - - default: - json_object_string_add(resp, "state", "unknown"); - break; - } - - json_object_int_add(resp, "diagnostics", bs->local_diag); - json_object_int_add(resp, "remote-diagnostics", bs->remote_diag); - - /* Generate JSON response. */ - jsonstr = XSTRDUP( - MTYPE_BFDD_NOTIFICATION, - json_object_to_json_string_ext(resp, BFDD_JSON_CONV_OPTIONS)); - json_object_put(resp); - - return jsonstr; -} - -char *config_notify_config(const char *op, struct bfd_session *bs) -{ - struct json_object *resp; - char *jsonstr; - - resp = json_object_new_object(); - if (resp == NULL) - return NULL; - - json_object_string_add(resp, "op", op); - - json_object_add_peer(resp, bs); - - /* On peer deletion we don't need to add any additional information. */ - if (strcmp(op, BCM_NOTIFY_CONFIG_DELETE) == 0) - goto skip_config; - - json_object_int_add(resp, "detect-multiplier", bs->detect_mult); - json_object_int_add(resp, "receive-interval", - bs->timers.required_min_rx / 1000); - json_object_int_add(resp, "transmit-interval", - bs->timers.desired_min_tx / 1000); - json_object_int_add(resp, "echo-receive-interval", - bs->timers.required_min_echo_rx / 1000); - json_object_int_add(resp, "echo-transmit-interval", - bs->timers.desired_min_echo_tx / 1000); - - json_object_int_add(resp, "remote-detect-multiplier", - bs->remote_detect_mult); - json_object_int_add(resp, "remote-receive-interval", - bs->remote_timers.required_min_rx / 1000); - json_object_int_add(resp, "remote-transmit-interval", - bs->remote_timers.desired_min_tx / 1000); - json_object_int_add(resp, "remote-echo-receive-interval", - bs->remote_timers.required_min_echo / 1000); - - if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO)) - json_object_boolean_true_add(resp, "echo-mode"); - else - json_object_boolean_false_add(resp, "echo-mode"); - - if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN)) - json_object_boolean_true_add(resp, "shutdown"); - else - json_object_boolean_false_add(resp, "shutdown"); - -skip_config: - /* Generate JSON response. */ - jsonstr = XSTRDUP( - MTYPE_BFDD_NOTIFICATION, - json_object_to_json_string_ext(resp, BFDD_JSON_CONV_OPTIONS)); - json_object_put(resp); - - return jsonstr; -} - -int config_notify_request(struct bfd_control_socket *bcs, const char *jsonstr, - bpc_handle bh) -{ - struct json_object *jo; - - jo = json_tokener_parse(jsonstr); - if (jo == NULL) - return -1; - - return parse_config_json(jo, bh, bcs); -} - -static int json_object_add_peer(struct json_object *jo, struct bfd_session *bs) -{ - char addr_buf[INET6_ADDRSTRLEN]; - - /* Add peer 'key' information. */ - if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_IPV6)) - json_object_boolean_true_add(jo, "ipv6"); - else - json_object_boolean_false_add(jo, "ipv6"); - - if (CHECK_FLAG(bs->flags, BFD_SESS_FLAG_MH)) { - json_object_boolean_true_add(jo, "multihop"); - json_object_string_add(jo, "peer-address", - inet_ntop(bs->key.family, &bs->key.peer, - addr_buf, sizeof(addr_buf))); - json_object_string_add(jo, "local-address", - inet_ntop(bs->key.family, &bs->key.local, - addr_buf, sizeof(addr_buf))); - if (bs->key.vrfname[0]) - json_object_string_add(jo, "vrf-name", bs->key.vrfname); - } else { - json_object_boolean_false_add(jo, "multihop"); - json_object_string_add(jo, "peer-address", - inet_ntop(bs->key.family, &bs->key.peer, - addr_buf, sizeof(addr_buf))); - if (memcmp(&bs->key.local, &zero_addr, sizeof(bs->key.local))) - json_object_string_add( - jo, "local-address", - inet_ntop(bs->key.family, &bs->key.local, - addr_buf, sizeof(addr_buf))); - if (bs->key.ifname[0]) - json_object_string_add(jo, "local-interface", - bs->key.ifname); - } - - if (bs->pl) - json_object_string_add(jo, "label", bs->pl->pl_label); - - return 0; -} - - -/* - * Label handling - */ -struct peer_label *pl_find(const char *label) -{ - struct peer_label *pl; - - TAILQ_FOREACH (pl, &bglobal.bg_pllist, pl_entry) { - if (strcmp(pl->pl_label, label) != 0) - continue; - - return pl; - } - - return NULL; -} - -struct peer_label *pl_new(const char *label, struct bfd_session *bs) -{ - struct peer_label *pl; - - pl = XCALLOC(MTYPE_BFDD_LABEL, sizeof(*pl)); - - if (strlcpy(pl->pl_label, label, sizeof(pl->pl_label)) - > sizeof(pl->pl_label)) - zlog_warn("%s:%d: label was truncated", __func__, __LINE__); - - pl->pl_bs = bs; - bs->pl = pl; - - TAILQ_INSERT_HEAD(&bglobal.bg_pllist, pl, pl_entry); - - return pl; -} - -void pl_free(struct peer_label *pl) -{ - if (pl == NULL) - return; - - /* Remove the pointer back. */ - pl->pl_bs->pl = NULL; - - TAILQ_REMOVE(&bglobal.bg_pllist, pl, pl_entry); - XFREE(MTYPE_BFDD_LABEL, pl); -} diff --git a/bfdd/control.c b/bfdd/control.c deleted file mode 100644 index 98fd813ef..000000000 --- a/bfdd/control.c +++ /dev/null @@ -1,844 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/********************************************************************* - * Copyright 2017-2018 Network Device Education Foundation, Inc. ("NetDEF") - * - * control.c: implements the BFD daemon control socket. It will be used - * to talk with clients daemon/scripts/consumers. - * - * Authors - * ------- - * Rafael Zalamena <rzalamena@opensourcerouting.org> - */ - -#include <zebra.h> - -#include <fcntl.h> -#include <sys/stat.h> - -#include <sys/un.h> - -#include "bfd.h" - -/* - * Prototypes - */ -static int sock_set_nonblock(int fd); -struct bfd_control_queue *control_queue_new(struct bfd_control_socket *bcs); -static void control_queue_free(struct bfd_control_socket *bcs, - struct bfd_control_queue *bcq); -static int control_queue_dequeue(struct bfd_control_socket *bcs); -static int control_queue_enqueue(struct bfd_control_socket *bcs, - struct bfd_control_msg *bcm); -static int control_queue_enqueue_first(struct bfd_control_socket *bcs, - struct bfd_control_msg *bcm); -struct bfd_notify_peer *control_notifypeer_new(struct bfd_control_socket *bcs, - struct bfd_session *bs); -static void control_notifypeer_free(struct bfd_control_socket *bcs, - struct bfd_notify_peer *bnp); -struct bfd_notify_peer *control_notifypeer_find(struct bfd_control_socket *bcs, - struct bfd_session *bs); - - -struct bfd_control_socket *control_new(int sd); -static void control_free(struct bfd_control_socket *bcs); -static void control_reset_buf(struct bfd_control_buffer *bcb); -static void control_read(struct event *t); -static void control_write(struct event *t); - -static void control_handle_request_add(struct bfd_control_socket *bcs, - struct bfd_control_msg *bcm); -static void control_handle_request_del(struct bfd_control_socket *bcs, - struct bfd_control_msg *bcm); -static int notify_add_cb(struct bfd_peer_cfg *bpc, void *arg); -static int notify_del_cb(struct bfd_peer_cfg *bpc, void *arg); -static void control_handle_notify_add(struct bfd_control_socket *bcs, - struct bfd_control_msg *bcm); -static void control_handle_notify_del(struct bfd_control_socket *bcs, - struct bfd_control_msg *bcm); -static void _control_handle_notify(struct hash_bucket *hb, void *arg); -static void control_handle_notify(struct bfd_control_socket *bcs, - struct bfd_control_msg *bcm); -static void control_response(struct bfd_control_socket *bcs, uint16_t id, - const char *status, const char *error); - -static void _control_notify_config(struct bfd_control_socket *bcs, - const char *op, struct bfd_session *bs); -static void _control_notify(struct bfd_control_socket *bcs, - struct bfd_session *bs); - - -/* - * Functions - */ -static int sock_set_nonblock(int fd) -{ - int flags; - - flags = fcntl(fd, F_GETFL, 0); - if (flags == -1) { - zlog_warn("%s: fcntl F_GETFL: %s", __func__, strerror(errno)); - return -1; - } - - flags |= O_NONBLOCK; - if (fcntl(fd, F_SETFL, flags) == -1) { - zlog_warn("%s: fcntl F_SETFL: %s", __func__, strerror(errno)); - return -1; - } - - return 0; -} - -int control_init(const char *path) -{ - int sd; - mode_t umval; - struct sockaddr_un sun_ = { - .sun_family = AF_UNIX, - }; - - assert(path); - - strlcpy(sun_.sun_path, path, sizeof(sun_.sun_path)); - - /* Remove previously created sockets. */ - unlink(sun_.sun_path); - - sd = socket(AF_UNIX, SOCK_STREAM, PF_UNSPEC); - if (sd == -1) { - zlog_err("%s: socket: %s", __func__, strerror(errno)); - return -1; - } - - umval = umask(0); - if (bind(sd, (struct sockaddr *)&sun_, sizeof(sun_)) == -1) { - zlog_err("%s: bind: %s", __func__, strerror(errno)); - close(sd); - return -1; - } - umask(umval); - - if (listen(sd, SOMAXCONN) == -1) { - zlog_err("%s: listen: %s", __func__, strerror(errno)); - close(sd); - return -1; - } - - sock_set_nonblock(sd); - - bglobal.bg_csock = sd; - - return 0; -} - -void control_shutdown(void) -{ - struct bfd_control_socket *bcs; - - event_cancel(&bglobal.bg_csockev); - - socket_close(&bglobal.bg_csock); - - while (!TAILQ_EMPTY(&bglobal.bg_bcslist)) { - bcs = TAILQ_FIRST(&bglobal.bg_bcslist); - control_free(bcs); - } -} - -void control_accept(struct event *t) -{ - int csock, sd = EVENT_FD(t); - - csock = accept(sd, NULL, 0); - if (csock == -1) { - zlog_warn("%s: accept: %s", __func__, strerror(errno)); - return; - } - - control_new(csock); - - event_add_read(master, control_accept, NULL, sd, &bglobal.bg_csockev); -} - - -/* - * Client handling - */ -struct bfd_control_socket *control_new(int sd) -{ - struct bfd_control_socket *bcs; - - bcs = XCALLOC(MTYPE_BFDD_CONTROL, sizeof(*bcs)); - - /* Disable notifications by default. */ - bcs->bcs_notify = 0; - - bcs->bcs_sd = sd; - event_add_read(master, control_read, bcs, sd, &bcs->bcs_ev); - - TAILQ_INIT(&bcs->bcs_bcqueue); - TAILQ_INIT(&bcs->bcs_bnplist); - TAILQ_INSERT_TAIL(&bglobal.bg_bcslist, bcs, bcs_entry); - - return bcs; -} - -static void control_free(struct bfd_control_socket *bcs) -{ - struct bfd_control_queue *bcq; - struct bfd_notify_peer *bnp; - - event_cancel(&(bcs->bcs_ev)); - event_cancel(&(bcs->bcs_outev)); - - close(bcs->bcs_sd); - - TAILQ_REMOVE(&bglobal.bg_bcslist, bcs, bcs_entry); - - /* Empty output queue. */ - while (!TAILQ_EMPTY(&bcs->bcs_bcqueue)) { - bcq = TAILQ_FIRST(&bcs->bcs_bcqueue); - control_queue_free(bcs, bcq); - } - - /* Empty notification list. */ - while (!TAILQ_EMPTY(&bcs->bcs_bnplist)) { - bnp = TAILQ_FIRST(&bcs->bcs_bnplist); - control_notifypeer_free(bcs, bnp); - } - - control_reset_buf(&bcs->bcs_bin); - XFREE(MTYPE_BFDD_CONTROL, bcs); -} - -struct bfd_notify_peer *control_notifypeer_new(struct bfd_control_socket *bcs, - struct bfd_session *bs) -{ - struct bfd_notify_peer *bnp; - - bnp = control_notifypeer_find(bcs, bs); - if (bnp) - return bnp; - - bnp = XCALLOC(MTYPE_BFDD_CONTROL, sizeof(*bnp)); - - TAILQ_INSERT_TAIL(&bcs->bcs_bnplist, bnp, bnp_entry); - bnp->bnp_bs = bs; - bs->refcount++; - - return bnp; -} - -static void control_notifypeer_free(struct bfd_control_socket *bcs, - struct bfd_notify_peer *bnp) -{ - TAILQ_REMOVE(&bcs->bcs_bnplist, bnp, bnp_entry); - bnp->bnp_bs->refcount--; - XFREE(MTYPE_BFDD_CONTROL, bnp); -} - -struct bfd_notify_peer *control_notifypeer_find(struct bfd_control_socket *bcs, - struct bfd_session *bs) -{ - struct bfd_notify_peer *bnp; - - TAILQ_FOREACH (bnp, &bcs->bcs_bnplist, bnp_entry) { - if (bnp->bnp_bs == bs) - return bnp; - } - - return NULL; -} - -struct bfd_control_queue *control_queue_new(struct bfd_control_socket *bcs) -{ - struct bfd_control_queue *bcq; - - bcq = XCALLOC(MTYPE_BFDD_NOTIFICATION, sizeof(*bcq)); - - control_reset_buf(&bcq->bcq_bcb); - TAILQ_INSERT_TAIL(&bcs->bcs_bcqueue, bcq, bcq_entry); - - return bcq; -} - -static void control_queue_free(struct bfd_control_socket *bcs, - struct bfd_control_queue *bcq) -{ - control_reset_buf(&bcq->bcq_bcb); - TAILQ_REMOVE(&bcs->bcs_bcqueue, bcq, bcq_entry); - XFREE(MTYPE_BFDD_NOTIFICATION, bcq); -} - -static int control_queue_dequeue(struct bfd_control_socket *bcs) -{ - struct bfd_control_queue *bcq; - - /* List is empty, nothing to do. */ - if (TAILQ_EMPTY(&bcs->bcs_bcqueue)) - goto empty_list; - - bcq = TAILQ_FIRST(&bcs->bcs_bcqueue); - control_queue_free(bcs, bcq); - - /* Get the next buffer to send. */ - if (TAILQ_EMPTY(&bcs->bcs_bcqueue)) - goto empty_list; - - bcq = TAILQ_FIRST(&bcs->bcs_bcqueue); - bcs->bcs_bout = &bcq->bcq_bcb; - - bcs->bcs_outev = NULL; - event_add_write(master, control_write, bcs, bcs->bcs_sd, - &bcs->bcs_outev); - - return 1; - -empty_list: - event_cancel(&(bcs->bcs_outev)); - bcs->bcs_bout = NULL; - return 0; -} - -static int control_queue_enqueue(struct bfd_control_socket *bcs, - struct bfd_control_msg *bcm) -{ - struct bfd_control_queue *bcq; - struct bfd_control_buffer *bcb; - - bcq = control_queue_new(bcs); - - bcb = &bcq->bcq_bcb; - bcb->bcb_left = sizeof(struct bfd_control_msg) + ntohl(bcm->bcm_length); - bcb->bcb_pos = 0; - bcb->bcb_bcm = bcm; - - /* If this is the first item, then dequeue and start using it. */ - if (bcs->bcs_bout == NULL) { - bcs->bcs_bout = bcb; - - /* New messages, active write events. */ - event_add_write(master, control_write, bcs, bcs->bcs_sd, - &bcs->bcs_outev); - } - - return 0; -} - -static int control_queue_enqueue_first(struct bfd_control_socket *bcs, - struct bfd_control_msg *bcm) -{ - struct bfd_control_queue *bcq, *bcqn; - struct bfd_control_buffer *bcb; - - /* Enqueue it somewhere. */ - if (control_queue_enqueue(bcs, bcm) == -1) - return -1; - - /* - * The item is either the first or the last. So we must first - * check the best case where the item is already the first. - */ - bcq = TAILQ_FIRST(&bcs->bcs_bcqueue); - bcb = &bcq->bcq_bcb; - if (bcm == bcb->bcb_bcm) - return 0; - - /* - * The item was not the first, so it is the last. We'll try to - * assign it to the head of the queue, however if there is a - * transfer in progress, then we have to make the item as the - * next one. - * - * Interrupting the transfer of in progress message will cause - * the client to lose track of the message position/data. - */ - bcqn = TAILQ_LAST(&bcs->bcs_bcqueue, bcqueue); - TAILQ_REMOVE(&bcs->bcs_bcqueue, bcqn, bcq_entry); - if (bcb->bcb_pos != 0) { - /* - * First position is already being sent, insert into - * second position. - */ - TAILQ_INSERT_AFTER(&bcs->bcs_bcqueue, bcq, bcqn, bcq_entry); - } else { - /* - * Old message didn't start being sent, we still have - * time to put this one in the head of the queue. - */ - TAILQ_INSERT_HEAD(&bcs->bcs_bcqueue, bcqn, bcq_entry); - bcb = &bcqn->bcq_bcb; - bcs->bcs_bout = bcb; - } - - return 0; -} - -static void control_reset_buf(struct bfd_control_buffer *bcb) -{ - /* Get ride of old data. */ - XFREE(MTYPE_BFDD_NOTIFICATION, bcb->bcb_buf); - bcb->bcb_pos = 0; - bcb->bcb_left = 0; -} - -static void control_read(struct event *t) -{ - struct bfd_control_socket *bcs = EVENT_ARG(t); - struct bfd_control_buffer *bcb = &bcs->bcs_bin; - int sd = bcs->bcs_sd; - struct bfd_control_msg bcm; - ssize_t bread; - size_t plen; - - /* - * Check if we have already downloaded message content, if so then skip - * to - * download the rest of it and process. - * - * Otherwise download a new message header and allocate the necessary - * memory. - */ - if (bcb->bcb_buf != NULL) - goto skip_header; - - bread = read(sd, &bcm, sizeof(bcm)); - if (bread == 0) { - control_free(bcs); - return; - } - if (bread < 0) { - if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) - goto schedule_next_read; - - zlog_warn("%s: read: %s", __func__, strerror(errno)); - control_free(bcs); - return; - } - - /* Validate header fields. */ - plen = ntohl(bcm.bcm_length); - if (plen < 2) { - zlog_debug("%s: client closed due small message length: %d", - __func__, bcm.bcm_length); - control_free(bcs); - return; - } - -#define FRR_BFD_MAXLEN 10 * 1024 - - if (plen > FRR_BFD_MAXLEN) { - zlog_debug("%s: client closed, invalid message length: %d", - __func__, bcm.bcm_length); - control_free(bcs); - return; - } - - if (bcm.bcm_ver != BMV_VERSION_1) { - zlog_debug("%s: client closed due bad version: %d", __func__, - bcm.bcm_ver); - control_free(bcs); - return; - } - - /* Prepare the buffer to load the message. */ - bcs->bcs_version = bcm.bcm_ver; - bcs->bcs_type = bcm.bcm_type; - - bcb->bcb_pos = sizeof(bcm); - bcb->bcb_left = plen; - bcb->bcb_buf = XMALLOC(MTYPE_BFDD_NOTIFICATION, - sizeof(bcm) + bcb->bcb_left + 1); - if (bcb->bcb_buf == NULL) { - zlog_warn("%s: not enough memory for message size: %zu", - __func__, bcb->bcb_left); - control_free(bcs); - return; - } - - memcpy(bcb->bcb_buf, &bcm, sizeof(bcm)); - - /* Terminate data string with NULL for later processing. */ - bcb->bcb_buf[sizeof(bcm) + bcb->bcb_left] = 0; - -skip_header: - /* Download the remaining data of the message and process it. */ - bread = read(sd, &bcb->bcb_buf[bcb->bcb_pos], bcb->bcb_left); - if (bread == 0) { - control_free(bcs); - return; - } - if (bread < 0) { - if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) - goto schedule_next_read; - - zlog_warn("%s: read: %s", __func__, strerror(errno)); - control_free(bcs); - return; - } - - bcb->bcb_pos += bread; - bcb->bcb_left -= bread; - /* We need more data, return to wait more. */ - if (bcb->bcb_left > 0) - goto schedule_next_read; - - switch (bcb->bcb_bcm->bcm_type) { - case BMT_REQUEST_ADD: - control_handle_request_add(bcs, bcb->bcb_bcm); - break; - case BMT_REQUEST_DEL: - control_handle_request_del(bcs, bcb->bcb_bcm); - break; - case BMT_NOTIFY: - control_handle_notify(bcs, bcb->bcb_bcm); - break; - case BMT_NOTIFY_ADD: - control_handle_notify_add(bcs, bcb->bcb_bcm); - break; - case BMT_NOTIFY_DEL: - control_handle_notify_del(bcs, bcb->bcb_bcm); - break; - - default: - zlog_debug("%s: unhandled message type: %d", __func__, - bcb->bcb_bcm->bcm_type); - control_response(bcs, bcb->bcb_bcm->bcm_id, BCM_RESPONSE_ERROR, - "invalid message type"); - break; - } - - bcs->bcs_version = 0; - bcs->bcs_type = 0; - control_reset_buf(bcb); - -schedule_next_read: - bcs->bcs_ev = NULL; - event_add_read(master, control_read, bcs, sd, &bcs->bcs_ev); -} - -static void control_write(struct event *t) -{ - struct bfd_control_socket *bcs = EVENT_ARG(t); - struct bfd_control_buffer *bcb = bcs->bcs_bout; - int sd = bcs->bcs_sd; - ssize_t bwrite; - - bwrite = write(sd, &bcb->bcb_buf[bcb->bcb_pos], bcb->bcb_left); - if (bwrite == 0) { - control_free(bcs); - return; - } - if (bwrite < 0) { - if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { - bcs->bcs_outev = NULL; - event_add_write(master, control_write, bcs, bcs->bcs_sd, - &bcs->bcs_outev); - return; - } - - zlog_warn("%s: write: %s", __func__, strerror(errno)); - control_free(bcs); - return; - } - - bcb->bcb_pos += bwrite; - bcb->bcb_left -= bwrite; - if (bcb->bcb_left > 0) { - bcs->bcs_outev = NULL; - event_add_write(master, control_write, bcs, bcs->bcs_sd, - &bcs->bcs_outev); - return; - } - - control_queue_dequeue(bcs); -} - - -/* - * Message processing - */ -static void control_handle_request_add(struct bfd_control_socket *bcs, - struct bfd_control_msg *bcm) -{ - const char *json = (const char *)bcm->bcm_data; - - if (config_request_add(json) == 0) - control_response(bcs, bcm->bcm_id, BCM_RESPONSE_OK, NULL); - else - control_response(bcs, bcm->bcm_id, BCM_RESPONSE_ERROR, - "request add failed"); -} - -static void control_handle_request_del(struct bfd_control_socket *bcs, - struct bfd_control_msg *bcm) -{ - const char *json = (const char *)bcm->bcm_data; - - if (config_request_del(json) == 0) - control_response(bcs, bcm->bcm_id, BCM_RESPONSE_OK, NULL); - else - control_response(bcs, bcm->bcm_id, BCM_RESPONSE_ERROR, - "request del failed"); -} - -static struct bfd_session *_notify_find_peer(struct bfd_peer_cfg *bpc) -{ - struct peer_label *pl; - - if (bpc->bpc_has_label) { - pl = pl_find(bpc->bpc_label); - if (pl) - return pl->pl_bs; - } - - return bs_peer_find(bpc); -} - -static void _control_handle_notify(struct hash_bucket *hb, void *arg) -{ - struct bfd_control_socket *bcs = arg; - struct bfd_session *bs = hb->data; - - /* Notify peer configuration. */ - if (bcs->bcs_notify & BCM_NOTIFY_CONFIG) - _control_notify_config(bcs, BCM_NOTIFY_CONFIG_ADD, bs); - - /* Notify peer status. */ - if (bcs->bcs_notify & BCM_NOTIFY_PEER_STATE) - _control_notify(bcs, bs); -} - -static void control_handle_notify(struct bfd_control_socket *bcs, - struct bfd_control_msg *bcm) -{ - memcpy(&bcs->bcs_notify, bcm->bcm_data, sizeof(bcs->bcs_notify)); - - control_response(bcs, bcm->bcm_id, BCM_RESPONSE_OK, NULL); - - /* - * If peer asked for notification configuration, send everything that - * was configured until the moment to sync up. - */ - if (bcs->bcs_notify & (BCM_NOTIFY_CONFIG | BCM_NOTIFY_PEER_STATE)) - bfd_id_iterate(_control_handle_notify, bcs); -} - -static int notify_add_cb(struct bfd_peer_cfg *bpc, void *arg) -{ - struct bfd_control_socket *bcs = arg; - struct bfd_session *bs = _notify_find_peer(bpc); - - if (bs == NULL) - return -1; - - control_notifypeer_new(bcs, bs); - - /* Notify peer status. */ - _control_notify(bcs, bs); - - return 0; -} - -static int notify_del_cb(struct bfd_peer_cfg *bpc, void *arg) -{ - struct bfd_control_socket *bcs = arg; - struct bfd_session *bs = _notify_find_peer(bpc); - struct bfd_notify_peer *bnp; - - if (bs == NULL) - return -1; - - bnp = control_notifypeer_find(bcs, bs); - if (bnp) - control_notifypeer_free(bcs, bnp); - - return 0; -} - -static void control_handle_notify_add(struct bfd_control_socket *bcs, - struct bfd_control_msg *bcm) -{ - const char *json = (const char *)bcm->bcm_data; - - if (config_notify_request(bcs, json, notify_add_cb) == 0) { - control_response(bcs, bcm->bcm_id, BCM_RESPONSE_OK, NULL); - return; - } - - control_response(bcs, bcm->bcm_id, BCM_RESPONSE_ERROR, - "failed to parse notify data"); -} - -static void control_handle_notify_del(struct bfd_control_socket *bcs, - struct bfd_control_msg *bcm) -{ - const char *json = (const char *)bcm->bcm_data; - - if (config_notify_request(bcs, json, notify_del_cb) == 0) { - control_response(bcs, bcm->bcm_id, BCM_RESPONSE_OK, NULL); - return; - } - - control_response(bcs, bcm->bcm_id, BCM_RESPONSE_ERROR, - "failed to parse notify data"); -} - - -/* - * Internal functions used by the BFD daemon. - */ -static void control_response(struct bfd_control_socket *bcs, uint16_t id, - const char *status, const char *error) -{ - struct bfd_control_msg *bcm; - char *jsonstr; - size_t jsonstrlen; - - /* Generate JSON response. */ - jsonstr = config_response(status, error); - if (jsonstr == NULL) { - zlog_warn("%s: config_response: failed to get JSON str", - __func__); - return; - } - - /* Allocate data and answer. */ - jsonstrlen = strlen(jsonstr); - bcm = XMALLOC(MTYPE_BFDD_NOTIFICATION, - sizeof(struct bfd_control_msg) + jsonstrlen); - - bcm->bcm_length = htonl(jsonstrlen); - bcm->bcm_ver = BMV_VERSION_1; - bcm->bcm_type = BMT_RESPONSE; - bcm->bcm_id = id; - memcpy(bcm->bcm_data, jsonstr, jsonstrlen); - XFREE(MTYPE_BFDD_NOTIFICATION, jsonstr); - - control_queue_enqueue_first(bcs, bcm); -} - -static void _control_notify(struct bfd_control_socket *bcs, - struct bfd_session *bs) -{ - struct bfd_control_msg *bcm; - char *jsonstr; - size_t jsonstrlen; - - /* Generate JSON response. */ - jsonstr = config_notify(bs); - if (jsonstr == NULL) { - zlog_warn("%s: config_notify: failed to get JSON str", - __func__); - return; - } - - /* Allocate data and answer. */ - jsonstrlen = strlen(jsonstr); - bcm = XMALLOC(MTYPE_BFDD_NOTIFICATION, - sizeof(struct bfd_control_msg) + jsonstrlen); - - bcm->bcm_length = htonl(jsonstrlen); - bcm->bcm_ver = BMV_VERSION_1; - bcm->bcm_type = BMT_NOTIFY; - bcm->bcm_id = htons(BCM_NOTIFY_ID); - memcpy(bcm->bcm_data, jsonstr, jsonstrlen); - XFREE(MTYPE_BFDD_NOTIFICATION, jsonstr); - - control_queue_enqueue(bcs, bcm); -} - -int control_notify(struct bfd_session *bs, uint8_t notify_state) -{ - struct bfd_control_socket *bcs; - struct bfd_notify_peer *bnp; - - /* Notify zebra listeners as well. */ - ptm_bfd_notify(bs, notify_state); - - /* - * PERFORMANCE: reuse the bfd_control_msg allocated data for - * all control sockets to avoid wasting memory. - */ - TAILQ_FOREACH (bcs, &bglobal.bg_bcslist, bcs_entry) { - /* - * Test for all notifications first, then search for - * specific peers. - */ - if ((bcs->bcs_notify & BCM_NOTIFY_PEER_STATE) == 0) { - bnp = control_notifypeer_find(bcs, bs); - /* - * If the notification is not configured here, - * don't send it. - */ - if (bnp == NULL) - continue; - } - - _control_notify(bcs, bs); - } - - return 0; -} - -static void _control_notify_config(struct bfd_control_socket *bcs, - const char *op, struct bfd_session *bs) -{ - struct bfd_control_msg *bcm; - char *jsonstr; - size_t jsonstrlen; - - /* Generate JSON response. */ - jsonstr = config_notify_config(op, bs); - if (jsonstr == NULL) { - zlog_warn("%s: config_notify_config: failed to get JSON str", - __func__); - return; - } - - /* Allocate data and answer. */ - jsonstrlen = strlen(jsonstr); - bcm = XMALLOC(MTYPE_BFDD_NOTIFICATION, - sizeof(struct bfd_control_msg) + jsonstrlen); - - bcm->bcm_length = htonl(jsonstrlen); - bcm->bcm_ver = BMV_VERSION_1; - bcm->bcm_type = BMT_NOTIFY; - bcm->bcm_id = htons(BCM_NOTIFY_ID); - memcpy(bcm->bcm_data, jsonstr, jsonstrlen); - XFREE(MTYPE_BFDD_NOTIFICATION, jsonstr); - - control_queue_enqueue(bcs, bcm); -} - -int control_notify_config(const char *op, struct bfd_session *bs) -{ - struct bfd_control_socket *bcs; - struct bfd_notify_peer *bnp; - - /* Remove the control sockets notification for this peer. */ - if (strcmp(op, BCM_NOTIFY_CONFIG_DELETE) == 0 && bs->refcount > 0) { - TAILQ_FOREACH (bcs, &bglobal.bg_bcslist, bcs_entry) { - bnp = control_notifypeer_find(bcs, bs); - if (bnp) - control_notifypeer_free(bcs, bnp); - } - } - - /* - * PERFORMANCE: reuse the bfd_control_msg allocated data for - * all control sockets to avoid wasting memory. - */ - TAILQ_FOREACH (bcs, &bglobal.bg_bcslist, bcs_entry) { - /* - * Test for all notifications first, then search for - * specific peers. - */ - if ((bcs->bcs_notify & BCM_NOTIFY_CONFIG) == 0) - continue; - - _control_notify_config(bcs, op, bs); - } - - return 0; -} diff --git a/bfdd/dplane.c b/bfdd/dplane.c index d8539812e..7f55f3407 100644 --- a/bfdd/dplane.c +++ b/bfdd/dplane.c @@ -354,7 +354,7 @@ bfd_dplane_session_state_change(struct bfd_dplane_ctx *bdc, bs->remote_timers.required_min_echo = ntohl(state->required_echo_rx); /* Notify and update counters. */ - control_notify(bs, bs->ses_state); + ptm_bfd_notify(bs, bs->ses_state); /* No state change. */ if (old_state == bs->ses_state) diff --git a/bfdd/ptm_adapter.c b/bfdd/ptm_adapter.c index b5ab2ef1d..f6ebefb7b 100644 --- a/bfdd/ptm_adapter.c +++ b/bfdd/ptm_adapter.c @@ -148,7 +148,6 @@ static void _ptm_bfd_session_del(struct bfd_session *bs, uint8_t diag) "ptm-del-session: [%s] session refcount is zero but it was configured by CLI", bs_to_string(bs)); } else { - control_notify_config(BCM_NOTIFY_CONFIG_DELETE, bs); bfd_session_free(bs); } } @@ -892,7 +891,7 @@ static struct ptm_client *pc_new(uint32_t pid) return pc; /* Allocate the client data and save it. */ - pc = XCALLOC(MTYPE_BFDD_CONTROL, sizeof(*pc)); + pc = XCALLOC(MTYPE_BFDD_CLIENT, sizeof(*pc)); pc->pc_pid = pid; TAILQ_INSERT_HEAD(&pcqueue, pc, pc_entry); @@ -910,7 +909,7 @@ static void pc_free(struct ptm_client *pc) pcn_free(pcn); } - XFREE(MTYPE_BFDD_CONTROL, pc); + XFREE(MTYPE_BFDD_CLIENT, pc); } static void pc_free_all(void) @@ -934,7 +933,7 @@ static struct ptm_client_notification *pcn_new(struct ptm_client *pc, return pcn; /* Save the client notification data. */ - pcn = XCALLOC(MTYPE_BFDD_NOTIFICATION, sizeof(*pcn)); + pcn = XCALLOC(MTYPE_BFDD_CLIENT_NOTIFICATION, sizeof(*pcn)); TAILQ_INSERT_HEAD(&pc->pc_pcnqueue, pcn, pcn_entry); pcn->pcn_pc = pc; @@ -982,5 +981,5 @@ static void pcn_free(struct ptm_client_notification *pcn) pcn->pcn_pc = NULL; TAILQ_REMOVE(&pc->pc_pcnqueue, pcn, pcn_entry); - XFREE(MTYPE_BFDD_NOTIFICATION, pcn); + XFREE(MTYPE_BFDD_CLIENT_NOTIFICATION, pcn); } diff --git a/bfdd/subdir.am b/bfdd/subdir.am index b86a18967..5d2d8fda5 100644 --- a/bfdd/subdir.am +++ b/bfdd/subdir.am @@ -17,8 +17,6 @@ bfdd_libbfd_a_SOURCES = \ bfdd/bfdd_vty.c \ bfdd/bfdd_cli.c \ bfdd/bfd_packet.c \ - bfdd/config.c \ - bfdd/control.c \ bfdd/dplane.c \ bfdd/event.c \ bfdd/ptm_adapter.c \ @@ -37,7 +35,6 @@ clippy_scan += \ # end noinst_HEADERS += \ - bfdd/bfdctl.h \ bfdd/bfdd_nb.h \ bfdd/bfd.h \ # end |