From 990e89e5edcc096527f291353289036aed3985a3 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Sat, 18 May 2019 15:58:20 -0300 Subject: [PATCH 01/21] yang: import BFD yang model New yang model to support the BFD session configuration. Signed-off-by: Rafael Zalamena --- yang/frr-bfdd.yang | 387 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 387 insertions(+) create mode 100644 yang/frr-bfdd.yang diff --git a/yang/frr-bfdd.yang b/yang/frr-bfdd.yang new file mode 100644 index 0000000000..4fb857e6d1 --- /dev/null +++ b/yang/frr-bfdd.yang @@ -0,0 +1,387 @@ +module frr-bfdd { + yang-version 1.1; + namespace "http://frrouting.org/yang/bfdd"; + prefix frr-bfdd; + + import ietf-inet-types { + prefix inet; + } + import ietf-yang-types { + prefix yang; + } + import frr-interface { + prefix frr-interface; + } + import frr-route-types { + prefix frr-route-types; + } + + organization "Free Range Routing"; + contact + "FRR Users List: + FRR Development List: "; + description + "This module defines a model for managing FRR bfdd daemon."; + + revision 2019-05-09 { + description "Initial revision."; + reference + "RFC 5880: Bidirectional Forwarding Detection (BFD). + RFC 5881: Bidirectional Forwarding Detection (BFD) + for IPv4 and IPv6 (Single Hop). + RFC 5882: Bidirectional Forwarding Detection (BFD) for Multihop Paths."; + } + + + /* + * BFD types declaration. + */ + typedef multiplier { + description "Detection multiplier"; + type uint8 { + range 2..255; + } + } + + typedef discriminator { + description "BFD session identification"; + type uint32 { + range 1..4294967295; + } + } + + typedef state { + description "BFD session state"; + type enumeration { + enum admin-down { + value 0; + description "Administratively down"; + } + enum down { + value 1; + description "Down"; + } + enum init { + value 2; + description "Initializing"; + } + enum up { + value 3; + description "Up"; + } + } + } + + typedef diagnostic { + description "BFD session diagnostic"; + type enumeration { + enum ok { + value 0; + description "Ok"; + } + enum control-expired { + value 1; + description "Control timer expired"; + } + enum echo-failed { + value 2; + description "Echo function failed"; + } + enum neighbor-down { + value 3; + description "Neighbor signaled session down"; + } + enum forwarding-reset { + value 4; + description "Forwarding plane reset"; + } + enum path-down { + value 5; + description "Path down"; + } + enum concatenated-path-down { + value 6; + description "Concatenated path down"; + } + enum administratively-down { + value 7; + description "Administratively down"; + } + enum reverse-concat-path-down { + value 8; + description "Reverse concatenated path down"; + } + } + } + + /* + * Shared BFD items. + */ + grouping session-common { + description "Common BFD session settings"; + + leaf detection-multiplier { + type multiplier; + default 3; + description "Local session detection multiplier"; + } + + leaf desired-transmission-interval { + type uint32; + units milliseconds; + default 300; + description "Minimum desired control packet transmission interval"; + } + + leaf required-receive-interval { + type uint32; + units milliseconds; + default 300; + description "Minimum required control packet receive interval"; + } + + leaf administrative-down { + type boolean; + default true; + description "Disables or enables the session administratively"; + } + } + + grouping session-echo { + description "BFD session echo settings"; + + leaf echo-mode { + type boolean; + default false; + description "Use echo packets to detect failures"; + } + + leaf desired-echo-transmission-interval { + type uint32; + units milliseconds; + default 50; + description "Minimum desired control packet transmission interval"; + } + } + + grouping session-states { + /* + * Local settings. + */ + leaf local-discriminator { + type discriminator; + description "Local session identifier"; + } + + leaf local-state { + type state; + description "Local session state"; + } + + leaf local-diagnostic { + type diagnostic; + description "Local session diagnostic"; + } + + leaf local-multiplier { + type multiplier; + description "Local session current multiplier"; + } + + /* + * Remote settings. + */ + leaf remote-discriminator { + type discriminator; + description "Remote session identifier"; + } + + leaf remote-state { + type state; + description "Remote session state"; + } + + leaf remote-diagnostic { + type diagnostic; + description "Local session diagnostic"; + } + + leaf remote-multiplier { + type multiplier; + description "Remote session detection multiplier"; + } + + /* + * Negotiated settings. + */ + leaf negotiated-transmission-interval { + description "Negotiated transmit interval"; + type uint32; + units milliseconds; + } + + leaf negotiated-receive-interval { + description "Negotiated receive interval"; + type uint32; + units milliseconds; + } + + leaf detection-mode { + description "Detection mode"; + + type enumeration { + enum async-with-echo { + value "1"; + description "Async with echo"; + } + enum async-without-echo { + value "2"; + description "Async without echo"; + } + enum demand-with-echo { + value "3"; + description "Demand with echo"; + } + enum demand-without-echo { + value "4"; + description "Demand without echo"; + } + } + } + + /* + * Statistics. + */ + leaf last-down-time { + type yang:date-and-time; + description "Time and date of the last time session was down"; + } + + leaf last-up-time { + type yang:date-and-time; + description "Time and date of the last time session was up"; + } + + leaf session-down-count { + type uint32; + description "Amount of times the session went down"; + } + + leaf session-up-count { + type uint32; + description "Amount of times the session went up"; + } + + leaf control-packet-input-count { + type uint64; + description "Amount of control packets received"; + } + + leaf control-packet-output-count { + type uint64; + description "Amount of control packets sent"; + } + + /* + * Echo mode operational data. + */ + leaf negotiated-echo-transmission-interval { + type uint32; + units milliseconds; + description "Negotiated echo transmit interval"; + } + + /* + * Statistics. + */ + leaf echo-packet-input-count { + type uint64; + description "Amount of echo packets received"; + } + + leaf echo-packet-output-count { + type uint64; + description "Amount of echo packets sent"; + } + } + + /* + * BFD operational. + */ + container bfdd { + container bfd { + presence "Present if the BFD protocol is enabled"; + + container sessions { + list single-hop { + key "dest-addr interface vrf"; + description "List of single hop sessions"; + + leaf source-addr { + type inet:ip-address; + description "Local IP address"; + } + + leaf dest-addr { + type inet:ip-address; + description "IP address of the peer"; + } + + leaf interface { + type string { + length "0..16"; + } + description "Interface to use to contact peer"; + } + + leaf vrf { + type string; + description "Virtual Routing Domain name"; + } + + uses session-common; + uses session-echo; + + container stats { + uses session-states; + config false; + } + } + + list multi-hop { + key "source-addr dest-addr interface vrf"; + description "List of multi hop sessions"; + + leaf source-addr { + type inet:ip-address; + description "Local IP address"; + } + + leaf dest-addr { + type inet:ip-address; + description "IP address of the peer"; + } + + leaf interface { + type string { + length "0..16"; + } + description "Interface to use to contact peer"; + } + + leaf vrf { + type string; + description "Virtual Routing Domain name"; + } + + uses session-common; + + container stats { + uses session-states; + config false; + } + } + } + } + } +} From a4d3c1d41d13c2bbb68224b7bad141e220017b2f Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Fri, 24 May 2019 22:11:27 -0300 Subject: [PATCH 02/21] lib: northbound cli support to end config nodes Some more complex CLI usages will require northbound to support signalizing a custom configuration node end. For an example: ``` router bgp 100 bgp router-id 10.254.254.1 neighbor 10.0.0.100 remote-as 200 ! address-family ipv4 unicast network 10.0.1.0/24 network 10.0.2.0/24 network 10.0.3.0/24 exit-address-family ! address-family ipv6 unicast neighbor 10.0.0.100 activate exit-address-family ! ``` This commit implements a new callback called `cli_show_end` which complements `cli_show` and is only called at the end of processing the yang configuration node. It will be used to write the configuration node termination like: "!" or "exit-address-family". Signed-off-by: Rafael Zalamena --- lib/northbound.h | 21 +++++++++++++++++++++ lib/northbound_cli.c | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/lib/northbound.h b/lib/northbound.h index 8f6753506b..69d7c8e0ee 100644 --- a/lib/northbound.h +++ b/lib/northbound.h @@ -337,6 +337,27 @@ struct nb_callbacks { */ void (*cli_show)(struct vty *vty, struct lyd_node *dnode, bool show_defaults); + + /* + * Optional callback to show the CLI node end for lists or containers. + * + * vty + * The vty terminal to dump the configuration to. + * + * dnode + * libyang data node that should be shown in the form of a CLI + * command. + * + * show_defaults + * Specify whether to display default configuration values or not. + * This parameter can be ignored most of the time since the + * northbound doesn't call this callback for default leaves or + * non-presence containers that contain only default child nodes. + * The exception are commands associated to multiple configuration + * nodes, in which case it might be desirable to hide one or more + * parts of the command when this parameter is set to false. + */ + void (*cli_show_end)(struct vty *vty, struct lyd_node *dnode); }; /* diff --git a/lib/northbound_cli.c b/lib/northbound_cli.c index 7b7b526af0..c96bfbdb91 100644 --- a/lib/northbound_cli.c +++ b/lib/northbound_cli.c @@ -434,10 +434,29 @@ static int nb_cli_candidate_load_transaction(struct vty *vty, return CMD_SUCCESS; } +/* + * ly_iter_next_is_up: detects when iterating up on the yang model. + * + * This function detects whether next node in the iteration is upwards, + * then return the node otherwise return NULL. + */ +static struct lyd_node *ly_iter_next_up(struct lyd_node *elem) +{ + /* Are we going downwards? Is this still not a leaf? */ + if (!(elem->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA))) + return NULL; + + /* Are there still leaves in this branch? */ + if (elem->next != NULL) + return NULL; + + return elem->parent; +} + void nb_cli_show_dnode_cmds(struct vty *vty, struct lyd_node *root, bool with_defaults) { - struct lyd_node *next, *child; + struct lyd_node *next, *child, *parent; LY_TREE_DFS_BEGIN (root, next, child) { struct nb_node *nb_node; @@ -452,6 +471,19 @@ void nb_cli_show_dnode_cmds(struct vty *vty, struct lyd_node *root, (*nb_node->cbs.cli_show)(vty, child, with_defaults); next: + /* + * When transiting upwards in the yang model we should + * give the previous container/list node a chance to + * print its close vty output (e.g. "!" or "end-family" + * etc...). + */ + parent = ly_iter_next_up(child); + if (parent != NULL) { + nb_node = parent->schema->priv; + if (nb_node->cbs.cli_show_end) + (*nb_node->cbs.cli_show_end)(vty, parent); + } + LY_TREE_DFS_END(root, next, child); } } From 014cab13bfc2386f22122107c3af0b409f9211c2 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Thu, 23 May 2019 15:22:08 -0300 Subject: [PATCH 03/21] bfdd: export some private functions These functions are going to be used by the future northbound implementation to handle BFD sessions. Signed-off-by: Rafael Zalamena --- bfdd/bfd.c | 27 ++++++++++++++++----------- bfdd/bfd.h | 6 ++++++ 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/bfdd/bfd.c b/bfdd/bfd.c index 08a70abc1e..5f41d6b70e 100644 --- a/bfdd/bfd.c +++ b/bfdd/bfd.c @@ -39,14 +39,8 @@ DEFINE_QOBJ_TYPE(bfd_session) /* * Prototypes */ -void gen_bfd_key(struct bfd_key *key, struct sockaddr_any *peer, - struct sockaddr_any *local, bool mhop, const char *ifname, - const char *vrfname); - static uint32_t ptm_bfd_gen_ID(void); static void ptm_bfd_echo_xmt_TO(struct bfd_session *bfd); -static void bfd_session_free(struct bfd_session *bs); -static struct bfd_session *bfd_session_new(void); static struct bfd_session *bfd_find_disc(struct sockaddr_any *sa, uint32_t ldisc); static int bfd_session_update(struct bfd_session *bs, struct bfd_peer_cfg *bpc); @@ -469,7 +463,7 @@ int bfd_echo_recvtimer_cb(struct thread *t) return 0; } -static struct bfd_session *bfd_session_new(void) +struct bfd_session *bfd_session_new(void) { struct bfd_session *bs; @@ -629,7 +623,7 @@ static int bfd_session_update(struct bfd_session *bs, struct bfd_peer_cfg *bpc) return 0; } -static void bfd_session_free(struct bfd_session *bs) +void bfd_session_free(struct bfd_session *bs) { struct bfd_session_observer *bso; @@ -717,6 +711,17 @@ struct bfd_session *ptm_bfd_sess_new(struct bfd_peer_cfg *bpc) bfd->key.mhop = bpc->bpc_mhop; + if (bs_registrate(bfd) == NULL) + return NULL; + + /* Apply other configurations. */ + _bfd_session_update(bfd, bpc); + + return bfd; +} + +struct bfd_session *bs_registrate(struct bfd_session *bfd) +{ /* Registrate session into data structures. */ bfd_key_insert(bfd); bfd->discrs.my_discr = ptm_bfd_gen_ID(); @@ -733,9 +738,6 @@ struct bfd_session *ptm_bfd_sess_new(struct bfd_peer_cfg *bpc) if (bfd->key.ifname[0] || bfd->key.vrfname[0] || bfd->sock == -1) bs_observer_add(bfd); - /* Apply other configurations. */ - _bfd_session_update(bfd, bpc); - log_info("session-new: %s", bs_to_string(bfd)); control_notify_config(BCM_NOTIFY_CONFIG_ADD, bfd); @@ -1531,6 +1533,9 @@ void bfd_shutdown(void) hash_free(bfd_key_hash); } +/* + * VRF related functions. + */ static int bfd_vrf_new(struct vrf *vrf) { log_debug("VRF Created: %s(%u)", vrf->name, vrf->vrf_id); diff --git a/bfdd/bfd.h b/bfdd/bfd.h index ec31c8cbc6..48f9090ad4 100644 --- a/bfdd/bfd.h +++ b/bfdd/bfd.h @@ -546,6 +546,12 @@ void bs_observer_del(struct bfd_session_observer *bso); void bs_to_bpc(struct bfd_session *bs, struct bfd_peer_cfg *bpc); +void gen_bfd_key(struct bfd_key *key, struct sockaddr_any *peer, + struct sockaddr_any *local, bool mhop, const char *ifname, + const char *vrfname); +struct bfd_session *bfd_session_new(void); +struct bfd_session *bs_registrate(struct bfd_session *bs); +void bfd_session_free(struct bfd_session *bs); /* BFD hash data structures interface */ void bfd_initialize(void); void bfd_shutdown(void); From 3e4e7405ff2d9373c4e43550fa37c43fd06504d5 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Sat, 25 May 2019 10:08:46 -0300 Subject: [PATCH 04/21] bfdd: remove the label command This command has no use for CLI and is relevant for the control socket only. Signed-off-by: Rafael Zalamena --- bfdd/bfdd_vty.c | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/bfdd/bfdd_vty.c b/bfdd/bfdd_vty.c index 75f6632db0..6f0b85c411 100644 --- a/bfdd/bfdd_vty.c +++ b/bfdd/bfdd_vty.c @@ -296,27 +296,6 @@ DEFPY(bfd_peer_echo, bfd_peer_echo_cmd, "[no] echo-mode", return CMD_SUCCESS; } -DEFPY(bfd_peer_label, bfd_peer_label_cmd, "label WORD$label", - "Register peer label\n" - "Register peer label identification\n") -{ - struct bfd_session *bs; - - /* Validate label length. */ - if (strlen(label) >= MAXNAMELEN) { - vty_out(vty, "%% Label name is too long\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - bs = VTY_GET_CONTEXT(bfd_session); - if (bfd_session_update_label(bs, label) == -1) { - vty_out(vty, "%% Failed to update peer label.\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - return CMD_SUCCESS; -} - DEFPY(bfd_no_peer, bfd_no_peer_cmd, "no peer $peer [{multihop|local-address $local|interface IFNAME$ifname|vrf NAME$vrfname}]", NO_STR @@ -1103,5 +1082,4 @@ void bfdd_vty_init(void) install_element(BFD_PEER_NODE, &bfd_peer_echointerval_cmd); install_element(BFD_PEER_NODE, &bfd_peer_shutdown_cmd); install_element(BFD_PEER_NODE, &bfd_peer_echo_cmd); - install_element(BFD_PEER_NODE, &bfd_peer_label_cmd); } From adc26455bff183ce65d475b058045165826d823f Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Thu, 23 May 2019 16:09:24 -0300 Subject: [PATCH 05/21] bfdd: migrate session commands to northbound Lets start using the new BFD yang model and translate the BFD session configuration commands to use the northbound. One important change: all sessions will default to use `VRF_DEFAULT_NAME` (usually "default") when no VRF is configured. All places which search for BFD sessions must now take this into account. Signed-off-by: Rafael Zalamena --- bfdd/bfd.c | 78 ++- bfdd/bfd.h | 23 +- bfdd/bfdd.c | 9 +- bfdd/bfdd_cli.c | 232 +++++++++ bfdd/bfdd_northbound.c | 1060 ++++++++++++++++++++++++++++++++++++++++ bfdd/bfdd_vty.c | 264 +--------- bfdd/subdir.am | 6 + yang/subdir.am | 4 + 8 files changed, 1397 insertions(+), 279 deletions(-) create mode 100644 bfdd/bfdd_cli.c create mode 100644 bfdd/bfdd_northbound.c diff --git a/bfdd/bfd.c b/bfdd/bfd.c index 5f41d6b70e..828059eb4a 100644 --- a/bfdd/bfd.c +++ b/bfdd/bfd.c @@ -34,7 +34,6 @@ DEFINE_MTYPE_STATIC(BFDD, BFDD_CONFIG, "long-lived configuration memory") DEFINE_MTYPE_STATIC(BFDD, BFDD_SESSION_OBSERVER, "Session observer") DEFINE_MTYPE_STATIC(BFDD, BFDD_VRF, "BFD VRF") -DEFINE_QOBJ_TYPE(bfd_session) /* * Prototypes @@ -85,6 +84,8 @@ void gen_bfd_key(struct bfd_key *key, struct sockaddr_any *peer, strlcpy(key->ifname, ifname, sizeof(key->ifname)); if (vrfname && vrfname[0]) strlcpy(key->vrfname, vrfname, sizeof(key->vrfname)); + else + strlcpy(key->vrfname, VRF_DEFAULT_NAME, sizeof(key->vrfname)); } struct bfd_session *bs_peer_find(struct bfd_peer_cfg *bpc) @@ -390,17 +391,13 @@ struct bfd_session *ptm_bfd_sess_find(struct bfd_pkt *cp, /* Search for session without using discriminator. */ ifp = if_lookup_by_index(ifindex, vrfid); - if (vrfid == VRF_DEFAULT) { - /* - * Don't use the default vrf, otherwise we won't find - * sessions that doesn't specify it. - */ - vrf = NULL; - } else + if (vrfid != VRF_DEFAULT) vrf = vrf_lookup_by_id(vrfid); + else + vrf = NULL; gen_bfd_key(&key, peer, local, is_mhop, ifp ? ifp->name : NULL, - vrf ? vrf->name : NULL); + vrf ? vrf->name : VRF_DEFAULT_NAME); /* XXX maybe remoteDiscr should be checked for remoteHeard cases. */ return bfd_key_lookup(key); @@ -469,8 +466,6 @@ struct bfd_session *bfd_session_new(void) bs = XCALLOC(MTYPE_BFDD_CONFIG, sizeof(*bs)); - QOBJ_REG(bs, bfd_session); - bs->timers.desired_min_tx = BFD_DEFDESIREDMINTX; bs->timers.required_min_rx = BFD_DEFREQUIREDMINRX; bs->timers.required_min_echo = BFD_DEF_REQ_MIN_ECHO; @@ -644,7 +639,6 @@ void bfd_session_free(struct bfd_session *bs) pl_free(bs->pl); - QOBJ_UNREG(bs); XFREE(MTYPE_BFDD_CONFIG, bs); } @@ -680,6 +674,9 @@ struct bfd_session *ptm_bfd_sess_new(struct bfd_peer_cfg *bpc) if (bpc->bpc_has_vrfname) strlcpy(bfd->key.vrfname, bpc->bpc_vrfname, sizeof(bfd->key.vrfname)); + else + strlcpy(bfd->key.vrfname, VRF_DEFAULT_NAME, + sizeof(bfd->key.vrfname)); /* Copy remaining data. */ if (bpc->bpc_ipv4 == false) @@ -1292,6 +1289,7 @@ static unsigned int bfd_key_hash_do(const void *p); static void _bfd_free(struct hash_bucket *hb, void *arg __attribute__((__unused__))); +int _bfd_session_next(struct hash_bucket *hb, void *arg); /* BFD hash for our discriminator. */ static unsigned int bfd_id_hash_do(const void *p) @@ -1533,6 +1531,62 @@ void bfd_shutdown(void) hash_free(bfd_key_hash); } +struct bfd_session_iterator { + int bsi_stop; + bool bsi_mhop; + const struct bfd_session *bsi_bs; +}; + +int _bfd_session_next(struct hash_bucket *hb, void *arg) +{ + struct bfd_session_iterator *bsi = arg; + struct bfd_session *bs = hb->data; + + /* Previous entry signaled stop. */ + if (bsi->bsi_stop == 1) { + /* Match the single/multi hop sessions. */ + if (bs->key.mhop != bsi->bsi_mhop) + return HASHWALK_CONTINUE; + + bsi->bsi_bs = bs; + return HASHWALK_ABORT; + } + + /* We found the current item, stop in the next one. */ + if (bsi->bsi_bs == hb->data) { + bsi->bsi_stop = 1; + /* Set entry to NULL to signal end of list. */ + bsi->bsi_bs = NULL; + } else if (bsi->bsi_bs == NULL && bsi->bsi_mhop == bs->key.mhop) { + /* We want the first list item. */ + bsi->bsi_stop = 1; + bsi->bsi_bs = hb->data; + return HASHWALK_ABORT; + } + + return HASHWALK_CONTINUE; +} + +/* + * bfd_session_next: uses the current session to find the next. + * + * `bs` might point to NULL to get the first item of the data structure. + */ +const struct bfd_session *bfd_session_next(const struct bfd_session *bs, + bool mhop) +{ + struct bfd_session_iterator bsi; + + bsi.bsi_stop = 0; + bsi.bsi_bs = bs; + bsi.bsi_mhop = mhop; + hash_walk(bfd_key_hash, _bfd_session_next, &bsi); + if (bsi.bsi_stop == 0) + return NULL; + + return bsi.bsi_bs; +} + /* * VRF related functions. */ diff --git a/bfdd/bfd.h b/bfdd/bfd.h index 48f9090ad4..7568583f96 100644 --- a/bfdd/bfd.h +++ b/bfdd/bfd.h @@ -252,11 +252,7 @@ struct bfd_session { struct bfd_timers remote_timers; uint64_t refcount; /* number of pointers referencing this. */ - - /* VTY context data. */ - QOBJ_FIELDS }; -DECLARE_QOBJ_TYPE(bfd_session) struct peer_label { TAILQ_ENTRY(peer_label) pl_entry; @@ -552,6 +548,9 @@ void gen_bfd_key(struct bfd_key *key, struct sockaddr_any *peer, struct bfd_session *bfd_session_new(void); struct bfd_session *bs_registrate(struct bfd_session *bs); void bfd_session_free(struct bfd_session *bs); +const struct bfd_session *bfd_session_next(const struct bfd_session *bs, + bool mhop); + /* BFD hash data structures interface */ void bfd_initialize(void); void bfd_shutdown(void); @@ -590,6 +589,14 @@ extern struct in6_addr zero_addr; void bfdd_vty_init(void); +/* + * bfdd_cli.c + * + * BFD daemon CLI implementation. + */ +void bfdd_cli_init(void); + + /* * ptm_adapter.c */ @@ -602,4 +609,12 @@ void bfdd_sessions_disable_vrf(struct vrf *vrf); int ptm_bfd_notify(struct bfd_session *bs); + +/* + * bfdd_northbound.c + * + * BFD northbound callbacks. + */ +extern const struct frr_yang_module_info frr_bfdd_info; + #endif /* _BFD_H_ */ diff --git a/bfdd/bfdd.c b/bfdd/bfdd.c index 6c277c98f5..5a6089f384 100644 --- a/bfdd/bfdd.c +++ b/bfdd/bfdd.c @@ -93,10 +93,17 @@ static struct quagga_signal_t bfd_signals[] = { }, }; +static const struct frr_yang_module_info *bfdd_yang_modules[] = { + &frr_interface_info, + &frr_bfdd_info, +}; + FRR_DAEMON_INFO(bfdd, BFD, .vty_port = 2617, .proghelp = "Implementation of the BFD protocol.", .signals = bfd_signals, .n_signals = array_size(bfd_signals), - .privs = &bglobal.bfdd_privs) + .privs = &bglobal.bfdd_privs, + .yang_modules = bfdd_yang_modules, + .n_yang_modules = array_size(bfdd_yang_modules)) #define OPTION_CTLSOCK 1001 static struct option longopts[] = { diff --git a/bfdd/bfdd_cli.c b/bfdd/bfdd_cli.c new file mode 100644 index 0000000000..200ae543c7 --- /dev/null +++ b/bfdd/bfdd_cli.c @@ -0,0 +1,232 @@ +/* + * BFD daemon CLI implementation. + * + * Copyright (C) 2019 Network Device Education Foundation, Inc. ("NetDEF") + * Rafael Zalamena + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + */ + +#include "lib/command.h" +#include "lib/log.h" +#include "lib/northbound_cli.h" + +#ifndef VTYSH_EXTRACT_PL +#include "bfdd/bfdd_cli_clippy.c" +#endif /* VTYSH_EXTRACT_PL */ + +#include "bfd.h" + +/* + * Definitions. + */ +#define PEER_STR "Configure peer\n" +#define INTERFACE_NAME_STR "Configure interface name to use\n" +#define PEER_IPV4_STR "IPv4 peer address\n" +#define PEER_IPV6_STR "IPv6 peer address\n" +#define MHOP_STR "Configure multihop\n" +#define LOCAL_STR "Configure local address\n" +#define LOCAL_IPV4_STR "IPv4 local address\n" +#define LOCAL_IPV6_STR "IPv6 local address\n" +#define LOCAL_INTF_STR "Configure local interface name to use\n" +#define VRF_STR "Configure VRF\n" +#define VRF_NAME_STR "Configure VRF name\n" + +/* + * Prototypes. + */ + +/* + * Functions. + */ +DEFPY_NOSH( + bfd_peer_enter, bfd_peer_enter_cmd, + "peer [{multihop$multihop|local-address |interface IFNAME$ifname|vrf NAME}]", + PEER_STR + PEER_IPV4_STR + PEER_IPV6_STR + MHOP_STR + LOCAL_STR + LOCAL_IPV4_STR + LOCAL_IPV6_STR + INTERFACE_STR + LOCAL_INTF_STR + VRF_STR + VRF_NAME_STR) +{ + int ret, slen; + char xpath[XPATH_MAXLEN]; + char source_str[INET6_ADDRSTRLEN]; + + if (multihop) + snprintf(source_str, sizeof(source_str), "[source-addr='%s']", + local_address_str); + else + source_str[0] = 0; + + slen = snprintf(xpath, sizeof(xpath), + "/frr-bfdd:bfdd/bfd/sessions/%s%s[dest-addr='%s']", + multihop ? "multi-hop" : "single-hop", source_str, + peer_str); + if (ifname) + slen += snprintf(xpath + slen, sizeof(xpath) - slen, + "[interface='%s']", ifname); + else + slen += snprintf(xpath + slen, sizeof(xpath) - slen, + "[interface='']"); + if (vrf) + snprintf(xpath + slen, sizeof(xpath) - slen, "[vrf='%s']", vrf); + else + snprintf(xpath + slen, sizeof(xpath) - slen, "[vrf='%s']", + VRF_DEFAULT_NAME); + + nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); + + /* Apply settings immediatly. */ + ret = nb_cli_apply_changes(vty, NULL); + if (ret == CMD_SUCCESS) + VTY_PUSH_XPATH(BFD_PEER_NODE, xpath); + + return ret; +} + +DEFPY( + bfd_no_peer, bfd_no_peer_cmd, + "no peer [{multihop$multihop|local-address |interface IFNAME$ifname|vrf NAME}]", + NO_STR + PEER_STR + PEER_IPV4_STR + PEER_IPV6_STR + MHOP_STR + LOCAL_STR + LOCAL_IPV4_STR + LOCAL_IPV6_STR + INTERFACE_STR + LOCAL_INTF_STR + VRF_STR + VRF_NAME_STR) +{ + int slen; + char xpath[XPATH_MAXLEN]; + char source_str[INET6_ADDRSTRLEN]; + + if (multihop) + snprintf(source_str, sizeof(source_str), "[source-addr='%s']", + local_address_str); + else + source_str[0] = 0; + + slen = snprintf(xpath, sizeof(xpath), + "/frr-bfdd:bfdd/bfd/sessions/%s%s[dest-addr='%s']", + multihop ? "multi-hop" : "single-hop", source_str, + peer_str); + if (ifname) + slen += snprintf(xpath + slen, sizeof(xpath) - slen, + "[interface='%s']", ifname); + else + slen += snprintf(xpath + slen, sizeof(xpath) - slen, + "[interface='']"); + if (vrf) + snprintf(xpath + slen, sizeof(xpath) - slen, "[vrf='%s']", vrf); + else + snprintf(xpath + slen, sizeof(xpath) - slen, "[vrf='%s']", + VRF_DEFAULT_NAME); + + nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL); + + /* Apply settings immediatly. */ + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY( + bfd_peer_shutdown, bfd_peer_shutdown_cmd, + "[no] shutdown", + NO_STR + "Disable BFD peer") +{ + nb_cli_enqueue_change(vty, "./administrative-down", NB_OP_MODIFY, + no ? "false" : "true"); + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY( + bfd_peer_mult, bfd_peer_mult_cmd, + "detect-multiplier (2-255)$multiplier", + "Configure peer detection multiplier\n" + "Configure peer detection multiplier value\n") +{ + nb_cli_enqueue_change(vty, "./detection-multiplier", NB_OP_MODIFY, + multiplier_str); + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY( + bfd_peer_rx, bfd_peer_rx_cmd, + "receive-interval (10-60000)$interval", + "Configure peer receive interval\n" + "Configure peer receive interval value in milliseconds\n") +{ + nb_cli_enqueue_change(vty, "./required-receive-interval", NB_OP_MODIFY, + interval_str); + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY( + bfd_peer_tx, bfd_peer_tx_cmd, + "transmit-interval (10-60000)$interval", + "Configure peer transmit interval\n" + "Configure peer transmit interval value in milliseconds\n") +{ + nb_cli_enqueue_change(vty, "./desired-transmission-interval", + NB_OP_MODIFY, interval_str); + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY( + bfd_peer_echo, bfd_peer_echo_cmd, + "[no] echo-mode", + NO_STR + "Configure echo mode\n") +{ + nb_cli_enqueue_change(vty, "./echo-mode", NB_OP_MODIFY, + no ? "false" : "true"); + return nb_cli_apply_changes(vty, NULL); +} + +DEFPY( + bfd_peer_echo_interval, bfd_peer_echo_interval_cmd, + "echo-interval (10-60000)$interval", + "Configure peer echo interval\n" + "Configure peer echo interval value in milliseconds\n") +{ + nb_cli_enqueue_change(vty, "./desired-echo-transmission-interval", + NB_OP_MODIFY, interval_str); + return nb_cli_apply_changes(vty, NULL); +} + +void +bfdd_cli_init(void) +{ + install_element(BFD_NODE, &bfd_peer_enter_cmd); + install_element(BFD_NODE, &bfd_no_peer_cmd); + + install_element(BFD_PEER_NODE, &bfd_peer_shutdown_cmd); + install_element(BFD_PEER_NODE, &bfd_peer_mult_cmd); + install_element(BFD_PEER_NODE, &bfd_peer_rx_cmd); + install_element(BFD_PEER_NODE, &bfd_peer_tx_cmd); + install_element(BFD_PEER_NODE, &bfd_peer_echo_cmd); + install_element(BFD_PEER_NODE, &bfd_peer_echo_interval_cmd); +} diff --git a/bfdd/bfdd_northbound.c b/bfdd/bfdd_northbound.c new file mode 100644 index 0000000000..a22430e6b7 --- /dev/null +++ b/bfdd/bfdd_northbound.c @@ -0,0 +1,1060 @@ +/* + * BFD daemon northbound implementation. + * + * Copyright (C) 2019 Network Device Education Foundation, Inc. ("NetDEF") + * Rafael Zalamena + * + * This program 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 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA. + */ + +#include "lib/log.h" +#include "lib/northbound.h" + +#include "bfd.h" + +/* + * Prototypes. + */ +void bfd_session_get_key(bool mhop, const struct lyd_node *dnode, + struct bfd_key *bk); +int bfd_session_create(enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource, bool mhop); +int bfd_session_destroy(enum nb_event event, const struct lyd_node *dnode, + bool mhop); + +/* + * Helpers. + */ +void bfd_session_get_key(bool mhop, const struct lyd_node *dnode, + struct bfd_key *bk) +{ + const char *ifname = NULL, *vrfname = NULL; + struct sockaddr_any psa, lsa; + + /* Required destination parameter. */ + strtosa(yang_dnode_get_string(dnode, "./dest-addr"), &psa); + + /* Get optional source address. */ + memset(&lsa, 0, sizeof(lsa)); + if (yang_dnode_exists(dnode, "./source-addr")) + strtosa(yang_dnode_get_string(dnode, "./source-addr"), &lsa); + + /* Get optional interface and vrf names. */ + if (yang_dnode_exists(dnode, "./interface")) + ifname = yang_dnode_get_string(dnode, "./interface"); + if (yang_dnode_exists(dnode, "./vrf")) + vrfname = yang_dnode_get_string(dnode, "./vrf"); + + /* Generate the corresponding key. */ + gen_bfd_key(bk, &psa, &lsa, mhop, ifname, vrfname); +} + +int bfd_session_create(enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource, bool mhop) +{ + struct bfd_session *bs; + struct bfd_key bk; + + switch (event) { + case NB_EV_VALIDATE: + bfd_session_get_key(mhop, dnode, &bk); + if (bfd_key_lookup(bk)) + return NB_ERR_VALIDATION; + break; + + case NB_EV_PREPARE: + bs = bfd_session_new(); + if (bs == NULL) + return NB_ERR_RESOURCE; + + /* Fill the session key. */ + bfd_session_get_key(mhop, dnode, &bs->key); + + /* Set configuration flags. */ + BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG); + if (mhop) + BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_MH); + if (bs->key.family == AF_INET6) + BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_IPV6); + + resource->ptr = bs; + break; + + case NB_EV_APPLY: + bs = resource->ptr; + if (bs_registrate(bs) == NULL) + return NB_ERR_RESOURCE; + + nb_running_set_entry(dnode, bs); + break; + + case NB_EV_ABORT: + bfd_session_free(resource->ptr); + break; + } + + return NB_OK; +} + +int bfd_session_destroy(enum nb_event event, const struct lyd_node *dnode, + bool mhop) +{ + struct bfd_key bk; + + switch (event) { + case NB_EV_VALIDATE: + bfd_session_get_key(mhop, dnode, &bk); + if (bfd_key_lookup(bk) == NULL) + return NB_ERR_VALIDATION; + break; + + case NB_EV_PREPARE: + /* NOTHING */ + break; + + case NB_EV_APPLY: + bfd_session_free(nb_running_unset_entry(dnode)); + break; + + case NB_EV_ABORT: + /* NOTHING */ + break; + } + + return NB_OK; +} + +/* + * XPath: /frr-bfdd:bfdd/bfd + */ +static int bfdd_bfd_create(enum nb_event event, + const struct lyd_node *dnode + __attribute__((__unused__)), + union nb_resource *resource + __attribute__((__unused__))) +{ + /* NOTHING */ + return NB_OK; +} + +static int bfdd_bfd_destroy(enum nb_event event, const struct lyd_node *dnode) +{ + /* NOTHING */ + return NB_OK; +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop + */ +static int bfdd_bfd_sessions_single_hop_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + return bfd_session_create(event, dnode, resource, false); +} + +static int bfdd_bfd_sessions_single_hop_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + return bfd_session_destroy(event, dnode, false); +} + +static const void * +bfdd_bfd_sessions_single_hop_get_next(const void *parent_list_entry + __attribute__((__unused__)), + const void *list_entry) +{ + return bfd_session_next(list_entry, false); +} + +static int bfdd_bfd_sessions_single_hop_get_keys(const void *list_entry, + struct yang_list_keys *keys) +{ + const struct bfd_session *bs = list_entry; + char dstbuf[INET6_ADDRSTRLEN]; + + inet_ntop(bs->key.family, &bs->key.peer, dstbuf, sizeof(dstbuf)); + + keys->num = 3; + strlcpy(keys->key[0], dstbuf, sizeof(keys->key[0])); + strlcpy(keys->key[1], bs->key.ifname, sizeof(keys->key[1])); + strlcpy(keys->key[2], bs->key.vrfname, sizeof(keys->key[2])); + + return NB_OK; +} + +static const void * +bfdd_bfd_sessions_single_hop_lookup_entry(const void *parent_list_entry + __attribute__((__unused__)), + const struct yang_list_keys *keys) +{ + const char *dest_addr = keys->key[0]; + const char *ifname = keys->key[1]; + const char *vrf = keys->key[2]; + struct sockaddr_any psa, lsa; + struct bfd_key bk; + + strtosa(dest_addr, &psa); + memset(&lsa, 0, sizeof(lsa)); + gen_bfd_key(&bk, &psa, &lsa, false, ifname, vrf); + + return bfd_key_lookup(bk); +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/source-addr + */ +static int bfdd_bfd_sessions_single_hop_source_addr_modify( + enum nb_event event __attribute__((__unused__)), + const struct lyd_node *dnode __attribute__((__unused__)), + union nb_resource *resource __attribute__((__unused__))) +{ + return NB_OK; +} + +static int bfdd_bfd_sessions_single_hop_source_addr_destroy( + enum nb_event event __attribute__((__unused__)), + const struct lyd_node *dnode __attribute__((__unused__))) +{ + return NB_OK; +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/detection-multiplier + */ +static int bfdd_bfd_sessions_single_hop_detection_multiplier_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource __attribute__((__unused__))) +{ + uint8_t detection_multiplier = yang_dnode_get_uint8(dnode, NULL); + struct bfd_session *bs; + + switch (event) { + case NB_EV_VALIDATE: + if (detection_multiplier == 1) + return NB_ERR_VALIDATION; + break; + + case NB_EV_PREPARE: + /* NOTHING */ + break; + + case NB_EV_APPLY: + bs = nb_running_get_entry(dnode, NULL, true); + bs->detect_mult = detection_multiplier; + break; + + case NB_EV_ABORT: + /* NOTHING */ + break; + } + + return NB_OK; +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/desired-transmission-interval + */ +static int bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource __attribute__((__unused__))) +{ + uint32_t tx_interval = yang_dnode_get_uint32(dnode, NULL); + struct bfd_session *bs; + + switch (event) { + case NB_EV_VALIDATE: + if (tx_interval < 10 || tx_interval > 60000) + return NB_ERR_VALIDATION; + break; + + case NB_EV_PREPARE: + /* NOTHING */ + break; + + case NB_EV_APPLY: + bs = nb_running_get_entry(dnode, NULL, true); + + tx_interval *= 1000; + if (tx_interval == bs->timers.desired_min_tx) + return NB_OK; + + bs->timers.desired_min_tx = tx_interval; + bfd_set_polling(bs); + break; + + case NB_EV_ABORT: + /* NOTHING */ + break; + } + + return NB_OK; +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/required-receive-interval + */ +static int bfdd_bfd_sessions_single_hop_required_receive_interval_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource __attribute__((__unused__))) +{ + uint32_t rx_interval = yang_dnode_get_uint32(dnode, NULL); + struct bfd_session *bs; + + switch (event) { + case NB_EV_VALIDATE: + if (rx_interval < 10 || rx_interval > 60000) + return NB_ERR_VALIDATION; + break; + + case NB_EV_PREPARE: + /* NOTHING */ + break; + + case NB_EV_APPLY: + bs = nb_running_get_entry(dnode, NULL, true); + + rx_interval *= 1000; + if (rx_interval == bs->timers.required_min_rx) + return NB_OK; + + bs->timers.required_min_rx = rx_interval; + bfd_set_polling(bs); + break; + + case NB_EV_ABORT: + /* NOTHING */ + break; + } + + return NB_OK; +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/administrative-down + */ +static int bfdd_bfd_sessions_single_hop_administrative_down_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource __attribute__((__unused__))) +{ + bool shutdown = yang_dnode_get_bool(dnode, NULL); + struct bfd_session *bs; + + switch (event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + return NB_OK; + + case NB_EV_APPLY: + break; + + case NB_EV_ABORT: + return NB_OK; + } + + bs = nb_running_get_entry(dnode, NULL, true); + + if (shutdown == false) { + if (!BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN)) + return NB_OK; + + BFD_UNSET_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN); + + /* Change and notify state change. */ + bs->ses_state = PTM_BFD_DOWN; + control_notify(bs); + + /* Enable all timers. */ + bfd_recvtimer_update(bs); + bfd_xmttimer_update(bs, bs->xmt_TO); + if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO)) { + bfd_echo_recvtimer_update(bs); + bfd_echo_xmttimer_update(bs, bs->echo_xmt_TO); + } + } else { + if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN)) + return NB_OK; + + BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN); + + /* Disable all events. */ + bfd_recvtimer_delete(bs); + bfd_echo_recvtimer_delete(bs); + bfd_xmttimer_delete(bs); + bfd_echo_xmttimer_delete(bs); + + /* Change and notify state change. */ + bs->ses_state = PTM_BFD_ADM_DOWN; + control_notify(bs); + + ptm_bfd_snd(bs, 0); + } + + return NB_OK; +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/echo-mode + */ +static int bfdd_bfd_sessions_single_hop_echo_mode_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource __attribute__((__unused__))) +{ + bool echo = yang_dnode_get_bool(dnode, NULL); + struct bfd_session *bs; + + switch (event) { + case NB_EV_VALIDATE: + case NB_EV_PREPARE: + return NB_OK; + + case NB_EV_APPLY: + break; + + case NB_EV_ABORT: + return NB_OK; + } + + bs = nb_running_get_entry(dnode, NULL, true); + + if (echo == false) { + if (!BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO)) + return NB_OK; + + BFD_UNSET_FLAG(bs->flags, BFD_SESS_FLAG_ECHO); + ptm_bfd_echo_stop(bs); + } else { + if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO)) + return NB_OK; + + BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_ECHO); + /* Apply setting immediately. */ + if (!BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN)) + bs_echo_timer_handler(bs); + } + + return NB_OK; +} + +/* + * XPath: + * /frr-bfdd:bfdd/bfd/sessions/single-hop/desired-echo-transmission-interval + */ +static int +bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify( + enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource __attribute__((__unused__))) +{ + uint32_t echo_interval = yang_dnode_get_uint32(dnode, NULL); + struct bfd_session *bs; + + switch (event) { + case NB_EV_VALIDATE: + if (echo_interval < 10 || echo_interval > 60000) + return NB_ERR_VALIDATION; + break; + + case NB_EV_PREPARE: + /* NOTHING */ + break; + + case NB_EV_APPLY: + bs = nb_running_get_entry(dnode, NULL, true); + + echo_interval *= 1000; + if (echo_interval == bs->timers.required_min_echo) + return NB_OK; + + bs->timers.required_min_echo = echo_interval; + break; + + case NB_EV_ABORT: + /* NOTHING */ + break; + } + + return NB_OK; +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-discriminator + */ +static struct yang_data * +bfdd_bfd_sessions_single_hop_stats_local_discriminator_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_uint32(xpath, bs->discrs.my_discr); +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-state + */ +static struct yang_data * +bfdd_bfd_sessions_single_hop_stats_local_state_get_elem(const char *xpath, + const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_enum(xpath, bs->ses_state); +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-diagnostic + */ +static struct yang_data * +bfdd_bfd_sessions_single_hop_stats_local_diagnostic_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_enum(xpath, bs->local_diag); +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-multiplier + */ +static struct yang_data * +bfdd_bfd_sessions_single_hop_stats_local_multiplier_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_int8(xpath, bs->detect_mult); +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-discriminator + */ +static struct yang_data * +bfdd_bfd_sessions_single_hop_stats_remote_discriminator_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_uint32(xpath, bs->discrs.remote_discr); +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-state + */ +static struct yang_data * +bfdd_bfd_sessions_single_hop_stats_remote_state_get_elem(const char *xpath, + const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_enum(xpath, bs->ses_state); +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-diagnostic + */ +static struct yang_data * +bfdd_bfd_sessions_single_hop_stats_remote_diagnostic_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_enum(xpath, bs->remote_diag); +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-multiplier + */ +static struct yang_data * +bfdd_bfd_sessions_single_hop_stats_remote_multiplier_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_int8(xpath, bs->remote_detect_mult); +} + +/* + * XPath: + * /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/negotiated-transmission-interval + */ +static struct yang_data * +bfdd_bfd_sessions_single_hop_stats_negotiated_transmission_interval_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_uint32(xpath, + bs->remote_timers.desired_min_tx / 1000); +} + +/* + * XPath: + * /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/negotiated-receive-interval + */ +static struct yang_data * +bfdd_bfd_sessions_single_hop_stats_negotiated_receive_interval_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_uint32(xpath, + bs->remote_timers.required_min_rx / 1000); +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/detection-mode + */ +static struct yang_data * +bfdd_bfd_sessions_single_hop_stats_detection_mode_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + int detection_mode; + + /* + * Detection mode: + * 1. Async with echo + * 2. Async without echo + * 3. Demand with echo + * 4. Demand without echo + * + * TODO: support demand mode. + */ + if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO)) + detection_mode = 1; + else + detection_mode = 2; + + return yang_data_new_enum(xpath, detection_mode); +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/last-down-time + */ +static struct yang_data * +bfdd_bfd_sessions_single_hop_stats_last_down_time_get_elem( + const char *xpath __attribute__((__unused__)), + const void *list_entry __attribute__((__unused__))) +{ + /* + * TODO: implement me. + * + * No yang support for time elements yet. + */ + return NULL; +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/last-up-time + */ +static struct yang_data * +bfdd_bfd_sessions_single_hop_stats_last_up_time_get_elem( + const char *xpath __attribute__((__unused__)), + const void *list_entry __attribute__((__unused__))) +{ + /* + * TODO: implement me. + * + * No yang support for time elements yet. + */ + return NULL; +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/session-down-count + */ +static struct yang_data * +bfdd_bfd_sessions_single_hop_stats_session_down_count_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_uint64(xpath, bs->stats.session_down); +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/session-up-count + */ +static struct yang_data * +bfdd_bfd_sessions_single_hop_stats_session_up_count_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_uint64(xpath, bs->stats.session_up); +} + +/* + * XPath: + * /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/control-packet-input-count + */ +static struct yang_data * +bfdd_bfd_sessions_single_hop_stats_control_packet_input_count_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_uint64(xpath, bs->stats.rx_ctrl_pkt); +} + +/* + * XPath: + * /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/control-packet-output-count + */ +static struct yang_data * +bfdd_bfd_sessions_single_hop_stats_control_packet_output_count_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_uint64(xpath, bs->stats.tx_ctrl_pkt); +} + +/* + * XPath: + * /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/negotiated-echo-transmission-interval + */ +static struct yang_data * +bfdd_bfd_sessions_single_hop_stats_negotiated_echo_transmission_interval_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_uint32(xpath, + bs->remote_timers.required_min_echo / 1000); +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/echo-packet-input-count + */ +static struct yang_data * +bfdd_bfd_sessions_single_hop_stats_echo_packet_input_count_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_uint64(xpath, bs->stats.rx_echo_pkt); +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/single-hop/stats/echo-packet-output-count + */ +static struct yang_data * +bfdd_bfd_sessions_single_hop_stats_echo_packet_output_count_get_elem( + const char *xpath, const void *list_entry) +{ + const struct bfd_session *bs = list_entry; + + return yang_data_new_uint64(xpath, bs->stats.tx_echo_pkt); +} + +/* + * XPath: /frr-bfdd:bfdd/bfd/sessions/multi-hop + */ +static int bfdd_bfd_sessions_multi_hop_create(enum nb_event event, + const struct lyd_node *dnode, + union nb_resource *resource) +{ + return bfd_session_create(event, dnode, resource, true); +} + +static int bfdd_bfd_sessions_multi_hop_destroy(enum nb_event event, + const struct lyd_node *dnode) +{ + return bfd_session_destroy(event, dnode, true); +} + +static const void * +bfdd_bfd_sessions_multi_hop_get_next(const void *parent_list_entry + __attribute__((__unused__)), + const void *list_entry) +{ + return bfd_session_next(list_entry, true); +} + +static int bfdd_bfd_sessions_multi_hop_get_keys(const void *list_entry, + struct yang_list_keys *keys) +{ + const struct bfd_session *bs = list_entry; + char dstbuf[INET6_ADDRSTRLEN], srcbuf[INET6_ADDRSTRLEN]; + + inet_ntop(bs->key.family, &bs->key.peer, dstbuf, sizeof(dstbuf)); + inet_ntop(bs->key.family, &bs->key.local, srcbuf, sizeof(srcbuf)); + + keys->num = 4; + strlcpy(keys->key[0], srcbuf, sizeof(keys->key[0])); + strlcpy(keys->key[1], dstbuf, sizeof(keys->key[1])); + strlcpy(keys->key[2], bs->key.ifname, sizeof(keys->key[2])); + strlcpy(keys->key[3], bs->key.vrfname, sizeof(keys->key[3])); + + return NB_OK; +} + +static const void * +bfdd_bfd_sessions_multi_hop_lookup_entry(const void *parent_list_entry + __attribute__((__unused__)), + const struct yang_list_keys *keys) +{ + const char *source_addr = keys->key[0]; + const char *dest_addr = keys->key[1]; + const char *ifname = keys->key[2]; + const char *vrf = keys->key[3]; + struct sockaddr_any psa, lsa; + struct bfd_key bk; + + strtosa(dest_addr, &psa); + strtosa(source_addr, &lsa); + gen_bfd_key(&bk, &psa, &lsa, true, ifname, vrf); + + return bfd_key_lookup(bk); +} + +/* clang-format off */ +const struct frr_yang_module_info frr_bfdd_info = { + .name = "frr-bfdd", + .nodes = { + { + .xpath = "/frr-bfdd:bfdd/bfd", + .cbs.create = bfdd_bfd_create, + .cbs.destroy = bfdd_bfd_destroy, + .cbs.cli_show = bfd_cli_show_header, + .cbs.cli_show_end = bfd_cli_show_header_end, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop", + .cbs.create = bfdd_bfd_sessions_single_hop_create, + .cbs.destroy = bfdd_bfd_sessions_single_hop_destroy, + .cbs.get_next = bfdd_bfd_sessions_single_hop_get_next, + .cbs.get_keys = bfdd_bfd_sessions_single_hop_get_keys, + .cbs.lookup_entry = bfdd_bfd_sessions_single_hop_lookup_entry, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/source-addr", + .cbs.modify = bfdd_bfd_sessions_single_hop_source_addr_modify, + .cbs.destroy = bfdd_bfd_sessions_single_hop_source_addr_destroy, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/detection-multiplier", + .cbs.modify = bfdd_bfd_sessions_single_hop_detection_multiplier_modify, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/desired-transmission-interval", + .cbs.modify = bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/required-receive-interval", + .cbs.modify = bfdd_bfd_sessions_single_hop_required_receive_interval_modify, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/administrative-down", + .cbs.modify = bfdd_bfd_sessions_single_hop_administrative_down_modify, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/echo-mode", + .cbs.modify = bfdd_bfd_sessions_single_hop_echo_mode_modify, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/desired-echo-transmission-interval", + .cbs.modify = bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-discriminator", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_local_discriminator_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-state", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_local_state_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-diagnostic", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_local_diagnostic_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-multiplier", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_local_multiplier_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-discriminator", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_remote_discriminator_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-state", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_remote_state_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-diagnostic", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_remote_diagnostic_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-multiplier", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_remote_multiplier_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/negotiated-transmission-interval", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_transmission_interval_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/negotiated-receive-interval", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_receive_interval_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/detection-mode", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_detection_mode_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/last-down-time", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_last_down_time_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/last-up-time", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_last_up_time_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/session-down-count", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_session_down_count_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/session-up-count", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_session_up_count_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/control-packet-input-count", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_control_packet_input_count_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/control-packet-output-count", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_control_packet_output_count_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/negotiated-echo-transmission-interval", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_echo_transmission_interval_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/echo-packet-input-count", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_echo_packet_input_count_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/echo-packet-output-count", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_echo_packet_output_count_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop", + .cbs.create = bfdd_bfd_sessions_multi_hop_create, + .cbs.destroy = bfdd_bfd_sessions_multi_hop_destroy, + .cbs.get_next = bfdd_bfd_sessions_multi_hop_get_next, + .cbs.get_keys = bfdd_bfd_sessions_multi_hop_get_keys, + .cbs.lookup_entry = bfdd_bfd_sessions_multi_hop_lookup_entry, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/detection-multiplier", + .cbs.modify = bfdd_bfd_sessions_single_hop_detection_multiplier_modify, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/desired-transmission-interval", + .cbs.modify = bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/required-receive-interval", + .cbs.modify = bfdd_bfd_sessions_single_hop_required_receive_interval_modify, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/administrative-down", + .cbs.modify = bfdd_bfd_sessions_single_hop_administrative_down_modify, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/local-discriminator", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_local_discriminator_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/local-state", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_local_state_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/local-diagnostic", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_local_diagnostic_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/local-multiplier", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_local_multiplier_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/remote-discriminator", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_remote_discriminator_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/remote-state", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_remote_state_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/remote-diagnostic", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_remote_diagnostic_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/remote-multiplier", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_remote_multiplier_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/negotiated-transmission-interval", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_transmission_interval_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/negotiated-receive-interval", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_receive_interval_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/detection-mode", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_detection_mode_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/last-down-time", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_last_down_time_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/last-up-time", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_last_up_time_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/session-down-count", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_session_down_count_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/session-up-count", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_session_up_count_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/control-packet-input-count", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_control_packet_input_count_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/control-packet-output-count", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_control_packet_output_count_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/negotiated-echo-transmission-interval", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_echo_transmission_interval_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/echo-packet-input-count", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_echo_packet_input_count_get_elem, + }, + { + .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/echo-packet-output-count", + .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_echo_packet_output_count_get_elem, + }, + { + .xpath = NULL, + }, + } +}; diff --git a/bfdd/bfdd_vty.c b/bfdd/bfdd_vty.c index 6f0b85c411..befb8b0af3 100644 --- a/bfdd/bfdd_vty.c +++ b/bfdd/bfdd_vty.c @@ -34,8 +34,6 @@ /* * Commands help string definitions. */ -#define PEER_STR "Configure peer\n" -#define INTERFACE_NAME_STR "Configure interface name to use\n" #define PEER_IPV4_STR "IPv4 peer address\n" #define PEER_IPV6_STR "IPv6 peer address\n" #define MHOP_STR "Configure multihop\n" @@ -43,8 +41,6 @@ #define LOCAL_IPV4_STR "IPv4 local address\n" #define LOCAL_IPV6_STR "IPv6 local address\n" #define LOCAL_INTF_STR "Configure local interface name to use\n" -#define VRF_STR "Configure VRF\n" -#define VRF_NAME_STR "Configure VRF name\n" /* * Prototypes @@ -88,256 +84,6 @@ DEFUN_NOSH(bfd_enter, bfd_enter_cmd, "bfd", "Configure BFD peers\n") return CMD_SUCCESS; } -DEFUN_NOSH( - bfd_peer_enter, bfd_peer_enter_cmd, - "peer [{multihop|local-address |interface IFNAME|vrf NAME}]", - PEER_STR PEER_IPV4_STR PEER_IPV6_STR - MHOP_STR - LOCAL_STR LOCAL_IPV4_STR LOCAL_IPV6_STR - INTERFACE_STR - LOCAL_INTF_STR - VRF_STR VRF_NAME_STR) -{ - bool mhop; - int idx; - struct bfd_session *bs; - const char *peer, *ifname, *local, *vrfname; - struct bfd_peer_cfg bpc; - struct sockaddr_any psa, lsa, *lsap; - char errormsg[128]; - - vrfname = peer = ifname = local = NULL; - - /* Gather all provided information. */ - peer = argv[1]->arg; - - idx = 0; - mhop = argv_find(argv, argc, "multihop", &idx); - - idx = 0; - if (argv_find(argv, argc, "interface", &idx)) - ifname = argv[idx + 1]->arg; - - idx = 0; - if (argv_find(argv, argc, "local-address", &idx)) - local = argv[idx + 1]->arg; - - idx = 0; - if (argv_find(argv, argc, "vrf", &idx)) - vrfname = argv[idx + 1]->arg; - - strtosa(peer, &psa); - if (local) { - strtosa(local, &lsa); - lsap = &lsa; - } else - lsap = NULL; - - if (bfd_configure_peer(&bpc, mhop, &psa, lsap, ifname, vrfname, - errormsg, sizeof(errormsg)) - != 0) { - vty_out(vty, "%% Invalid peer configuration: %s\n", errormsg); - return CMD_WARNING_CONFIG_FAILED; - } - - bs = bs_peer_find(&bpc); - if (bs == NULL) { - bs = ptm_bfd_sess_new(&bpc); - if (bs == NULL) { - vty_out(vty, "%% Failed to add peer.\n"); - return CMD_WARNING_CONFIG_FAILED; - } - } - - if (!BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG)) { - if (bs->refcount) - vty_out(vty, "%% session peer is now configurable via bfd daemon.\n"); - BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG); - } - - VTY_PUSH_CONTEXT(BFD_PEER_NODE, bs); - - return CMD_SUCCESS; -} - -DEFPY(bfd_peer_detectmultiplier, bfd_peer_detectmultiplier_cmd, - "detect-multiplier (2-255)$multiplier", - "Configure peer detection multiplier\n" - "Configure peer detection multiplier value\n") -{ - struct bfd_session *bs; - - bs = VTY_GET_CONTEXT(bfd_session); - if (bs->detect_mult == multiplier) - return CMD_SUCCESS; - - bs->detect_mult = multiplier; - - return CMD_SUCCESS; -} - -DEFPY(bfd_peer_recvinterval, bfd_peer_recvinterval_cmd, - "receive-interval (10-60000)$interval", - "Configure peer receive interval\n" - "Configure peer receive interval value in milliseconds\n") -{ - struct bfd_session *bs; - - bs = VTY_GET_CONTEXT(bfd_session); - if (bs->timers.required_min_rx == (uint32_t)(interval * 1000)) - return CMD_SUCCESS; - - bs->timers.required_min_rx = interval * 1000; - bfd_set_polling(bs); - - return CMD_SUCCESS; -} - -DEFPY(bfd_peer_txinterval, bfd_peer_txinterval_cmd, - "transmit-interval (10-60000)$interval", - "Configure peer transmit interval\n" - "Configure peer transmit interval value in milliseconds\n") -{ - struct bfd_session *bs; - - bs = VTY_GET_CONTEXT(bfd_session); - if (bs->timers.desired_min_tx == (uint32_t)(interval * 1000)) - return CMD_SUCCESS; - - bs->timers.desired_min_tx = interval * 1000; - bfd_set_polling(bs); - - return CMD_SUCCESS; -} - -DEFPY(bfd_peer_echointerval, bfd_peer_echointerval_cmd, - "echo-interval (10-60000)$interval", - "Configure peer echo interval\n" - "Configure peer echo interval value in milliseconds\n") -{ - struct bfd_session *bs; - - bs = VTY_GET_CONTEXT(bfd_session); - if (bs->timers.required_min_echo == (uint32_t)(interval * 1000)) - return CMD_SUCCESS; - - bs->timers.required_min_echo = interval * 1000; - - return CMD_SUCCESS; -} - -DEFPY(bfd_peer_shutdown, bfd_peer_shutdown_cmd, "[no] shutdown", - NO_STR "Disable BFD peer") -{ - struct bfd_session *bs; - - bs = VTY_GET_CONTEXT(bfd_session); - if (no) { - if (!BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN)) - return CMD_SUCCESS; - - BFD_UNSET_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN); - - /* Change and notify state change. */ - bs->ses_state = PTM_BFD_DOWN; - control_notify(bs); - - /* Enable all timers. */ - bfd_recvtimer_update(bs); - bfd_xmttimer_update(bs, bs->xmt_TO); - if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO)) { - bfd_echo_recvtimer_update(bs); - bfd_echo_xmttimer_update(bs, bs->echo_xmt_TO); - } - } else { - if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN)) - return CMD_SUCCESS; - - BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN); - - /* Disable all events. */ - bfd_recvtimer_delete(bs); - bfd_echo_recvtimer_delete(bs); - bfd_xmttimer_delete(bs); - bfd_echo_xmttimer_delete(bs); - - /* Change and notify state change. */ - bs->ses_state = PTM_BFD_ADM_DOWN; - control_notify(bs); - - ptm_bfd_snd(bs, 0); - } - - return CMD_SUCCESS; -} - -DEFPY(bfd_peer_echo, bfd_peer_echo_cmd, "[no] echo-mode", - NO_STR "Configure echo mode\n") -{ - struct bfd_session *bs; - - bs = VTY_GET_CONTEXT(bfd_session); - if (no) { - if (!BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO)) - return CMD_SUCCESS; - - BFD_UNSET_FLAG(bs->flags, BFD_SESS_FLAG_ECHO); - ptm_bfd_echo_stop(bs); - } else { - if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO)) - return CMD_SUCCESS; - - BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_ECHO); - /* Apply setting immediately. */ - if (!BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN)) - bs_echo_timer_handler(bs); - } - - return CMD_SUCCESS; -} - -DEFPY(bfd_no_peer, bfd_no_peer_cmd, - "no peer $peer [{multihop|local-address $local|interface IFNAME$ifname|vrf NAME$vrfname}]", - NO_STR - PEER_STR PEER_IPV4_STR PEER_IPV6_STR - MHOP_STR - LOCAL_STR LOCAL_IPV4_STR LOCAL_IPV6_STR - INTERFACE_STR - LOCAL_INTF_STR - VRF_STR VRF_NAME_STR) -{ - int idx; - bool mhop; - struct bfd_peer_cfg bpc; - struct sockaddr_any psa, lsa, *lsap; - char errormsg[128]; - - strtosa(peer_str, &psa); - if (local) { - strtosa(local_str, &lsa); - lsap = &lsa; - } else { - lsap = NULL; - } - - idx = 0; - mhop = argv_find(argv, argc, "multihop", &idx); - - if (bfd_configure_peer(&bpc, mhop, &psa, lsap, ifname, vrfname, - errormsg, sizeof(errormsg)) - != 0) { - vty_out(vty, "%% Invalid peer configuration: %s\n", errormsg); - return CMD_WARNING_CONFIG_FAILED; - } - - if (ptm_bfd_sess_del(&bpc) != 0) { - vty_out(vty, "%% Failed to remove peer.\n"); - return CMD_WARNING_CONFIG_FAILED; - } - - return CMD_SUCCESS; -} - /* * Show commands helper functions @@ -1070,16 +816,10 @@ void bfdd_vty_init(void) /* Install BFD node and commands. */ install_node(&bfd_node, bfdd_write_config); install_default(BFD_NODE); - install_element(BFD_NODE, &bfd_peer_enter_cmd); - install_element(BFD_NODE, &bfd_no_peer_cmd); /* Install BFD peer node. */ install_node(&bfd_peer_node, bfdd_peer_write_config); install_default(BFD_PEER_NODE); - install_element(BFD_PEER_NODE, &bfd_peer_detectmultiplier_cmd); - install_element(BFD_PEER_NODE, &bfd_peer_recvinterval_cmd); - install_element(BFD_PEER_NODE, &bfd_peer_txinterval_cmd); - install_element(BFD_PEER_NODE, &bfd_peer_echointerval_cmd); - install_element(BFD_PEER_NODE, &bfd_peer_shutdown_cmd); - install_element(BFD_PEER_NODE, &bfd_peer_echo_cmd); + + bfdd_cli_init(); } diff --git a/bfdd/subdir.am b/bfdd/subdir.am index e88b982ec3..353667349f 100644 --- a/bfdd/subdir.am +++ b/bfdd/subdir.am @@ -7,12 +7,15 @@ noinst_LIBRARIES += bfdd/libbfd.a sbin_PROGRAMS += bfdd/bfdd dist_examples_DATA += bfdd/bfdd.conf.sample vtysh_scan += $(top_srcdir)/bfdd/bfdd_vty.c +vtysh_scan += $(top_srcdir)/bfdd/bfdd_cli.c man8 += $(MANBUILD)/bfdd.8 endif bfdd_libbfd_a_SOURCES = \ bfdd/bfd.c \ + bfdd/bfdd_northbound.c \ bfdd/bfdd_vty.c \ + bfdd/bfdd_cli.c \ bfdd/bfd_packet.c \ bfdd/config.c \ bfdd/control.c \ @@ -24,6 +27,9 @@ bfdd_libbfd_a_SOURCES = \ bfdd/bfdd_vty_clippy.c: $(CLIPPY_DEPS) bfdd/bfdd_vty.$(OBJEXT): bfdd/bfdd_vty_clippy.c +bfdd/bfdd_cli_clippy.c: $(CLIPPY_DEPS) +bfdd/bfdd_cli.$(OBJEXT): bfdd/bfdd_cli_clippy.c + noinst_HEADERS += \ bfdd/bfdctl.h \ bfdd/bfd.h \ diff --git a/yang/subdir.am b/yang/subdir.am index c95ec4dbff..4b3baeea9d 100644 --- a/yang/subdir.am +++ b/yang/subdir.am @@ -24,6 +24,10 @@ dist_yangmodels_DATA += yang/frr-test-module.yang dist_yangmodels_DATA += yang/frr-interface.yang dist_yangmodels_DATA += yang/frr-route-types.yang +if BFDD +dist_yangmodels_DATA += yang/frr-bfdd.yang +endif + if RIPD dist_yangmodels_DATA += yang/frr-ripd.yang endif From 0287a64a6ecf653d0c8be9212d34822ffe3e592e Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Sat, 25 May 2019 11:36:46 -0300 Subject: [PATCH 06/21] bfdd: implement write_config using northbound Move all the `show running-config` logic to the new northbound implementation. Signed-off-by: Rafael Zalamena --- bfdd/bfd.h | 23 ++++++++ bfdd/bfdd_cli.c | 123 +++++++++++++++++++++++++++++++++++++++++ bfdd/bfdd_northbound.c | 14 +++++ bfdd/bfdd_vty.c | 93 ++++++------------------------- 4 files changed, 176 insertions(+), 77 deletions(-) diff --git a/bfdd/bfd.h b/bfdd/bfd.h index 7568583f96..78b21a9b6f 100644 --- a/bfdd/bfd.h +++ b/bfdd/bfd.h @@ -596,6 +596,29 @@ void bfdd_vty_init(void); */ void bfdd_cli_init(void); +void bfd_cli_show_header(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void bfd_cli_show_header_end(struct vty *vty, struct lyd_node *dnode); +void bfd_cli_show_single_hop_peer(struct vty *vty, + struct lyd_node *dnode, + bool show_defaults); +void bfd_cli_show_multi_hop_peer(struct vty *vty, + struct lyd_node *dnode, + bool show_defaults); +void bfd_cli_show_peer_end(struct vty *vty, struct lyd_node *dnode); +void bfd_cli_show_mult(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void bfd_cli_show_tx(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void bfd_cli_show_rx(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void bfd_cli_show_shutdown(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void bfd_cli_show_echo(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); +void bfd_cli_show_echo_interval(struct vty *vty, struct lyd_node *dnode, + bool show_defaults); + /* * ptm_adapter.c diff --git a/bfdd/bfdd_cli.c b/bfdd/bfdd_cli.c index 200ae543c7..dac1c2521d 100644 --- a/bfdd/bfdd_cli.c +++ b/bfdd/bfdd_cli.c @@ -52,6 +52,19 @@ /* * Functions. */ +void bfd_cli_show_header(struct vty *vty, + struct lyd_node *dnode __attribute__((__unused__)), + bool show_defaults __attribute__((__unused__))) +{ + vty_out(vty, "!\nbfd\n"); +} + +void bfd_cli_show_header_end(struct vty *vty, + struct lyd_node *dnode __attribute__((__unused__))) +{ + vty_out(vty, "!\n"); +} + DEFPY_NOSH( bfd_peer_enter, bfd_peer_enter_cmd, "peer [{multihop$multihop|local-address |interface IFNAME$ifname|vrf NAME}]", @@ -151,6 +164,52 @@ DEFPY( return nb_cli_apply_changes(vty, NULL); } +static void _bfd_cli_show_peer(struct vty *vty, struct lyd_node *dnode, + bool show_defaults __attribute__((__unused__)), + bool mhop) +{ + const char *vrf = yang_dnode_get_string(dnode, "./vrf"); + const char *ifname = yang_dnode_get_string(dnode, "./interface"); + + vty_out(vty, " peer %s", + yang_dnode_get_string(dnode, "./dest-addr")); + + if (mhop) + vty_out(vty, " multihop"); + + if (yang_dnode_exists(dnode, "./source-addr")) + vty_out(vty, " local-address %s", + yang_dnode_get_string(dnode, "./source-addr")); + + if (strcmp(vrf, VRF_DEFAULT_NAME)) + vty_out(vty, " vrf %s", vrf); + + if (ifname[0]) + vty_out(vty, " interface %s", ifname); + + vty_out(vty, "\n"); +} + +void bfd_cli_show_single_hop_peer(struct vty *vty, + struct lyd_node *dnode, + bool show_defaults) +{ + _bfd_cli_show_peer(vty, dnode, show_defaults, false); +} + +void bfd_cli_show_multi_hop_peer(struct vty *vty, + struct lyd_node *dnode, + bool show_defaults) +{ + _bfd_cli_show_peer(vty, dnode, show_defaults, true); +} + +void bfd_cli_show_peer_end(struct vty *vty, + struct lyd_node *dnode __attribute__((__unused__))) +{ + vty_out(vty, " !\n"); +} + DEFPY( bfd_peer_shutdown, bfd_peer_shutdown_cmd, "[no] shutdown", @@ -162,6 +221,16 @@ DEFPY( return nb_cli_apply_changes(vty, NULL); } +void bfd_cli_show_shutdown(struct vty *vty, struct lyd_node *dnode, + bool show_defaults) +{ + if (show_defaults) + vty_out(vty, " shutdown\n"); + else + vty_out(vty, " %sshutdown\n", + yang_dnode_get_bool(dnode, NULL) ? "" : "no "); +} + DEFPY( bfd_peer_mult, bfd_peer_mult_cmd, "detect-multiplier (2-255)$multiplier", @@ -173,6 +242,17 @@ DEFPY( return nb_cli_apply_changes(vty, NULL); } +void bfd_cli_show_mult(struct vty *vty, struct lyd_node *dnode, + bool show_defaults) +{ + if (show_defaults) + vty_out(vty, " detect-multiplier %d\n", + BFD_DEFDETECTMULT); + else + vty_out(vty, " detect-multiplier %s\n", + yang_dnode_get_string(dnode, NULL)); +} + DEFPY( bfd_peer_rx, bfd_peer_rx_cmd, "receive-interval (10-60000)$interval", @@ -184,6 +264,17 @@ DEFPY( return nb_cli_apply_changes(vty, NULL); } +void bfd_cli_show_rx(struct vty *vty, struct lyd_node *dnode, + bool show_defaults) +{ + if (show_defaults) + vty_out(vty, " receive-interval %d\n", + BFD_DEFREQUIREDMINRX); + else + vty_out(vty, " receive-interval %s\n", + yang_dnode_get_string(dnode, NULL)); +} + DEFPY( bfd_peer_tx, bfd_peer_tx_cmd, "transmit-interval (10-60000)$interval", @@ -195,6 +286,17 @@ DEFPY( return nb_cli_apply_changes(vty, NULL); } +void bfd_cli_show_tx(struct vty *vty, struct lyd_node *dnode, + bool show_defaults) +{ + if (show_defaults) + vty_out(vty, " transmit-interval %d\n", + BFD_DEFDESIREDMINTX); + else + vty_out(vty, " transmit-interval %s\n", + yang_dnode_get_string(dnode, NULL)); +} + DEFPY( bfd_peer_echo, bfd_peer_echo_cmd, "[no] echo-mode", @@ -206,6 +308,16 @@ DEFPY( return nb_cli_apply_changes(vty, NULL); } +void bfd_cli_show_echo(struct vty *vty, struct lyd_node *dnode, + bool show_defaults) +{ + if (show_defaults) + vty_out(vty, " no echo-mode\n"); + else + vty_out(vty, " %secho-mode\n", + yang_dnode_get_bool(dnode, NULL) ? "" : "no "); +} + DEFPY( bfd_peer_echo_interval, bfd_peer_echo_interval_cmd, "echo-interval (10-60000)$interval", @@ -217,6 +329,17 @@ DEFPY( return nb_cli_apply_changes(vty, NULL); } +void bfd_cli_show_echo_interval(struct vty *vty, struct lyd_node *dnode, + bool show_defaults) +{ + if (show_defaults) + vty_out(vty, " echo-interval %d\n", + BFD_DEF_REQ_MIN_ECHO); + else + vty_out(vty, " echo-interval %s\n", + yang_dnode_get_string(dnode, NULL)); +} + void bfdd_cli_init(void) { diff --git a/bfdd/bfdd_northbound.c b/bfdd/bfdd_northbound.c index a22430e6b7..bbc39fc9c4 100644 --- a/bfdd/bfdd_northbound.c +++ b/bfdd/bfdd_northbound.c @@ -839,6 +839,8 @@ const struct frr_yang_module_info frr_bfdd_info = { .cbs.get_next = bfdd_bfd_sessions_single_hop_get_next, .cbs.get_keys = bfdd_bfd_sessions_single_hop_get_keys, .cbs.lookup_entry = bfdd_bfd_sessions_single_hop_lookup_entry, + .cbs.cli_show = bfd_cli_show_single_hop_peer, + .cbs.cli_show_end = bfd_cli_show_peer_end, }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/source-addr", @@ -848,26 +850,32 @@ const struct frr_yang_module_info frr_bfdd_info = { { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/detection-multiplier", .cbs.modify = bfdd_bfd_sessions_single_hop_detection_multiplier_modify, + .cbs.cli_show = bfd_cli_show_mult, }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/desired-transmission-interval", .cbs.modify = bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify, + .cbs.cli_show = bfd_cli_show_tx, }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/required-receive-interval", .cbs.modify = bfdd_bfd_sessions_single_hop_required_receive_interval_modify, + .cbs.cli_show = bfd_cli_show_rx, }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/administrative-down", .cbs.modify = bfdd_bfd_sessions_single_hop_administrative_down_modify, + .cbs.cli_show = bfd_cli_show_shutdown, }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/echo-mode", .cbs.modify = bfdd_bfd_sessions_single_hop_echo_mode_modify, + .cbs.cli_show = bfd_cli_show_echo, }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/desired-echo-transmission-interval", .cbs.modify = bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify, + .cbs.cli_show = bfd_cli_show_echo_interval, }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-discriminator", @@ -956,22 +964,28 @@ const struct frr_yang_module_info frr_bfdd_info = { .cbs.get_next = bfdd_bfd_sessions_multi_hop_get_next, .cbs.get_keys = bfdd_bfd_sessions_multi_hop_get_keys, .cbs.lookup_entry = bfdd_bfd_sessions_multi_hop_lookup_entry, + .cbs.cli_show = bfd_cli_show_multi_hop_peer, + .cbs.cli_show_end = bfd_cli_show_peer_end, }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/detection-multiplier", .cbs.modify = bfdd_bfd_sessions_single_hop_detection_multiplier_modify, + .cbs.cli_show = bfd_cli_show_mult, }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/desired-transmission-interval", .cbs.modify = bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify, + .cbs.cli_show = bfd_cli_show_tx, }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/required-receive-interval", .cbs.modify = bfdd_bfd_sessions_single_hop_required_receive_interval_modify, + .cbs.cli_show = bfd_cli_show_rx, }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/administrative-down", .cbs.modify = bfdd_bfd_sessions_single_hop_administrative_down_modify, + .cbs.cli_show = bfd_cli_show_shutdown, }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/local-discriminator", diff --git a/bfdd/bfdd_vty.c b/bfdd/bfdd_vty.c index befb8b0af3..130c117365 100644 --- a/bfdd/bfdd_vty.c +++ b/bfdd/bfdd_vty.c @@ -23,6 +23,7 @@ #include "lib/command.h" #include "lib/json.h" #include "lib/log.h" +#include "lib/northbound_cli.h" #include "lib/vty.h" #include "bfd.h" @@ -45,10 +46,6 @@ /* * Prototypes */ -static int bfdd_write_config(struct vty *vty); -static int bfdd_peer_write_config(struct vty *vty); -static void _bfdd_peer_write_config(struct vty *vty, struct bfd_session *bs); -static void _bfdd_peer_write_config_iter(struct hash_bucket *hb, void *arg); static int bfd_configure_peer(struct bfd_peer_cfg *bpc, bool mhop, const struct sockaddr_any *peer, const struct sockaddr_any *local, @@ -707,60 +704,6 @@ static int bfd_configure_peer(struct bfd_peer_cfg *bpc, bool mhop, return 0; } -static int bfdd_write_config(struct vty *vty) -{ - vty_out(vty, "bfd\n"); - vty_out(vty, "!\n"); - return 0; -} - -static void _bfdd_peer_write_config(struct vty *vty, struct bfd_session *bs) -{ - char addr_buf[INET6_ADDRSTRLEN]; - - vty_out(vty, " peer %s", - inet_ntop(bs->key.family, &bs->key.peer, addr_buf, - sizeof(addr_buf))); - - if (bs->key.mhop) - vty_out(vty, " multihop"); - - if (memcmp(&bs->key.local, &zero_addr, sizeof(bs->key.local))) - vty_out(vty, " local-address %s", - inet_ntop(bs->key.family, &bs->key.local, addr_buf, - sizeof(addr_buf))); - - if (bs->key.vrfname[0]) - vty_out(vty, " vrf %s", bs->key.vrfname); - if (bs->key.ifname[0]) - vty_out(vty, " interface %s", bs->key.ifname); - vty_out(vty, "\n"); - - if (bs->sock == -1) - vty_out(vty, - " ! vrf, interface or local-address doesn't exist\n"); - - if (bs->detect_mult != BPC_DEF_DETECTMULTIPLIER) - vty_out(vty, " detect-multiplier %d\n", bs->detect_mult); - if (bs->timers.required_min_rx != (BPC_DEF_RECEIVEINTERVAL * 1000)) - vty_out(vty, " receive-interval %" PRIu32 "\n", - bs->timers.required_min_rx / 1000); - if (bs->timers.desired_min_tx != (BPC_DEF_TRANSMITINTERVAL * 1000)) - vty_out(vty, " transmit-interval %" PRIu32 "\n", - bs->timers.desired_min_tx / 1000); - if (bs->timers.required_min_echo != (BPC_DEF_ECHOINTERVAL * 1000)) - vty_out(vty, " echo-interval %" PRIu32 "\n", - bs->timers.required_min_echo / 1000); - if (bs->pl) - vty_out(vty, " label %s\n", bs->pl->pl_label); - if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_ECHO)) - vty_out(vty, " echo-mode\n"); - - vty_out(vty, " %sshutdown\n", - BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_SHUTDOWN) ? "" : "no "); - - vty_out(vty, " !\n"); -} DEFUN_NOSH(show_debugging_bfd, show_debugging_bfd_cmd, @@ -774,24 +717,6 @@ DEFUN_NOSH(show_debugging_bfd, return CMD_SUCCESS; } -static void _bfdd_peer_write_config_iter(struct hash_bucket *hb, void *arg) -{ - struct vty *vty = arg; - struct bfd_session *bs = hb->data; - - if (!BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG)) - return; - - _bfdd_peer_write_config(vty, bs); -} - -static int bfdd_peer_write_config(struct vty *vty) -{ - bfd_id_iterate(_bfdd_peer_write_config_iter, vty); - - return 1; -} - struct cmd_node bfd_node = { BFD_NODE, "%s(config-bfd)# ", @@ -804,6 +729,20 @@ struct cmd_node bfd_peer_node = { 1, }; +static int bfdd_write_config(struct vty *vty) +{ + struct lyd_node *dnode; + int written = 0; + + dnode = yang_dnode_get(running_config->dnode, "/frr-bfdd:bfdd"); + if (dnode) { + nb_cli_show_dnode_cmds(vty, dnode, false); + written = 1; + } + + return written; +} + void bfdd_vty_init(void) { install_element(ENABLE_NODE, &bfd_show_peers_counters_cmd); @@ -818,7 +757,7 @@ void bfdd_vty_init(void) install_default(BFD_NODE); /* Install BFD peer node. */ - install_node(&bfd_peer_node, bfdd_peer_write_config); + install_node(&bfd_peer_node, NULL); install_default(BFD_PEER_NODE); bfdd_cli_init(); From 0030482f5ecdbab54ee607908b70ce3022728380 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Wed, 29 May 2019 17:17:37 -0300 Subject: [PATCH 07/21] bfdd: fix northbound remote-discriminator display When the remote discriminator hasn't been assigned yet, then we can't return a value of 0. The value '0' is an invalid discriminator and the yang handlers will complain about it. Signed-off-by: Rafael Zalamena --- bfdd/bfdd_northbound.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bfdd/bfdd_northbound.c b/bfdd/bfdd_northbound.c index bbc39fc9c4..4b21a21162 100644 --- a/bfdd/bfdd_northbound.c +++ b/bfdd/bfdd_northbound.c @@ -546,6 +546,9 @@ bfdd_bfd_sessions_single_hop_stats_remote_discriminator_get_elem( { const struct bfd_session *bs = list_entry; + if (bs->discrs.remote_discr == 0) + return NULL; + return yang_data_new_uint32(xpath, bs->discrs.remote_discr); } From 49cc9e7b64473f5ebc3a3e117a44dce3389d02df Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Thu, 30 May 2019 15:14:50 -0300 Subject: [PATCH 08/21] bfdd: implement configuration reload Reload configuration on SIGHUP using the northbound. Signed-off-by: Rafael Zalamena --- bfdd/bfdd.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/bfdd/bfdd.c b/bfdd/bfdd.c index 5a6089f384..5657744f75 100644 --- a/bfdd/bfdd.c +++ b/bfdd/bfdd.c @@ -39,6 +39,9 @@ struct thread_master *master; /* BFDd privileges */ static zebra_capabilities_t _caps_p[] = {ZCAP_BIND, ZCAP_SYS_ADMIN, ZCAP_NET_RAW}; +/* BFD daemon information. */ +static struct frr_daemon_info bfdd_di; + void socket_close(int *s) { if (*s <= 0) @@ -78,6 +81,14 @@ static void sigterm_handler(void) exit(0); } +static void sighup_handler(void) +{ + zlog_info("SIGHUP received"); + + /* Reload config file. */ + vty_read_config(NULL, bfdd_di.config_file, config_default); +} + static struct quagga_signal_t bfd_signals[] = { { .signal = SIGUSR1, @@ -91,6 +102,10 @@ static struct quagga_signal_t bfd_signals[] = { .signal = SIGINT, .handler = &sigterm_handler, }, + { + .signal = SIGHUP, + .handler = &sighup_handler, + }, }; static const struct frr_yang_module_info *bfdd_yang_modules[] = { From 47a7b00c2d4eb6cf65ca1a2d11e5078d64d465d0 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Thu, 30 May 2019 17:03:57 -0300 Subject: [PATCH 09/21] bfdd: fix daemon warning on startup ``` warnings: BFD: [EC 100663317] YANG model "frr-bfdd@*" not embedded, trying external file ``` Embed the YANG model into the binary to avoid reading an external file. Signed-off-by: Rafael Zalamena --- bfdd/subdir.am | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bfdd/subdir.am b/bfdd/subdir.am index 353667349f..5e3c3d4765 100644 --- a/bfdd/subdir.am +++ b/bfdd/subdir.am @@ -35,5 +35,9 @@ noinst_HEADERS += \ bfdd/bfd.h \ # end +nodist_bfdd_bfdd_SOURCES = \ + yang/frr-bfdd.yang.c \ + # end + bfdd_bfdd_SOURCES = bfdd/bfdd.c bfdd_bfdd_LDADD = bfdd/libbfd.a lib/libfrr.la From 2a573ff672f4b0eb76138362403a680bc9fc7fce Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Fri, 31 May 2019 16:48:25 -0300 Subject: [PATCH 10/21] bfdd: support global BFD reset Add command 'no bfd' to remove all BFD sessions configuration and fix other daemon integration. Signed-off-by: Rafael Zalamena --- bfdd/bfd.c | 30 +++++++++++++++++++++ bfdd/bfd.h | 1 + bfdd/bfdd_cli.c | 12 +++++++++ bfdd/bfdd_northbound.c | 60 ++++++++++++++++++++++++++++++++++++++---- 4 files changed, 98 insertions(+), 5 deletions(-) diff --git a/bfdd/bfd.c b/bfdd/bfd.c index 828059eb4a..fc9d033437 100644 --- a/bfdd/bfd.c +++ b/bfdd/bfd.c @@ -1290,6 +1290,7 @@ static unsigned int bfd_key_hash_do(const void *p); static void _bfd_free(struct hash_bucket *hb, void *arg __attribute__((__unused__))); int _bfd_session_next(struct hash_bucket *hb, void *arg); +void _bfd_session_remove_manual(struct hash_bucket *hb, void *arg); /* BFD hash for our discriminator. */ static unsigned int bfd_id_hash_do(const void *p) @@ -1587,6 +1588,35 @@ const struct bfd_session *bfd_session_next(const struct bfd_session *bs, return bsi.bsi_bs; } +void _bfd_session_remove_manual(struct hash_bucket *hb, + void *arg __attribute__((__unused__))) +{ + struct bfd_session *bs = hb->data; + + /* Delete only manually configured sessions. */ + if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG) == 0) + return; + + bs->refcount--; + BFD_UNSET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG); + + /* Don't delete sessions still in use. */ + if (bs->refcount != 0) + return; + + bfd_session_free(bs); +} + +/* + * bfd_sessions_remove_manual: remove all manually configured sessions. + * + * NOTE: this function doesn't remove automatically created sessions. + */ +void bfd_sessions_remove_manual(void) +{ + hash_iterate(bfd_key_hash, _bfd_session_remove_manual, NULL); +} + /* * VRF related functions. */ diff --git a/bfdd/bfd.h b/bfdd/bfd.h index 78b21a9b6f..10aeb3e52c 100644 --- a/bfdd/bfd.h +++ b/bfdd/bfd.h @@ -550,6 +550,7 @@ struct bfd_session *bs_registrate(struct bfd_session *bs); void bfd_session_free(struct bfd_session *bs); const struct bfd_session *bfd_session_next(const struct bfd_session *bs, bool mhop); +void bfd_sessions_remove_manual(void); /* BFD hash data structures interface */ void bfd_initialize(void); diff --git a/bfdd/bfdd_cli.c b/bfdd/bfdd_cli.c index dac1c2521d..64500cef7d 100644 --- a/bfdd/bfdd_cli.c +++ b/bfdd/bfdd_cli.c @@ -52,6 +52,16 @@ /* * Functions. */ +DEFUN( + bfd_config_reset, bfd_config_reset_cmd, + "no bfd", + NO_STR + "Configure BFD peers\n") +{ + nb_cli_enqueue_change(vty, "/frr-bfdd:bfdd/bfd", NB_OP_DESTROY, NULL); + return nb_cli_apply_changes(vty, NULL); +} + void bfd_cli_show_header(struct vty *vty, struct lyd_node *dnode __attribute__((__unused__)), bool show_defaults __attribute__((__unused__))) @@ -343,6 +353,8 @@ void bfd_cli_show_echo_interval(struct vty *vty, struct lyd_node *dnode, void bfdd_cli_init(void) { + install_element(CONFIG_NODE, &bfd_config_reset_cmd); + install_element(BFD_NODE, &bfd_peer_enter_cmd); install_element(BFD_NODE, &bfd_no_peer_cmd); diff --git a/bfdd/bfdd_northbound.c b/bfdd/bfdd_northbound.c index 4b21a21162..fd007b57b2 100644 --- a/bfdd/bfdd_northbound.c +++ b/bfdd/bfdd_northbound.c @@ -71,11 +71,27 @@ int bfd_session_create(enum nb_event event, const struct lyd_node *dnode, switch (event) { case NB_EV_VALIDATE: bfd_session_get_key(mhop, dnode, &bk); - if (bfd_key_lookup(bk)) + bs = bfd_key_lookup(bk); + + /* This session was already configured by CLI. */ + if (bs != NULL && BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG)) return NB_ERR_VALIDATION; break; case NB_EV_PREPARE: + bfd_session_get_key(mhop, dnode, &bk); + bs = bfd_key_lookup(bk); + + /* This session was already configured by another daemon. */ + if (bs != NULL) { + /* Now it is configured also by CLI. */ + BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG); + bs->refcount++; + + resource->ptr = bs; + break; + } + bs = bfd_session_new(); if (bs == NULL) return NB_ERR_RESOURCE; @@ -84,6 +100,7 @@ int bfd_session_create(enum nb_event event, const struct lyd_node *dnode, bfd_session_get_key(mhop, dnode, &bs->key); /* Set configuration flags. */ + bs->refcount = 1; BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG); if (mhop) BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_MH); @@ -95,14 +112,18 @@ int bfd_session_create(enum nb_event event, const struct lyd_node *dnode, case NB_EV_APPLY: bs = resource->ptr; - if (bs_registrate(bs) == NULL) + + /* Only attempt to registrate if freshly allocated. */ + if (bs->discrs.my_discr == 0 && bs_registrate(bs) == NULL) return NB_ERR_RESOURCE; nb_running_set_entry(dnode, bs); break; case NB_EV_ABORT: - bfd_session_free(resource->ptr); + bs = resource->ptr; + if (bs->refcount <= 1) + bfd_session_free(resource->ptr); break; } @@ -112,6 +133,7 @@ int bfd_session_create(enum nb_event event, const struct lyd_node *dnode, int bfd_session_destroy(enum nb_event event, const struct lyd_node *dnode, bool mhop) { + struct bfd_session *bs; struct bfd_key bk; switch (event) { @@ -126,7 +148,18 @@ int bfd_session_destroy(enum nb_event event, const struct lyd_node *dnode, break; case NB_EV_APPLY: - bfd_session_free(nb_running_unset_entry(dnode)); + bs = nb_running_unset_entry(dnode); + /* CLI is not using this session anymore. */ + if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG) == 0) + break; + + BFD_UNSET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG); + bs->refcount--; + /* There are still daemons using it. */ + if (bs->refcount > 0) + break; + + bfd_session_free(bs); break; case NB_EV_ABORT: @@ -152,7 +185,24 @@ static int bfdd_bfd_create(enum nb_event event, static int bfdd_bfd_destroy(enum nb_event event, const struct lyd_node *dnode) { - /* NOTHING */ + switch (event) { + case NB_EV_VALIDATE: + /* NOTHING */ + return NB_OK; + + case NB_EV_PREPARE: + /* NOTHING */ + return NB_OK; + + case NB_EV_APPLY: + bfd_sessions_remove_manual(); + break; + + case NB_EV_ABORT: + /* NOTHING */ + return NB_OK; + } + return NB_OK; } From 020a3906495ee68b8d070efa2f2d79e26363c67e Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Mon, 3 Jun 2019 11:11:34 -0300 Subject: [PATCH 11/21] lib: fix northbound static analyzer warning Make the function parameter `const` so the analyzer doesn't suspect we are trying to change its value. Signed-off-by: Rafael Zalamena --- lib/northbound_cli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/northbound_cli.c b/lib/northbound_cli.c index c96bfbdb91..c691bb27aa 100644 --- a/lib/northbound_cli.c +++ b/lib/northbound_cli.c @@ -440,7 +440,7 @@ static int nb_cli_candidate_load_transaction(struct vty *vty, * This function detects whether next node in the iteration is upwards, * then return the node otherwise return NULL. */ -static struct lyd_node *ly_iter_next_up(struct lyd_node *elem) +static struct lyd_node *ly_iter_next_up(const struct lyd_node *elem) { /* Are we going downwards? Is this still not a leaf? */ if (!(elem->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA))) From 8a676ce6b13eeec581856471d543d92aae2392f6 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Wed, 12 Jun 2019 18:05:19 -0300 Subject: [PATCH 12/21] bfdd: use microseconds timers in YANG Lets allow specification to accept microseconds, but limit the timers configuration in FRR to milliseconds (minimum is 10 ms and maximum is 60 seconds). This matches the RFC 5880 and the IETF BFD YANG draft model. Signed-off-by: Rafael Zalamena --- bfdd/bfdd_cli.c | 45 +++++++++++++++++++++++++++++++----------- bfdd/bfdd_northbound.c | 21 ++++++-------------- yang/frr-bfdd.yang | 18 ++++++++--------- 3 files changed, 48 insertions(+), 36 deletions(-) diff --git a/bfdd/bfdd_cli.c b/bfdd/bfdd_cli.c index 64500cef7d..29b77a409a 100644 --- a/bfdd/bfdd_cli.c +++ b/bfdd/bfdd_cli.c @@ -269,20 +269,27 @@ DEFPY( "Configure peer receive interval\n" "Configure peer receive interval value in milliseconds\n") { + char value[32]; + + snprintf(value, sizeof(value), "%ld", interval * 1000); nb_cli_enqueue_change(vty, "./required-receive-interval", NB_OP_MODIFY, - interval_str); + value); + return nb_cli_apply_changes(vty, NULL); } void bfd_cli_show_rx(struct vty *vty, struct lyd_node *dnode, bool show_defaults) { + uint32_t value; + if (show_defaults) vty_out(vty, " receive-interval %d\n", BFD_DEFREQUIREDMINRX); - else - vty_out(vty, " receive-interval %s\n", - yang_dnode_get_string(dnode, NULL)); + else { + value = yang_dnode_get_uint32(dnode, NULL); + vty_out(vty, " receive-interval %" PRIu32 "\n", value / 1000); + } } DEFPY( @@ -291,20 +298,27 @@ DEFPY( "Configure peer transmit interval\n" "Configure peer transmit interval value in milliseconds\n") { + char value[32]; + + snprintf(value, sizeof(value), "%ld", interval * 1000); nb_cli_enqueue_change(vty, "./desired-transmission-interval", - NB_OP_MODIFY, interval_str); + NB_OP_MODIFY, value); + return nb_cli_apply_changes(vty, NULL); } void bfd_cli_show_tx(struct vty *vty, struct lyd_node *dnode, bool show_defaults) { + uint32_t value; + if (show_defaults) vty_out(vty, " transmit-interval %d\n", BFD_DEFDESIREDMINTX); - else - vty_out(vty, " transmit-interval %s\n", - yang_dnode_get_string(dnode, NULL)); + else { + value = yang_dnode_get_uint32(dnode, NULL); + vty_out(vty, " transmit-interval %" PRIu32 "\n", value / 1000); + } } DEFPY( @@ -334,20 +348,27 @@ DEFPY( "Configure peer echo interval\n" "Configure peer echo interval value in milliseconds\n") { + char value[32]; + + snprintf(value, sizeof(value), "%ld", interval * 1000); nb_cli_enqueue_change(vty, "./desired-echo-transmission-interval", - NB_OP_MODIFY, interval_str); + NB_OP_MODIFY, value); + return nb_cli_apply_changes(vty, NULL); } void bfd_cli_show_echo_interval(struct vty *vty, struct lyd_node *dnode, bool show_defaults) { + uint32_t value; + if (show_defaults) vty_out(vty, " echo-interval %d\n", BFD_DEF_REQ_MIN_ECHO); - else - vty_out(vty, " echo-interval %s\n", - yang_dnode_get_string(dnode, NULL)); + else { + value = yang_dnode_get_uint32(dnode, NULL); + vty_out(vty, " echo-interval %" PRIu32 "\n", value / 1000); + } } void diff --git a/bfdd/bfdd_northbound.c b/bfdd/bfdd_northbound.c index fd007b57b2..24fdfa1ea2 100644 --- a/bfdd/bfdd_northbound.c +++ b/bfdd/bfdd_northbound.c @@ -327,7 +327,7 @@ static int bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify( switch (event) { case NB_EV_VALIDATE: - if (tx_interval < 10 || tx_interval > 60000) + if (tx_interval < 10000 || tx_interval > 60000000) return NB_ERR_VALIDATION; break; @@ -337,8 +337,6 @@ static int bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify( case NB_EV_APPLY: bs = nb_running_get_entry(dnode, NULL, true); - - tx_interval *= 1000; if (tx_interval == bs->timers.desired_min_tx) return NB_OK; @@ -366,7 +364,7 @@ static int bfdd_bfd_sessions_single_hop_required_receive_interval_modify( switch (event) { case NB_EV_VALIDATE: - if (rx_interval < 10 || rx_interval > 60000) + if (rx_interval < 10000 || rx_interval > 60000000) return NB_ERR_VALIDATION; break; @@ -376,8 +374,6 @@ static int bfdd_bfd_sessions_single_hop_required_receive_interval_modify( case NB_EV_APPLY: bs = nb_running_get_entry(dnode, NULL, true); - - rx_interval *= 1000; if (rx_interval == bs->timers.required_min_rx) return NB_OK; @@ -513,7 +509,7 @@ bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify( switch (event) { case NB_EV_VALIDATE: - if (echo_interval < 10 || echo_interval > 60000) + if (echo_interval < 10000 || echo_interval > 60000000) return NB_ERR_VALIDATION; break; @@ -523,8 +519,6 @@ bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify( case NB_EV_APPLY: bs = nb_running_get_entry(dnode, NULL, true); - - echo_interval *= 1000; if (echo_interval == bs->timers.required_min_echo) return NB_OK; @@ -648,8 +642,7 @@ bfdd_bfd_sessions_single_hop_stats_negotiated_transmission_interval_get_elem( { const struct bfd_session *bs = list_entry; - return yang_data_new_uint32(xpath, - bs->remote_timers.desired_min_tx / 1000); + return yang_data_new_uint32(xpath, bs->remote_timers.desired_min_tx); } /* @@ -662,8 +655,7 @@ bfdd_bfd_sessions_single_hop_stats_negotiated_receive_interval_get_elem( { const struct bfd_session *bs = list_entry; - return yang_data_new_uint32(xpath, - bs->remote_timers.required_min_rx / 1000); + return yang_data_new_uint32(xpath, bs->remote_timers.required_min_rx); } /* @@ -785,8 +777,7 @@ bfdd_bfd_sessions_single_hop_stats_negotiated_echo_transmission_interval_get_ele { const struct bfd_session *bs = list_entry; - return yang_data_new_uint32(xpath, - bs->remote_timers.required_min_echo / 1000); + return yang_data_new_uint32(xpath, bs->remote_timers.required_min_echo); } /* diff --git a/yang/frr-bfdd.yang b/yang/frr-bfdd.yang index 4fb857e6d1..4604f747c6 100644 --- a/yang/frr-bfdd.yang +++ b/yang/frr-bfdd.yang @@ -128,15 +128,15 @@ module frr-bfdd { leaf desired-transmission-interval { type uint32; - units milliseconds; - default 300; + units microseconds; + default 300000; description "Minimum desired control packet transmission interval"; } leaf required-receive-interval { type uint32; - units milliseconds; - default 300; + units microseconds; + default 300000; description "Minimum required control packet receive interval"; } @@ -158,8 +158,8 @@ module frr-bfdd { leaf desired-echo-transmission-interval { type uint32; - units milliseconds; - default 50; + units microseconds; + default 50000; description "Minimum desired control packet transmission interval"; } } @@ -217,13 +217,13 @@ module frr-bfdd { leaf negotiated-transmission-interval { description "Negotiated transmit interval"; type uint32; - units milliseconds; + units microseconds; } leaf negotiated-receive-interval { description "Negotiated receive interval"; type uint32; - units milliseconds; + units microseconds; } leaf detection-mode { @@ -287,7 +287,7 @@ module frr-bfdd { */ leaf negotiated-echo-transmission-interval { type uint32; - units milliseconds; + units microseconds; description "Negotiated echo transmit interval"; } From 7818c5fba052c0c2fdfaa2620404178167e9c103 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Fri, 14 Jun 2019 13:50:54 +0200 Subject: [PATCH 13/21] bfdd: add not '\n' to shutdown help string help string had not a '\n' at the end of the line for bfd shutdown help command. Signed-off-by: Philippe Guibert --- bfdd/bfdd_cli.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bfdd/bfdd_cli.c b/bfdd/bfdd_cli.c index 29b77a409a..7e14997823 100644 --- a/bfdd/bfdd_cli.c +++ b/bfdd/bfdd_cli.c @@ -224,7 +224,7 @@ DEFPY( bfd_peer_shutdown, bfd_peer_shutdown_cmd, "[no] shutdown", NO_STR - "Disable BFD peer") + "Disable BFD peer\n") { nb_cli_enqueue_change(vty, "./administrative-down", NB_OP_MODIFY, no ? "false" : "true"); From f7bb830439fe41efe2401ae84c63d865dee5ccf8 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Fri, 14 Jun 2019 15:16:31 +0200 Subject: [PATCH 14/21] bfdd: authorise multihop and interface setting the restriction to authorise multihop and interface setting has no meaning here. Signed-off-by: Philippe Guibert --- bfdd/bfdd_vty.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/bfdd/bfdd_vty.c b/bfdd/bfdd_vty.c index 130c117365..c3ca7a43f1 100644 --- a/bfdd/bfdd_vty.c +++ b/bfdd/bfdd_vty.c @@ -678,12 +678,6 @@ static int bfd_configure_peer(struct bfd_peer_cfg *bpc, bool mhop, /* Handle interface specification configuration. */ if (ifname) { - if (bpc->bpc_mhop) { - snprintf(ebuf, ebuflen, - "multihop doesn't accept interface names"); - return -1; - } - bpc->bpc_has_localif = true; if (strlcpy(bpc->bpc_localif, ifname, sizeof(bpc->bpc_localif)) > sizeof(bpc->bpc_localif)) { From eefca51eb32b9e1a4f12f309e6d7f0cf53ffd765 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Mon, 24 Jun 2019 11:46:29 -0300 Subject: [PATCH 15/21] bfdd: fix compilation warnings on OpenBSD Build will fail with `Werror` enabled with: ``` bfdd/bfdd_northbound.c:876: warning: initialized field overwritten bfdd/bfdd_northbound.c:876: warning: (near initialization for 'frr_bfdd_info.nodes[0].cbs') ... cc1: error: unrecognized command line option "-Wno-unused-result" gmake[1]: *** [Makefile:6875: bfdd/bfdd_northbound.o] Error 1 ``` Signed-off-by: Rafael Zalamena --- bfdd/bfdd_northbound.c | 268 +++++++++++++++++++++++++++++------------ 1 file changed, 188 insertions(+), 80 deletions(-) diff --git a/bfdd/bfdd_northbound.c b/bfdd/bfdd_northbound.c index 24fdfa1ea2..e8bde034ab 100644 --- a/bfdd/bfdd_northbound.c +++ b/bfdd/bfdd_northbound.c @@ -871,245 +871,353 @@ const struct frr_yang_module_info frr_bfdd_info = { .nodes = { { .xpath = "/frr-bfdd:bfdd/bfd", - .cbs.create = bfdd_bfd_create, - .cbs.destroy = bfdd_bfd_destroy, - .cbs.cli_show = bfd_cli_show_header, - .cbs.cli_show_end = bfd_cli_show_header_end, + .cbs = { + .create = bfdd_bfd_create, + .destroy = bfdd_bfd_destroy, + .cli_show = bfd_cli_show_header, + .cli_show_end = bfd_cli_show_header_end, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop", - .cbs.create = bfdd_bfd_sessions_single_hop_create, - .cbs.destroy = bfdd_bfd_sessions_single_hop_destroy, - .cbs.get_next = bfdd_bfd_sessions_single_hop_get_next, - .cbs.get_keys = bfdd_bfd_sessions_single_hop_get_keys, - .cbs.lookup_entry = bfdd_bfd_sessions_single_hop_lookup_entry, - .cbs.cli_show = bfd_cli_show_single_hop_peer, - .cbs.cli_show_end = bfd_cli_show_peer_end, + .cbs = { + .create = bfdd_bfd_sessions_single_hop_create, + .destroy = bfdd_bfd_sessions_single_hop_destroy, + .get_next = bfdd_bfd_sessions_single_hop_get_next, + .get_keys = bfdd_bfd_sessions_single_hop_get_keys, + .lookup_entry = bfdd_bfd_sessions_single_hop_lookup_entry, + .cli_show = bfd_cli_show_single_hop_peer, + .cli_show_end = bfd_cli_show_peer_end, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/source-addr", - .cbs.modify = bfdd_bfd_sessions_single_hop_source_addr_modify, - .cbs.destroy = bfdd_bfd_sessions_single_hop_source_addr_destroy, + .cbs = { + .modify = bfdd_bfd_sessions_single_hop_source_addr_modify, + .destroy = bfdd_bfd_sessions_single_hop_source_addr_destroy, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/detection-multiplier", - .cbs.modify = bfdd_bfd_sessions_single_hop_detection_multiplier_modify, - .cbs.cli_show = bfd_cli_show_mult, + .cbs = { + .modify = bfdd_bfd_sessions_single_hop_detection_multiplier_modify, + .cli_show = bfd_cli_show_mult, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/desired-transmission-interval", - .cbs.modify = bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify, - .cbs.cli_show = bfd_cli_show_tx, + .cbs = { + .modify = bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify, + .cli_show = bfd_cli_show_tx, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/required-receive-interval", - .cbs.modify = bfdd_bfd_sessions_single_hop_required_receive_interval_modify, - .cbs.cli_show = bfd_cli_show_rx, + .cbs = { + .modify = bfdd_bfd_sessions_single_hop_required_receive_interval_modify, + .cli_show = bfd_cli_show_rx, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/administrative-down", - .cbs.modify = bfdd_bfd_sessions_single_hop_administrative_down_modify, - .cbs.cli_show = bfd_cli_show_shutdown, + .cbs = { + .modify = bfdd_bfd_sessions_single_hop_administrative_down_modify, + .cli_show = bfd_cli_show_shutdown, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/echo-mode", - .cbs.modify = bfdd_bfd_sessions_single_hop_echo_mode_modify, - .cbs.cli_show = bfd_cli_show_echo, + .cbs = { + .modify = bfdd_bfd_sessions_single_hop_echo_mode_modify, + .cli_show = bfd_cli_show_echo, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/desired-echo-transmission-interval", - .cbs.modify = bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify, - .cbs.cli_show = bfd_cli_show_echo_interval, + .cbs = { + .modify = bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify, + .cli_show = bfd_cli_show_echo_interval, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-discriminator", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_local_discriminator_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_local_discriminator_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-state", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_local_state_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_local_state_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-diagnostic", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_local_diagnostic_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_local_diagnostic_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/local-multiplier", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_local_multiplier_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_local_multiplier_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-discriminator", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_remote_discriminator_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_discriminator_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-state", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_remote_state_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_state_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-diagnostic", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_remote_diagnostic_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_diagnostic_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/remote-multiplier", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_remote_multiplier_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_multiplier_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/negotiated-transmission-interval", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_transmission_interval_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_transmission_interval_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/negotiated-receive-interval", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_receive_interval_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_receive_interval_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/detection-mode", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_detection_mode_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_detection_mode_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/last-down-time", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_last_down_time_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_last_down_time_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/last-up-time", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_last_up_time_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_last_up_time_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/session-down-count", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_session_down_count_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_session_down_count_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/session-up-count", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_session_up_count_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_session_up_count_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/control-packet-input-count", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_control_packet_input_count_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_control_packet_input_count_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/control-packet-output-count", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_control_packet_output_count_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_control_packet_output_count_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/negotiated-echo-transmission-interval", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_echo_transmission_interval_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_echo_transmission_interval_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/echo-packet-input-count", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_echo_packet_input_count_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_echo_packet_input_count_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/single-hop/stats/echo-packet-output-count", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_echo_packet_output_count_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_echo_packet_output_count_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop", - .cbs.create = bfdd_bfd_sessions_multi_hop_create, - .cbs.destroy = bfdd_bfd_sessions_multi_hop_destroy, - .cbs.get_next = bfdd_bfd_sessions_multi_hop_get_next, - .cbs.get_keys = bfdd_bfd_sessions_multi_hop_get_keys, - .cbs.lookup_entry = bfdd_bfd_sessions_multi_hop_lookup_entry, - .cbs.cli_show = bfd_cli_show_multi_hop_peer, - .cbs.cli_show_end = bfd_cli_show_peer_end, + .cbs = { + .create = bfdd_bfd_sessions_multi_hop_create, + .destroy = bfdd_bfd_sessions_multi_hop_destroy, + .get_next = bfdd_bfd_sessions_multi_hop_get_next, + .get_keys = bfdd_bfd_sessions_multi_hop_get_keys, + .lookup_entry = bfdd_bfd_sessions_multi_hop_lookup_entry, + .cli_show = bfd_cli_show_multi_hop_peer, + .cli_show_end = bfd_cli_show_peer_end, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/detection-multiplier", - .cbs.modify = bfdd_bfd_sessions_single_hop_detection_multiplier_modify, - .cbs.cli_show = bfd_cli_show_mult, + .cbs = { + .modify = bfdd_bfd_sessions_single_hop_detection_multiplier_modify, + .cli_show = bfd_cli_show_mult, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/desired-transmission-interval", - .cbs.modify = bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify, - .cbs.cli_show = bfd_cli_show_tx, + .cbs = { + .modify = bfdd_bfd_sessions_single_hop_desired_transmission_interval_modify, + .cli_show = bfd_cli_show_tx, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/required-receive-interval", - .cbs.modify = bfdd_bfd_sessions_single_hop_required_receive_interval_modify, - .cbs.cli_show = bfd_cli_show_rx, + .cbs = { + .modify = bfdd_bfd_sessions_single_hop_required_receive_interval_modify, + .cli_show = bfd_cli_show_rx, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/administrative-down", - .cbs.modify = bfdd_bfd_sessions_single_hop_administrative_down_modify, - .cbs.cli_show = bfd_cli_show_shutdown, + .cbs = { + .modify = bfdd_bfd_sessions_single_hop_administrative_down_modify, + .cli_show = bfd_cli_show_shutdown, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/local-discriminator", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_local_discriminator_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_local_discriminator_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/local-state", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_local_state_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_local_state_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/local-diagnostic", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_local_diagnostic_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_local_diagnostic_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/local-multiplier", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_local_multiplier_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_local_multiplier_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/remote-discriminator", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_remote_discriminator_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_discriminator_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/remote-state", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_remote_state_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_state_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/remote-diagnostic", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_remote_diagnostic_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_diagnostic_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/remote-multiplier", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_remote_multiplier_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_remote_multiplier_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/negotiated-transmission-interval", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_transmission_interval_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_transmission_interval_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/negotiated-receive-interval", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_receive_interval_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_receive_interval_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/detection-mode", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_detection_mode_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_detection_mode_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/last-down-time", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_last_down_time_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_last_down_time_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/last-up-time", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_last_up_time_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_last_up_time_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/session-down-count", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_session_down_count_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_session_down_count_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/session-up-count", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_session_up_count_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_session_up_count_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/control-packet-input-count", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_control_packet_input_count_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_control_packet_input_count_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/control-packet-output-count", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_control_packet_output_count_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_control_packet_output_count_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/negotiated-echo-transmission-interval", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_echo_transmission_interval_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_negotiated_echo_transmission_interval_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/echo-packet-input-count", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_echo_packet_input_count_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_echo_packet_input_count_get_elem, + } }, { .xpath = "/frr-bfdd:bfdd/bfd/sessions/multi-hop/stats/echo-packet-output-count", - .cbs.get_elem = bfdd_bfd_sessions_single_hop_stats_echo_packet_output_count_get_elem, + .cbs = { + .get_elem = bfdd_bfd_sessions_single_hop_stats_echo_packet_output_count_get_elem, + } }, { .xpath = NULL, From 8e0c84ff27b420b3aae7166c5974aecf6e537fe1 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Mon, 24 Jun 2019 12:09:29 -0300 Subject: [PATCH 16/21] bfdd: fix compilation warnings on OmniOS Build will fail with `Werror` enabled with: ``` CC bfdd/bfdd_cli.o In file included from ./lib/frratomic.h:21:0, from ./lib/memory.h:22, from ./lib/vector.h:25, from ./lib/command.h:25, from bfdd/bfdd_cli.c:23: ./config.h:665:0: error: "_FILE_OFFSET_BITS" redefined [-Werror] #define _FILE_OFFSET_BITS 64 ^ In file included from /usr/include/iso/stdlib_iso.h:49:0, from /usr/include/stdlib.h:37, from ./lib/memory.h:20, from ./lib/vector.h:25, from ./lib/command.h:25, from bfdd/bfdd_cli.c:23: /opt/gcc-5.1.0/lib/gcc/i386-pc-solaris2.11/5.1.0/include-fixed/sys/feature_tests.h:231:0: note: this is the location of the previous definition #define _FILE_OFFSET_BITS 32 ^ In file included from ./lib/thread.h:24:0, from ./lib/vty.h:27, from ./lib/command.h:26, from bfdd/bfdd_cli.c:23: ./lib/zebra.h:271:2: error: #warning "assuming 4-byte alignment for CMSG_SPACE" [-Werror=cpp] #warning "assuming 4-byte alignment for CMSG_SPACE" ^ ./lib/zebra.h:277:2: error: #warning "assuming 4-byte alignment for CMSG_LEN" [-Werror=cpp] #warning "assuming 4-byte alignment for CMSG_LEN" ^ cc1: all warnings being treated as errors Makefile:6876: recipe for target 'bfdd/bfdd_cli.o' failed gmake[1]: *** [bfdd/bfdd_cli.o] Error 1 ``` Signed-off-by: Rafael Zalamena --- bfdd/bfdd_cli.c | 2 ++ bfdd/bfdd_northbound.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/bfdd/bfdd_cli.c b/bfdd/bfdd_cli.c index 7e14997823..15df0f769f 100644 --- a/bfdd/bfdd_cli.c +++ b/bfdd/bfdd_cli.c @@ -20,6 +20,8 @@ * 02110-1301 USA. */ +#include + #include "lib/command.h" #include "lib/log.h" #include "lib/northbound_cli.h" diff --git a/bfdd/bfdd_northbound.c b/bfdd/bfdd_northbound.c index e8bde034ab..0d31394629 100644 --- a/bfdd/bfdd_northbound.c +++ b/bfdd/bfdd_northbound.c @@ -20,6 +20,8 @@ * 02110-1301 USA. */ +#include + #include "lib/log.h" #include "lib/northbound.h" From 77452ad263562ab9cca989da1df9a9ad2afd17e1 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Mon, 24 Jun 2019 18:26:04 -0300 Subject: [PATCH 17/21] bfdd: small tweaks on northbound * Change `ERR_VALIDATION` to `ERR_INCONSISTENCY` to error on inconsistent state. * Duplicated sanity checks: * Remove detection multiplier sanity check. * Remove duplicated session sanity check. Signed-off-by: Rafael Zalamena --- bfdd/bfdd_northbound.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/bfdd/bfdd_northbound.c b/bfdd/bfdd_northbound.c index 0d31394629..cb097248c3 100644 --- a/bfdd/bfdd_northbound.c +++ b/bfdd/bfdd_northbound.c @@ -72,12 +72,6 @@ int bfd_session_create(enum nb_event event, const struct lyd_node *dnode, switch (event) { case NB_EV_VALIDATE: - bfd_session_get_key(mhop, dnode, &bk); - bs = bfd_key_lookup(bk); - - /* This session was already configured by CLI. */ - if (bs != NULL && BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG)) - return NB_ERR_VALIDATION; break; case NB_EV_PREPARE: @@ -142,7 +136,7 @@ int bfd_session_destroy(enum nb_event event, const struct lyd_node *dnode, case NB_EV_VALIDATE: bfd_session_get_key(mhop, dnode, &bk); if (bfd_key_lookup(bk) == NULL) - return NB_ERR_VALIDATION; + return NB_ERR_INCONSISTENCY; break; case NB_EV_PREPARE: @@ -296,8 +290,6 @@ static int bfdd_bfd_sessions_single_hop_detection_multiplier_modify( switch (event) { case NB_EV_VALIDATE: - if (detection_multiplier == 1) - return NB_ERR_VALIDATION; break; case NB_EV_PREPARE: From fdf8ac87f8a6256dd657d61517cdce6642098464 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Tue, 25 Jun 2019 09:34:14 -0300 Subject: [PATCH 18/21] bfdd: convert `bfd` command to northbound This helps northbound to create the `bfd` node on the configuration output sooner than adding a peer. Signed-off-by: Rafael Zalamena --- bfdd/bfdd_cli.c | 18 +++++++++++++++++- bfdd/bfdd_vty.c | 10 ---------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/bfdd/bfdd_cli.c b/bfdd/bfdd_cli.c index 15df0f769f..c2c3040ebc 100644 --- a/bfdd/bfdd_cli.c +++ b/bfdd/bfdd_cli.c @@ -54,6 +54,21 @@ /* * Functions. */ +DEFPY_NOSH( + bfd_enter, bfd_enter_cmd, + "bfd", + "Configure BFD peers\n") +{ + int ret; + + nb_cli_enqueue_change(vty, "/frr-bfdd:bfdd/bfd", NB_OP_CREATE, NULL); + ret = nb_cli_apply_changes(vty, NULL); + if (ret == CMD_SUCCESS) + VTY_PUSH_XPATH(BFD_NODE, "/frr-bfdd:bfdd/bfd"); + + return ret; +} + DEFUN( bfd_config_reset, bfd_config_reset_cmd, "no bfd", @@ -120,7 +135,7 @@ DEFPY_NOSH( nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); - /* Apply settings immediatly. */ + /* Apply settings immediately. */ ret = nb_cli_apply_changes(vty, NULL); if (ret == CMD_SUCCESS) VTY_PUSH_XPATH(BFD_PEER_NODE, xpath); @@ -376,6 +391,7 @@ void bfd_cli_show_echo_interval(struct vty *vty, struct lyd_node *dnode, void bfdd_cli_init(void) { + install_element(CONFIG_NODE, &bfd_enter_cmd); install_element(CONFIG_NODE, &bfd_config_reset_cmd); install_element(BFD_NODE, &bfd_peer_enter_cmd); diff --git a/bfdd/bfdd_vty.c b/bfdd/bfdd_vty.c index c3ca7a43f1..a211f34219 100644 --- a/bfdd/bfdd_vty.c +++ b/bfdd/bfdd_vty.c @@ -72,15 +72,6 @@ _find_peer_or_error(struct vty *vty, int argc, struct cmd_token **argv, const char *local_str, const char *ifname, const char *vrfname); -/* - * Commands definition. - */ -DEFUN_NOSH(bfd_enter, bfd_enter_cmd, "bfd", "Configure BFD peers\n") -{ - vty->node = BFD_NODE; - return CMD_SUCCESS; -} - /* * Show commands helper functions @@ -743,7 +734,6 @@ void bfdd_vty_init(void) install_element(ENABLE_NODE, &bfd_show_peer_counters_cmd); install_element(ENABLE_NODE, &bfd_show_peers_cmd); install_element(ENABLE_NODE, &bfd_show_peer_cmd); - install_element(CONFIG_NODE, &bfd_enter_cmd); install_element(ENABLE_NODE, &show_debugging_bfd_cmd); /* Install BFD node and commands. */ From 307fc4259a4945a857170547ff3ab50b2c162cbc Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Tue, 2 Jul 2019 13:05:27 -0300 Subject: [PATCH 19/21] bfdd: fix some CI warnings Use `static` functions for file local functions to please `check_patch.pl`. Signed-off-by: Rafael Zalamena --- bfdd/bfd.c | 16 ++++++++-------- bfdd/bfdd_northbound.c | 22 ++++++---------------- 2 files changed, 14 insertions(+), 24 deletions(-) diff --git a/bfdd/bfd.c b/bfdd/bfd.c index fc9d033437..5d143d4e5f 100644 --- a/bfdd/bfd.c +++ b/bfdd/bfd.c @@ -1289,8 +1289,6 @@ static unsigned int bfd_key_hash_do(const void *p); static void _bfd_free(struct hash_bucket *hb, void *arg __attribute__((__unused__))); -int _bfd_session_next(struct hash_bucket *hb, void *arg); -void _bfd_session_remove_manual(struct hash_bucket *hb, void *arg); /* BFD hash for our discriminator. */ static unsigned int bfd_id_hash_do(const void *p) @@ -1343,9 +1341,10 @@ struct bfd_key_walk_partial_lookup { }; /* ignore some parameters */ -static int bfd_key_lookup_ignore_partial_walker(struct hash_bucket *b, void *data) +static int bfd_key_lookup_ignore_partial_walker(struct hash_bucket *b, + void *data) { - struct bfd_key_walk_partial_lookup *ctx = + struct bfd_key_walk_partial_lookup *ctx = (struct bfd_key_walk_partial_lookup *)data; struct bfd_session *given = ctx->given; struct bfd_session *parsed = b->data; @@ -1354,7 +1353,8 @@ static int bfd_key_lookup_ignore_partial_walker(struct hash_bucket *b, void *dat return HASHWALK_CONTINUE; if (given->key.mhop != parsed->key.mhop) return HASHWALK_CONTINUE; - if (memcmp(&given->key.peer, &parsed->key.peer, sizeof(struct in6_addr))) + if (memcmp(&given->key.peer, &parsed->key.peer, + sizeof(struct in6_addr))) return HASHWALK_CONTINUE; if (memcmp(given->key.vrfname, parsed->key.vrfname, MAXNAMELEN)) return HASHWALK_CONTINUE; @@ -1538,7 +1538,7 @@ struct bfd_session_iterator { const struct bfd_session *bsi_bs; }; -int _bfd_session_next(struct hash_bucket *hb, void *arg) +static int _bfd_session_next(struct hash_bucket *hb, void *arg) { struct bfd_session_iterator *bsi = arg; struct bfd_session *bs = hb->data; @@ -1588,8 +1588,8 @@ const struct bfd_session *bfd_session_next(const struct bfd_session *bs, return bsi.bsi_bs; } -void _bfd_session_remove_manual(struct hash_bucket *hb, - void *arg __attribute__((__unused__))) +static void _bfd_session_remove_manual(struct hash_bucket *hb, + void *arg __attribute__((__unused__))) { struct bfd_session *bs = hb->data; diff --git a/bfdd/bfdd_northbound.c b/bfdd/bfdd_northbound.c index cb097248c3..7cd2fb6b9a 100644 --- a/bfdd/bfdd_northbound.c +++ b/bfdd/bfdd_northbound.c @@ -27,21 +27,11 @@ #include "bfd.h" -/* - * Prototypes. - */ -void bfd_session_get_key(bool mhop, const struct lyd_node *dnode, - struct bfd_key *bk); -int bfd_session_create(enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource, bool mhop); -int bfd_session_destroy(enum nb_event event, const struct lyd_node *dnode, - bool mhop); - /* * Helpers. */ -void bfd_session_get_key(bool mhop, const struct lyd_node *dnode, - struct bfd_key *bk) +static void bfd_session_get_key(bool mhop, const struct lyd_node *dnode, + struct bfd_key *bk) { const char *ifname = NULL, *vrfname = NULL; struct sockaddr_any psa, lsa; @@ -64,8 +54,8 @@ void bfd_session_get_key(bool mhop, const struct lyd_node *dnode, gen_bfd_key(bk, &psa, &lsa, mhop, ifname, vrfname); } -int bfd_session_create(enum nb_event event, const struct lyd_node *dnode, - union nb_resource *resource, bool mhop) +static int bfd_session_create(enum nb_event event, const struct lyd_node *dnode, + union nb_resource *resource, bool mhop) { struct bfd_session *bs; struct bfd_key bk; @@ -126,8 +116,8 @@ int bfd_session_create(enum nb_event event, const struct lyd_node *dnode, return NB_OK; } -int bfd_session_destroy(enum nb_event event, const struct lyd_node *dnode, - bool mhop) +static int bfd_session_destroy(enum nb_event event, + const struct lyd_node *dnode, bool mhop) { struct bfd_session *bs; struct bfd_key bk; From 7f121ef718f5f20521e2e968b65e580b5881d8f0 Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Mon, 8 Jul 2019 17:38:28 -0300 Subject: [PATCH 20/21] yang: change single hop `leaf` order Move `source-address` to after the list keys, otherwise the CLI would get into an invalid state and be unable to set any other configuration inside that node. Spotted by Philippe Guibert. Signed-off-by: Rafael Zalamena --- yang/frr-bfdd.yang | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/yang/frr-bfdd.yang b/yang/frr-bfdd.yang index 4604f747c6..24ca8f68a8 100644 --- a/yang/frr-bfdd.yang +++ b/yang/frr-bfdd.yang @@ -317,11 +317,6 @@ module frr-bfdd { key "dest-addr interface vrf"; description "List of single hop sessions"; - leaf source-addr { - type inet:ip-address; - description "Local IP address"; - } - leaf dest-addr { type inet:ip-address; description "IP address of the peer"; @@ -339,6 +334,11 @@ module frr-bfdd { description "Virtual Routing Domain name"; } + leaf source-addr { + type inet:ip-address; + description "Local IP address"; + } + uses session-common; uses session-echo; From 284062bf1776cf544749c36a57096a138fe4bffb Mon Sep 17 00:00:00 2001 From: Rafael Zalamena Date: Mon, 8 Jul 2019 15:56:56 -0300 Subject: [PATCH 21/21] bfdd: keep source information for single hop Add source address to northbound when creating sessions with this information. It is not possible to change source address after the session was created, but we should be able to set it to make IPv6 work. Spotted by Philippe Guibert. Signed-off-by: Rafael Zalamena --- bfdd/bfdd_cli.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/bfdd/bfdd_cli.c b/bfdd/bfdd_cli.c index c2c3040ebc..acb1801cc4 100644 --- a/bfdd/bfdd_cli.c +++ b/bfdd/bfdd_cli.c @@ -108,8 +108,8 @@ DEFPY_NOSH( VRF_NAME_STR) { int ret, slen; - char xpath[XPATH_MAXLEN]; char source_str[INET6_ADDRSTRLEN]; + char xpath[XPATH_MAXLEN], xpath_srcaddr[XPATH_MAXLEN + 32]; if (multihop) snprintf(source_str, sizeof(source_str), "[source-addr='%s']", @@ -134,6 +134,12 @@ DEFPY_NOSH( VRF_DEFAULT_NAME); nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL); + if (multihop == NULL && local_address_str != NULL) { + snprintf(xpath_srcaddr, sizeof(xpath_srcaddr), + "%s/source-addr", xpath); + nb_cli_enqueue_change(vty, xpath_srcaddr, NB_OP_MODIFY, + local_address_str); + } /* Apply settings immediately. */ ret = nb_cli_apply_changes(vty, NULL);