From: Donald Sharp Date: Wed, 22 Jul 2015 19:35:37 +0000 (-0700) Subject: This patch changes ospfd from only listening mode for BFD status updates to interacti... X-Git-Tag: frr-2.0-rc1~1308 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=7f342629a9eae034138fd542734fe2e6eca8085d;p=matthieu%2Ffrr.git This patch changes ospfd from only listening mode for BFD status updates to interactive mode of dynamically registering/deregistering neighbors discovered on BFD enabled interfaces with PTM/BFD through zebra. Neighbor is registered with BFD when 2-way adjacency is established and deregistered when adjacency goes down if the BFD is enabled on the interface through which the neighbor was discovered. OSPF BFD command enhancement to configure BFD parameters (detect multiplier, min rx and min tx). interface ip ospf bfd This patch also adds BFD support for IPv6 OSPF. ospf6d will dynamically register/deregister IPv6 neighbors with BFD for monitoring the connectivity of the neighbor. Neighbor is registered with BFD when 2-way adjacency is established and deregistered when adjacency goes down if the BFD is enabled on the interface through which the neighbor was discovered. OSPF6 BFD command added to configure BFD and parameters (detect multiplier, min rx and min tx). interface ipv6 ospf6 bfd Signed-off-by: Radhika Mahankali Reviewed-by: Donald Sharp Reviewed-by: Kanna Rajagopal --- diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c index 02047f7f07..87feebe8a6 100644 --- a/bgpd/bgp_bfd.c +++ b/bgpd/bgp_bfd.c @@ -32,43 +32,15 @@ #include "stream.h" #include "zclient.h" #include "vty.h" -#include "bgp_fsm.h" +#include "bfd.h" #include "bgpd/bgpd.h" +#include "bgp_fsm.h" #include "bgpd/bgp_bfd.h" #include "bgpd/bgp_debug.h" #include "bgpd/bgp_vty.h" extern struct zclient *zclient; -/* - * bgp_bfd_peer_init - Allocate and initialize the peer BFD information - * with default values. - */ -void -bgp_bfd_peer_init(struct peer *peer) -{ - struct bgp_bfd_peer_info *bfd_info; - - peer->bfd_info = XCALLOC (MTYPE_BGP_PEER_BFD_INFO, - sizeof (struct bgp_bfd_peer_info)); - - bfd_info = (struct bgp_bfd_peer_info *)peer->bfd_info; - - /* Set default BFD parameter values */ - bfd_info->required_min_rx = BGP_BFD_DEF_MIN_RX; - bfd_info->desired_min_tx = BGP_BFD_DEF_MIN_TX; - bfd_info->detect_mult = BGP_BFD_DEF_DETECT_MULT; -} - -/* - * bgp_bfd_peer_free - Free the peer BFD information. - */ -void -bgp_bfd_peer_free(struct peer *peer) -{ - XFREE (MTYPE_BGP_PEER_BFD_INFO, peer->bfd_info); -} - /* * bgp_bfd_peer_group2peer_copy - Copy the BFD information from peer group template * to peer. @@ -76,11 +48,17 @@ bgp_bfd_peer_free(struct peer *peer) void bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer) { - struct bgp_bfd_peer_info *bfd_info; - struct bgp_bfd_peer_info *conf_bfd_info; + struct bfd_info *bfd_info; + struct bfd_info *conf_bfd_info; + + if (!conf->bfd_info) + return; + + conf_bfd_info = (struct bfd_info *)conf->bfd_info; + if (!peer->bfd_info) + peer->bfd_info = bfd_info_create(); - bfd_info = (struct bgp_bfd_peer_info *)peer->bfd_info; - conf_bfd_info = (struct bgp_bfd_peer_info *)conf->bfd_info; + bfd_info = (struct bfd_info *)peer->bfd_info; /* Copy BFD parameter values */ bfd_info->required_min_rx = conf_bfd_info->required_min_rx; @@ -101,111 +79,28 @@ bgp_bfd_is_peer_multihop(struct peer *peer) } /* - * sendmsg_bfd_peer - Format and send a Peer register/Unregister - * command to Zebra to be forwarded to BFD + * bgp_bfd_peer_sendmsg - Format and send a Peer register/Unregister + * command to Zebra to be forwarded to BFD */ static void -sendmsg_bfd_peer (struct peer *peer, int command) +bgp_bfd_peer_sendmsg (struct peer *peer, int command) { - struct stream *s; - int ret; - int len; - struct bgp_bfd_peer_info *bfd_info; - - bfd_info = (struct bgp_bfd_peer_info *)peer->bfd_info; - - /* Check socket. */ - if (!zclient || zclient->sock < 0) - { - zlog_debug("%s: Can't send BFD peer register, Zebra client not established", - __FUNCTION__); - return; - } - - s = zclient->obuf; - stream_reset (s); - zclient_create_header (s, command); - - stream_putw(s, peer->su.sa.sa_family); - switch (peer->su.sa.sa_family) - { - case AF_INET: - stream_put_in_addr (s, &peer->su.sin.sin_addr); - break; -#ifdef HAVE_IPV6 - case AF_INET6: - stream_put(s, &(peer->su.sin6.sin6_addr), 16); - break; -#endif - default: - break; - } - - if (command != ZEBRA_BFD_DEST_DEREGISTER) - { - stream_putl(s, bfd_info->required_min_rx); - stream_putl(s, bfd_info->desired_min_tx); - stream_putc(s, bfd_info->detect_mult); - } - - if (bgp_bfd_is_peer_multihop(peer)) - { - stream_putc(s, 1); - /* Multi-hop destination send the source IP address to BFD */ - if (peer->su_local) - { - stream_putw(s, peer->su_local->sa.sa_family); - switch (peer->su_local->sa.sa_family) - { - case AF_INET: - stream_put_in_addr (s, &peer->su_local->sin.sin_addr); - break; - #ifdef HAVE_IPV6 - case AF_INET6: - stream_put(s, &(peer->su_local->sin6.sin6_addr), 16); - break; - #endif - default: - break; - } - } - stream_putc(s, peer->ttl); - } - else - { - stream_putc(s, 0); -#ifdef HAVE_IPV6 - if ((peer->su.sa.sa_family == AF_INET6) && (peer->su_local)) - { - stream_putw(s, peer->su_local->sa.sa_family); - stream_put(s, &(peer->su_local->sin6.sin6_addr), 16); - } -#endif - - if (peer->nexthop.ifp) - { - len = strlen(peer->nexthop.ifp->name); - stream_putc(s, len); - stream_put(s, peer->nexthop.ifp->name, len); - } - else - { - stream_putc(s, 0); - } - } - - stream_putw_at (s, 0, stream_get_endp (s)); - - ret = zclient_send_message(zclient); - - if (ret < 0) - zlog_warn("sendmsg_bfd_peer: zclient_send_message() failed"); - - if (command == ZEBRA_BFD_DEST_REGISTER) - SET_FLAG(bfd_info->flags, BGP_BFD_FLAG_BFD_REG); - else if (command == ZEBRA_BFD_DEST_DEREGISTER) - UNSET_FLAG(bfd_info->flags, BGP_BFD_FLAG_BFD_REG); - return; + struct bfd_info *bfd_info; + + bfd_info = (struct bfd_info *)peer->bfd_info; + + if (peer->su.sa.sa_family == AF_INET) + bfd_peer_sendmsg (zclient, bfd_info, AF_INET, + &peer->su.sin.sin_addr, + (peer->su_local) ? &peer->su_local->sin.sin_addr : NULL, + (peer->nexthop.ifp) ? peer->nexthop.ifp->name : NULL, + peer->ttl, bgp_bfd_is_peer_multihop(peer), command, 1); + else if (peer->su.sa.sa_family == AF_INET6) + bfd_peer_sendmsg (zclient, bfd_info, AF_INET6, + &peer->su.sin6.sin6_addr, + (peer->su_local) ? &peer->su_local->sin6.sin6_addr : NULL, + (peer->nexthop.ifp) ? peer->nexthop.ifp->name : NULL, + peer->ttl, bgp_bfd_is_peer_multihop(peer), command, 1); } /* @@ -215,16 +110,17 @@ sendmsg_bfd_peer (struct peer *peer, int command) void bgp_bfd_register_peer (struct peer *peer) { - struct bgp_bfd_peer_info *bfd_info; + struct bfd_info *bfd_info; - bfd_info = (struct bgp_bfd_peer_info *)peer->bfd_info; + if (!peer->bfd_info) + return; + bfd_info = (struct bfd_info *)peer->bfd_info; /* Check if BFD is enabled and peer has already been registered with BFD */ - if (!CHECK_FLAG(peer->flags, PEER_FLAG_BFD) || - CHECK_FLAG(bfd_info->flags, BGP_BFD_FLAG_BFD_REG)) + if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG)) return; - sendmsg_bfd_peer(peer, ZEBRA_BFD_DEST_REGISTER); + bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_REGISTER); } /** @@ -235,41 +131,44 @@ bgp_bfd_register_peer (struct peer *peer) void bgp_bfd_deregister_peer (struct peer *peer) { - struct bgp_bfd_peer_info *bfd_info; + struct bfd_info *bfd_info; - bfd_info = (struct bgp_bfd_peer_info *)peer->bfd_info; + if (!peer->bfd_info) + return; + bfd_info = (struct bfd_info *)peer->bfd_info; /* Check if BFD is eanbled and peer has not been registered */ - if (!CHECK_FLAG(peer->flags, PEER_FLAG_BFD) || - !CHECK_FLAG(bfd_info->flags, BGP_BFD_FLAG_BFD_REG)) + if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG)) return; - sendmsg_bfd_peer(peer, ZEBRA_BFD_DEST_DEREGISTER); + bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_DEREGISTER); } /* * bgp_bfd_update_peer - update peer with BFD with new BFD paramters * through zebra. */ -void +static void bgp_bfd_update_peer (struct peer *peer) { - struct bgp_bfd_peer_info *bfd_info; + struct bfd_info *bfd_info; - bfd_info = (struct bgp_bfd_peer_info *)peer->bfd_info; + if (!peer->bfd_info) + return; + bfd_info = (struct bfd_info *)peer->bfd_info; /* Check if the peer has been registered with BFD*/ - if (!CHECK_FLAG(bfd_info->flags, BGP_BFD_FLAG_BFD_REG)) + if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG)) return; - sendmsg_bfd_peer(peer, ZEBRA_BFD_DEST_UPDATE); + bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_UPDATE); } /* * bgp_bfd_dest_replay - Replay all the peers that have BFD enabled * to zebra */ -int +static int bgp_bfd_dest_replay (int command, struct zclient *client, zebra_size_t length) { struct listnode *mnode, *node, *nnode; @@ -284,9 +183,6 @@ bgp_bfd_dest_replay (int command, struct zclient *client, zebra_size_t length) for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp)) for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) { - if (!CHECK_FLAG (peer->flags, PEER_FLAG_BFD)) - continue; - bgp_bfd_update_peer(peer); } @@ -298,7 +194,7 @@ bgp_bfd_dest_replay (int command, struct zclient *client, zebra_size_t length) * has changed and bring down the peer * connectivity. */ -int +static int bgp_interface_bfd_dest_down (int command, struct zclient *zclient, zebra_size_t length) { @@ -306,7 +202,7 @@ bgp_interface_bfd_dest_down (int command, struct zclient *zclient, struct prefix dp; struct prefix sp; - ifp = zebra_interface_bfd_read (zclient->ibuf, &dp, &sp); + ifp = bfd_get_peer_info (zclient->ibuf, &dp, &sp); if (BGP_DEBUG (zebra, ZEBRA)) { @@ -334,7 +230,7 @@ bgp_interface_bfd_dest_down (int command, struct zclient *zclient, for (ALL_LIST_ELEMENTS_RO (bm->bgp, mnode, bgp)) for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer)) { - if (!CHECK_FLAG (peer->flags, PEER_FLAG_BFD)) + if (!peer->bfd_info) continue; if ((dp.family == AF_INET) && (peer->su.sa.sa_family == AF_INET)) @@ -394,53 +290,39 @@ bgp_interface_bfd_dest_down (int command, struct zclient *zclient, /* * bgp_bfd_peer_param_set - Set the configured BFD paramter values for peer. */ -int +static int bgp_bfd_peer_param_set (struct peer *peer, u_int32_t min_rx, u_int32_t min_tx, - u_int8_t detect_mult, int reg_peer, int defaults) + u_int8_t detect_mult, int defaults) { struct peer_group *group; struct listnode *node, *nnode; - int change = 0; - struct bgp_bfd_peer_info *bfd_info; - - bfd_info = (struct bgp_bfd_peer_info *)peer->bfd_info; - - if ((bfd_info->required_min_rx != min_rx) || - (bfd_info->desired_min_tx != min_tx) || - (bfd_info->detect_mult != detect_mult)) - change = 1; + int command = 0; - bfd_info->required_min_rx = min_rx; - bfd_info->desired_min_tx = min_tx; - bfd_info->detect_mult = detect_mult; - - if (!defaults) - SET_FLAG (bfd_info->flags, BGP_BFD_FLAG_PARAM_CFG); - else - UNSET_FLAG (bfd_info->flags, BGP_BFD_FLAG_PARAM_CFG); + bfd_set_param(&(peer->bfd_info), min_rx, min_tx, detect_mult, + defaults, &command); if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) { group = peer->group; for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) { - bfd_info = (struct bgp_bfd_peer_info *)peer->bfd_info; - bfd_info->required_min_rx = min_rx; - bfd_info->desired_min_tx = min_tx; - bfd_info->detect_mult = detect_mult; - SET_FLAG (bfd_info->flags, BGP_BFD_FLAG_PARAM_CFG); + command = 0; + bfd_set_param(&(peer->bfd_info), min_rx, min_tx, detect_mult, + defaults, &command); - if (reg_peer && (peer->status == Established)) + if ((peer->status == Established) && + (command == ZEBRA_BFD_DEST_REGISTER)) bgp_bfd_register_peer(peer); - else if (change) + else if (command == ZEBRA_BFD_DEST_UPDATE) bgp_bfd_update_peer(peer); } } - else + else { - if (reg_peer && (peer->status == Established)) + if ((peer->status == Established) && + (command == ZEBRA_BFD_DEST_REGISTER)) bgp_bfd_register_peer(peer); - else if (change) + else if (command == ZEBRA_BFD_DEST_UPDATE) bgp_bfd_update_peer(peer); } return 0; @@ -449,35 +331,30 @@ bgp_bfd_peer_param_set (struct peer *peer, u_int32_t min_rx, u_int32_t min_tx, /* * bgp_bfd_peer_param_unset - Unset the configured BFD paramter values for peer. */ -int +static int bgp_bfd_peer_param_unset (struct peer *peer) { struct peer_group *group; struct listnode *node, *nnode; - struct bgp_bfd_peer_info *bfd_info; - - bfd_info = (struct bgp_bfd_peer_info *)peer->bfd_info; - bfd_info->required_min_rx = BGP_BFD_DEF_MIN_RX; - bfd_info->desired_min_tx = BGP_BFD_DEF_MIN_TX; - bfd_info->detect_mult = BGP_BFD_DEF_DETECT_MULT; - UNSET_FLAG (bfd_info->flags, BGP_BFD_FLAG_PARAM_CFG); + if (!peer->bfd_info) + return 0; if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) { + bfd_info_free(&(peer->bfd_info)); group = peer->group; for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) { - bfd_info->required_min_rx = BGP_BFD_DEF_MIN_RX; - bfd_info->desired_min_tx = BGP_BFD_DEF_MIN_TX; - bfd_info->detect_mult = BGP_BFD_DEF_DETECT_MULT; - UNSET_FLAG (bfd_info->flags, BGP_BFD_FLAG_PARAM_CFG); - bgp_bfd_deregister_peer(peer); + bfd_info_free(&(peer->bfd_info)); } } else - bgp_bfd_deregister_peer(peer); + { + bgp_bfd_deregister_peer(peer); + bfd_info_free(&(peer->bfd_info)); + } return 0; } @@ -487,11 +364,14 @@ bgp_bfd_peer_param_unset (struct peer *peer) void bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr) { - struct bgp_bfd_peer_info *bfd_info; + struct bfd_info *bfd_info; - bfd_info = (struct bgp_bfd_peer_info *)peer->bfd_info; + if (!peer->bfd_info) + return; + + bfd_info = (struct bfd_info *)peer->bfd_info; - if (CHECK_FLAG (bfd_info->flags, BGP_BFD_FLAG_PARAM_CFG)) + if (CHECK_FLAG (bfd_info->flags, BFD_FLAG_PARAM_CFG)) vty_out (vty, " neighbor %s bfd %d %d %d%s", addr, bfd_info->detect_mult, bfd_info->required_min_rx, bfd_info->desired_min_tx, VTY_NEWLINE); @@ -505,20 +385,20 @@ bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr) void bgp_bfd_show_info(struct vty *vty, struct peer *peer) { - struct bgp_bfd_peer_info *bfd_info; + struct bfd_info *bfd_info; + + if (!peer->bfd_info) + return; - bfd_info = (struct bgp_bfd_peer_info *)peer->bfd_info; + bfd_info = (struct bfd_info *)peer->bfd_info; - if (CHECK_FLAG(peer->flags, PEER_FLAG_BFD)) - { - vty_out (vty, " BFD: Multi-hop: %s%s", - (bgp_bfd_is_peer_multihop(peer)) ? "yes" : "no", VTY_NEWLINE); - vty_out (vty, " Detect Mul: %d, Min Rx interval: %d," - " Min Tx interval: %d%s", - bfd_info->detect_mult, bfd_info->required_min_rx, - bfd_info->desired_min_tx, VTY_NEWLINE); - vty_out (vty, "%s", VTY_NEWLINE); - } + vty_out (vty, " BFD: Multi-hop: %s%s", + (bgp_bfd_is_peer_multihop(peer)) ? "yes" : "no", VTY_NEWLINE); + vty_out (vty, " Detect Mul: %d, Min Rx interval: %d," + " Min Tx interval: %d%s", + bfd_info->detect_mult, bfd_info->required_min_rx, + bfd_info->desired_min_tx, VTY_NEWLINE); + vty_out (vty, "%s", VTY_NEWLINE); } DEFUN (neighbor_bfd, @@ -530,23 +410,13 @@ DEFUN (neighbor_bfd, { struct peer *peer; int ret; - int reg_peer = 0; peer = peer_and_group_lookup_vty (vty, argv[0]); if (! peer) return CMD_WARNING; - if ( !CHECK_FLAG (peer->flags, PEER_FLAG_BFD) ) - { - ret = peer_flag_set (peer, PEER_FLAG_BFD); - if (ret != 0) - return bgp_vty_return (vty, ret); - - reg_peer = 1; - } - - ret = bgp_bfd_peer_param_set (peer, BGP_BFD_DEF_MIN_RX, BGP_BFD_DEF_MIN_TX, - BGP_BFD_DEF_DETECT_MULT, reg_peer, 1); + ret = bgp_bfd_peer_param_set (peer, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, + BFD_DEF_DETECT_MULT, 1); if (ret != 0) return bgp_vty_return (vty, ret); @@ -556,7 +426,7 @@ DEFUN (neighbor_bfd, DEFUN (neighbor_bfd_param, neighbor_bfd_param_cmd, - NEIGHBOR_CMD2 "bfd <2-255> <50-60000> <50-60000>", + NEIGHBOR_CMD2 "bfd " BFD_CMD_DETECT_MULT_RANGE BFD_CMD_MIN_RX_RANGE BFD_CMD_MIN_TX_RANGE, NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Enables BFD support\n" @@ -569,26 +439,16 @@ DEFUN (neighbor_bfd_param, u_int32_t tx_val; u_int8_t dm_val; int ret; - int reg_peer = 0; peer = peer_and_group_lookup_vty (vty, argv[0]); if (!peer) return CMD_WARNING; - if (!CHECK_FLAG (peer->flags, PEER_FLAG_BFD)) - { - ret = peer_flag_set (peer, PEER_FLAG_BFD); - if (ret != 0) - return bgp_vty_return (vty, ret); - - reg_peer = 1; - } - - VTY_GET_INTEGER_RANGE ("detect-mul", dm_val, argv[1], 2, 255); - VTY_GET_INTEGER_RANGE ("min-rx", rx_val, argv[2], 50, 60000); - VTY_GET_INTEGER_RANGE ("min-tx", tx_val, argv[3], 50, 60000); + if ((ret = bfd_validate_param (vty, argv[1], argv[2], argv[3], &dm_val, + &rx_val, &tx_val)) != CMD_SUCCESS) + return ret; - ret = bgp_bfd_peer_param_set (peer, rx_val, tx_val, dm_val, reg_peer, 0); + ret = bgp_bfd_peer_param_set (peer, rx_val, tx_val, dm_val, 0); if (ret != 0) return bgp_vty_return (vty, ret); @@ -611,18 +471,10 @@ DEFUN (no_neighbor_bfd, if (! peer) return CMD_WARNING; - /* Do nothing if there is no change in the flag */ - if ( !CHECK_FLAG (peer->flags, PEER_FLAG_BFD) ) - return CMD_SUCCESS; - ret = bgp_bfd_peer_param_unset(peer); if (ret != 0) return bgp_vty_return (vty, ret); - ret = peer_flag_unset (peer, PEER_FLAG_BFD); - if (ret != 0) - return bgp_vty_return (vty, ret); - return CMD_SUCCESS; } diff --git a/bgpd/bgp_bfd.h b/bgpd/bgp_bfd.h index 8c72c231e6..97ad093eee 100644 --- a/bgpd/bgp_bfd.h +++ b/bgpd/bgp_bfd.h @@ -24,30 +24,9 @@ #ifndef _QUAGGA_BGP_BFD_H #define _QUAGGA_BGP_BFD_H -#define BGP_BFD_DEF_MIN_RX 300 -#define BGP_BFD_DEF_MIN_TX 300 -#define BGP_BFD_DEF_DETECT_MULT 3 - -#define BGP_BFD_FLAG_PARAM_CFG (1 << 0) /* parameters have been configured */ -#define BGP_BFD_FLAG_BFD_REG (1 << 1) /* Peer registered with BFD */ - -struct bgp_bfd_peer_info -{ - u_int16_t flags; - u_int8_t detect_mult; - u_int32_t desired_min_tx; - u_int32_t required_min_rx; -}; - extern void bgp_bfd_init(void); -extern void -bgp_bfd_peer_init(struct peer *peer); - -extern void -bgp_bfd_peer_free(struct peer *peer); - extern void bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer); @@ -57,9 +36,6 @@ bgp_bfd_register_peer (struct peer *peer); extern void bgp_bfd_deregister_peer (struct peer *peer); -extern void -bgp_bfd_update_peer (struct peer *peer); - extern void bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 5a633ed60f..dec6b7d688 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -36,6 +36,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "linklist.h" #include "workqueue.h" #include "queue.h" +#include "bfd.h" #include "bgpd/bgpd.h" #include "bgpd/bgp_table.h" @@ -826,6 +827,8 @@ peer_global_config_reset (struct peer *peer) peer->v_holdtime = peer->bgp->default_holdtime; peer->v_keepalive = peer->bgp->default_keepalive; + bfd_info_free(&(peer->bfd_info)); + /* Set back the CONFIG_NODE flag. */ SET_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE); } @@ -951,8 +954,7 @@ peer_free (struct peer *peer) if (peer->conf_if) XFREE (MTYPE_PEER_CONF_IF, peer->conf_if); - if (peer->bfd_info) - bgp_bfd_peer_free(peer); + bfd_info_free(&(peer->bfd_info)); memset (peer, 0, sizeof (struct peer)); @@ -1298,8 +1300,6 @@ peer_create (union sockunion *su, const char *conf_if, struct bgp *bgp, } } - bgp_bfd_peer_init(peer); - /* Set up peer's events and timers. */ if (! active && peer_active (peer)) bgp_timer_set (peer); @@ -1905,7 +1905,6 @@ peer_group_get (struct bgp *bgp, const char *name) group->conf->connect = 0; SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP); listnode_add_sort (bgp->group, group); - bgp_bfd_peer_init(group->conf); return 0; } @@ -2251,8 +2250,7 @@ peer_group_delete (struct peer_group *group) /* Delete from all peer_group list. */ listnode_delete (bgp->group, group); - if (group->conf->bfd_info) - bgp_bfd_peer_free(group->conf); + bfd_info_free(&(group->conf->bfd_info)); peer_group_free (group); @@ -2569,6 +2567,7 @@ peer_group_unbind (struct bgp *bgp, struct peer *peer, } return 0; } + bgp_bfd_deregister_peer(peer); peer_global_config_reset (peer); } @@ -3234,7 +3233,6 @@ static const struct peer_flag_action peer_flag_action_list[] = { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset }, { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset }, { PEER_FLAG_CAPABILITY_ENHE, 0, peer_change_reset }, - { PEER_FLAG_BFD, 0, peer_change_none }, { 0, 0, 0 } }; @@ -6073,9 +6071,8 @@ bgp_config_write_peer (struct vty *vty, struct bgp *bgp, vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE); /* bfd. */ - if (CHECK_FLAG (peer->flags, PEER_FLAG_BFD)) - if (! peer_group_active (peer) || - ! CHECK_FLAG (g_peer->flags, PEER_FLAG_BFD)) + if (peer->bfd_info) + if (! peer_group_active (peer) || ! g_peer->bfd_info) { bgp_bfd_peer_config_write(vty, peer, addr); } diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 1778aadbef..b20b080123 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -610,11 +610,10 @@ struct peer #define PEER_FLAG_LOCAL_AS_REPLACE_AS (1 << 8) /* local-as no-prepend replace-as */ #define PEER_FLAG_DELETE (1 << 9) /* mark the peer for deleting */ #define PEER_FLAG_CONFIG_NODE (1 << 10) /* the node to update configs on */ -#define PEER_FLAG_BFD (1 << 11) /* bfd */ -#define PEER_FLAG_LONESOUL (1 << 12) -#define PEER_FLAG_DYNAMIC_NEIGHBOR (1 << 13) /* dynamic neighbor */ -#define PEER_FLAG_CAPABILITY_ENHE (1 << 14) /* Extended next-hop (rfc 5549)*/ -#define PEER_FLAG_IFPEER_V6ONLY (1 << 15) /* if-based peer is v6 only * +#define PEER_FLAG_LONESOUL (1 << 11) +#define PEER_FLAG_DYNAMIC_NEIGHBOR (1 << 12) /* dynamic neighbor */ +#define PEER_FLAG_CAPABILITY_ENHE (1 << 13) /* Extended next-hop (rfc 5549)*/ +#define PEER_FLAG_IFPEER_V6ONLY (1 << 14) /* if-based peer is v6 only * /* NSF mode (graceful restart) */ u_char nsf[AFI_MAX][SAFI_MAX]; diff --git a/lib/Makefile.am b/lib/Makefile.am index 1ed1d0a702..76aedf2c0b 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -13,7 +13,7 @@ libzebra_la_SOURCES = \ filter.c routemap.c distribute.c stream.c str.c log.c plist.c \ zclient.c sockopt.c smux.c agentx.c snmp.c md5.c if_rmap.c keychain.c privs.c \ sigevent.c pqueue.c jhash.c memtypes.c workqueue.c nexthop.c json.c \ - ptm_lib.c csv.c + ptm_lib.c csv.c bfd.c BUILT_SOURCES = memtypes.h route_types.h gitversion.h @@ -29,7 +29,7 @@ pkginclude_HEADERS = \ plist.h zclient.h sockopt.h smux.h md5.h if_rmap.h keychain.h \ privs.h sigevent.h pqueue.h jhash.h zassert.h memtypes.h \ workqueue.h route_types.h libospf.h nexthop.h json.h \ - ptm_lib.h csv.h + ptm_lib.h csv.h bfd.h EXTRA_DIST = \ regex.c regex-gnu.h \ diff --git a/lib/bfd.c b/lib/bfd.c new file mode 100644 index 0000000000..78e015898f --- /dev/null +++ b/lib/bfd.c @@ -0,0 +1,287 @@ +/** + * bfd.c: BFD handling routines + * + * @copyright Copyright (C) 2015 Cumulus Networks, Inc. + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include + +#include "command.h" +#include "memory.h" +#include "prefix.h" +#include "thread.h" +#include "stream.h" +#include "zclient.h" +#include "table.h" +#include "vty.h" +#include "bfd.h" + +/* + * bfd_info_create - Allocate the BFD information + */ +struct bfd_info * +bfd_info_create(void) +{ + struct bfd_info *bfd_info; + + bfd_info = XCALLOC (MTYPE_BFD_INFO, sizeof (struct bfd_info)); + assert(bfd_info); + + return bfd_info; +} + +/* + * bfd_info_free - Free the BFD information. + */ +void +bfd_info_free(void **bfd_info) +{ + if (*bfd_info) + { + XFREE (MTYPE_BFD_INFO, *bfd_info); + *bfd_info = NULL; + } +} + +/* + * bfd_validate_param - Validate the BFD paramter information. + */ +int +bfd_validate_param(struct vty *vty, const char *dm_str, const char *rx_str, + const char *tx_str, u_int8_t *dm_val, u_int32_t *rx_val, + u_int32_t *tx_val) +{ + VTY_GET_INTEGER_RANGE ("detect-mul", *dm_val, dm_str, + BFD_MIN_DETECT_MULT, BFD_MAX_DETECT_MULT); + VTY_GET_INTEGER_RANGE ("min-rx", *rx_val, rx_str, + BFD_MIN_MIN_RX, BFD_MAX_MIN_RX); + VTY_GET_INTEGER_RANGE ("min-tx", *tx_val, tx_str, + BFD_MIN_MIN_TX, BFD_MAX_MIN_TX); + return CMD_SUCCESS; +} + +/* + * bfd_set_param - Set the configured BFD paramter values + */ +void +bfd_set_param (struct bfd_info **bfd_info, u_int32_t min_rx, u_int32_t min_tx, + u_int8_t detect_mult, int defaults, int *command) +{ + if (!*bfd_info) + { + *bfd_info = bfd_info_create(); + *command = ZEBRA_BFD_DEST_REGISTER; + } + else + { + if (((*bfd_info)->required_min_rx != min_rx) || + ((*bfd_info)->desired_min_tx != min_tx) || + ((*bfd_info)->detect_mult != detect_mult)) + *command = ZEBRA_BFD_DEST_UPDATE; + } + + if (*command) + { + (*bfd_info)->required_min_rx = min_rx; + (*bfd_info)->desired_min_tx = min_tx; + (*bfd_info)->detect_mult = detect_mult; + } + + if (!defaults) + SET_FLAG ((*bfd_info)->flags, BFD_FLAG_PARAM_CFG); + else + UNSET_FLAG ((*bfd_info)->flags, BFD_FLAG_PARAM_CFG); +} + +/* + * bfd_peer_sendmsg - Format and send a peer register/Unregister + * command to Zebra to be forwarded to BFD + */ +void +bfd_peer_sendmsg (struct zclient *zclient, struct bfd_info *bfd_info, + int family, void *dst_ip, void *src_ip, char *if_name, + int ttl, int multihop, int command, int set_flag) +{ + struct stream *s; + int ret; + int len; + + /* Check socket. */ + if (!zclient || zclient->sock < 0) + { + zlog_debug("%s: Can't send BFD peer register, Zebra client not " + "established", __FUNCTION__); + return; + } + + s = zclient->obuf; + stream_reset (s); + zclient_create_header (s, command); + + stream_putw(s, family); + switch (family) + { + case AF_INET: + stream_put_in_addr (s, (struct in_addr *)dst_ip); + break; +#ifdef HAVE_IPV6 + case AF_INET6: + stream_put(s, dst_ip, 16); + break; +#endif + default: + break; + } + + if (command != ZEBRA_BFD_DEST_DEREGISTER) + { + stream_putl(s, bfd_info->required_min_rx); + stream_putl(s, bfd_info->desired_min_tx); + stream_putc(s, bfd_info->detect_mult); + } + + if (multihop) + { + stream_putc(s, 1); + /* Multi-hop destination send the source IP address to BFD */ + if (src_ip) + { + stream_putw(s, family); + switch (family) + { + case AF_INET: + stream_put_in_addr (s, (struct in_addr *) src_ip); + break; + #ifdef HAVE_IPV6 + case AF_INET6: + stream_put(s, src_ip, 16); + break; + #endif + default: + break; + } + } + stream_putc(s, ttl); + } + else + { + stream_putc(s, 0); +#ifdef HAVE_IPV6 + if ((family == AF_INET6) && (src_ip)) + { + stream_putw(s, family); + stream_put(s, src_ip, 16); + } +#endif + if (if_name) + { + len = strlen(if_name); + stream_putc(s, len); + stream_put(s, if_name, len); + } + else + { + stream_putc(s, 0); + } + } + + stream_putw_at (s, 0, stream_get_endp (s)); + + ret = zclient_send_message(zclient); + + if (ret < 0) + { + zlog_warn("bfd_peer_sendmsg: zclient_send_message() failed"); + return; + } + + if (set_flag) + { + if (command == ZEBRA_BFD_DEST_REGISTER) + SET_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG); + else if (command == ZEBRA_BFD_DEST_DEREGISTER) + UNSET_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG); + } + + return; +} + +/* + * bfd_get_command_dbg_str - Convert command to a debug string. + */ +const char * +bfd_get_command_dbg_str(int command) +{ + switch (command) + { + case ZEBRA_BFD_DEST_REGISTER: + return "Register"; + case ZEBRA_BFD_DEST_DEREGISTER: + return "Deregister"; + case ZEBRA_BFD_DEST_UPDATE: + return "Update"; + default: + return "Unknown"; + } +} + +/* + * bfd_get_peer_info - Extract the Peer information for which the BFD session + * went down from the message sent from Zebra to clients. + */ +struct interface * +bfd_get_peer_info (struct stream *s, struct prefix *dp, struct prefix *sp) +{ + unsigned int ifindex; + struct interface *ifp = NULL; + int plen; + + /* Get interface index. */ + ifindex = stream_getl (s); + + /* Lookup index. */ + if (ifindex != 0) + { + ifp = if_lookup_by_index (ifindex); + if (ifp == NULL) + { + zlog_warn ("zebra_interface_bfd_read: " + "Can't find interface by ifindex: %d ", ifindex); + return NULL; + } + } + + /* Fetch destination address. */ + dp->family = stream_getc (s); + + plen = prefix_blen (dp); + stream_get (&dp->u.prefix, s, plen); + dp->prefixlen = stream_getc (s); + + if (sp) + { + sp->family = stream_getc (s); + + plen = prefix_blen (sp); + stream_get (&sp->u.prefix, s, plen); + sp->prefixlen = stream_getc (s); + } + return ifp; +} diff --git a/lib/bfd.h b/lib/bfd.h new file mode 100644 index 0000000000..6ad1868dc2 --- /dev/null +++ b/lib/bfd.h @@ -0,0 +1,77 @@ +/** + * bfd.h: BFD definitions and structures + * + * @copyright Copyright (C) 2015 Cumulus Networks, Inc. + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef _ZEBRA_BFD_H +#define _ZEBRA_BFD_H + +#define BFD_CMD_DETECT_MULT_RANGE "<2-255> " +#define BFD_CMD_MIN_RX_RANGE "<50-60000> " +#define BFD_CMD_MIN_TX_RANGE "<50-60000>" + +#define BFD_DEF_MIN_RX 300 +#define BFD_MIN_MIN_RX 50 +#define BFD_MAX_MIN_RX 60000 +#define BFD_DEF_MIN_TX 300 +#define BFD_MIN_MIN_TX 50 +#define BFD_MAX_MIN_TX 60000 +#define BFD_DEF_DETECT_MULT 3 +#define BFD_MIN_DETECT_MULT 2 +#define BFD_MAX_DETECT_MULT 255 + +#define BFD_FLAG_PARAM_CFG (1 << 0) /* parameters have been configured */ +#define BFD_FLAG_BFD_REG (1 << 1) /* Peer registered with BFD */ + +struct bfd_info +{ + u_int16_t flags; + u_int8_t detect_mult; + u_int32_t desired_min_tx; + u_int32_t required_min_rx; +}; + +extern struct bfd_info * +bfd_info_create(void); + +extern void +bfd_info_free(void **bfd_info); + +extern int +bfd_validate_param(struct vty *vty, const char *dm_str, const char *rx_str, + const char *tx_str, u_int8_t *dm_val, u_int32_t *rx_val, + u_int32_t *tx_val); + +extern void +bfd_set_param (struct bfd_info **bfd_info, u_int32_t min_rx, u_int32_t min_tx, + u_int8_t detect_mult, int defaults, int *command); +extern void +bfd_peer_sendmsg (struct zclient *zclient, struct bfd_info *bfd_info, + int family, void *dst_ip, void *src_ip, char *if_name, + int ttl, int multihop, int command, int set_flag); + +extern const char * +bfd_get_command_dbg_str(int command); + +extern struct interface * +bfd_get_peer_info (struct stream *s, struct prefix *dp, struct prefix *sp); + +#endif /* _ZEBRA_BFD_H */ diff --git a/lib/memtypes.c b/lib/memtypes.c index 57eb31ff34..f0f11c2ca7 100644 --- a/lib/memtypes.c +++ b/lib/memtypes.c @@ -71,6 +71,7 @@ struct memory_list memory_list_lib[] = { MTYPE_PQUEUE, "Priority queue" }, { MTYPE_PQUEUE_DATA, "Priority queue data" }, { MTYPE_HOST, "Host config" }, + { MTYPE_BFD_INFO, "BFD info" }, { -1, NULL }, }; @@ -162,7 +163,6 @@ struct memory_list memory_list_bgp[] = { MTYPE_BGP_REGEXP, "BGP regexp" }, { MTYPE_BGP_AGGREGATE, "BGP aggregate" }, { MTYPE_BGP_ADDR, "BGP own address" }, - { MTYPE_BGP_PEER_BFD_INFO, "BGP peer BFD info" }, { -1, NULL } }; diff --git a/lib/zclient.c b/lib/zclient.c index 1b03510ed5..39b6f8ec5f 100644 --- a/lib/zclient.c +++ b/lib/zclient.c @@ -942,46 +942,6 @@ memconstant(const void *s, int c, size_t n) return 1; } -struct interface* -zebra_interface_bfd_read (struct stream *s, struct prefix *dp, - struct prefix *sp) -{ - unsigned int ifindex; - struct interface *ifp = NULL; - int plen; - - /* Get interface index. */ - ifindex = stream_getl (s); - - /* Lookup index. */ - if (ifindex != 0) - { - ifp = if_lookup_by_index (ifindex); - if (ifp == NULL) - { - zlog_warn ("zebra_interface_bfd_read: " - "Can't find interface by ifindex: %d ", ifindex); - return NULL; - } - } - - /* Fetch destination address. */ - dp->family = stream_getc (s); - - plen = prefix_blen (dp); - stream_get (&dp->u.prefix, s, plen); - dp->prefixlen = stream_getc (s); - - if (sp) - { - sp->family = stream_getc (s); - - plen = prefix_blen (sp); - stream_get (&sp->u.prefix, s, plen); - sp->prefixlen = stream_getc (s); - } - return ifp; -} struct connected * zebra_interface_address_read (int type, struct stream *s) diff --git a/lib/zclient.h b/lib/zclient.h index ab8c03e2d1..26cae04344 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -177,9 +177,6 @@ extern void zclient_create_header (struct stream *, uint16_t); extern struct interface *zebra_interface_add_read (struct stream *); extern struct interface *zebra_interface_state_read (struct stream *s); extern struct connected *zebra_interface_address_read (int, struct stream *); -extern struct interface *zebra_interface_bfd_read (struct stream *s, - struct prefix *, - struct prefix *); extern struct nbr_connected *zebra_interface_nbr_address_read (int, struct stream *); extern void zebra_interface_if_set_value (struct stream *, struct interface *); extern void zebra_router_id_update_read (struct stream *s, struct prefix *rid); diff --git a/ospf6d/Makefile.am b/ospf6d/Makefile.am index 726ce543e1..ec729d899c 100644 --- a/ospf6d/Makefile.am +++ b/ospf6d/Makefile.am @@ -15,14 +15,14 @@ libospf6_a_SOURCES = \ ospf6_top.c ospf6_area.c ospf6_interface.c ospf6_neighbor.c \ ospf6_flood.c ospf6_route.c ospf6_intra.c ospf6_zebra.c \ ospf6_spf.c ospf6_proto.c ospf6_asbr.c ospf6_abr.c ospf6_snmp.c \ - ospf6d.c + ospf6d.c ospf6_bfd.c noinst_HEADERS = \ ospf6_network.h ospf6_message.h ospf6_lsa.h ospf6_lsdb.h \ ospf6_top.h ospf6_area.h ospf6_interface.h ospf6_neighbor.h \ ospf6_flood.h ospf6_route.h ospf6_intra.h ospf6_zebra.h \ ospf6_spf.h ospf6_proto.h ospf6_asbr.h ospf6_abr.h ospf6_snmp.h \ - ospf6d.h + ospf6d.h ospf6_bfd.h ospf6d_SOURCES = \ ospf6_main.c $(libospf6_a_SOURCES) diff --git a/ospf6d/ospf6_bfd.c b/ospf6d/ospf6_bfd.c new file mode 100644 index 0000000000..e30f4962d1 --- /dev/null +++ b/ospf6d/ospf6_bfd.c @@ -0,0 +1,341 @@ +/** + * ospf6_bfd.c: IPv6 OSPF BFD handling routines + * + * @copyright Copyright (C) 2015 Cumulus Networks, Inc. + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include + +#include "command.h" +#include "linklist.h" +#include "memory.h" +#include "prefix.h" +#include "thread.h" +#include "buffer.h" +#include "stream.h" +#include "zclient.h" +#include "vty.h" +#include "table.h" +#include "bfd.h" +#include "if.h" +#include "ospf6d.h" +#include "ospf6_message.h" +#include "ospf6_neighbor.h" +#include "ospf6_interface.h" +#include "ospf6_route.h" +#include "ospf6_zebra.h" +#include "ospf6_bfd.h" + +extern struct zclient *zclient; + +/* + * ospf6_bfd_reg_dereg_nbr - Register/Deregister a neighbor with BFD through + * zebra for starting/stopping the monitoring of + * the neighbor rechahability. + */ +static void +ospf6_bfd_reg_dereg_nbr (struct ospf6_neighbor *on, int command) +{ + struct ospf6_interface *oi = on->ospf6_if; + struct interface *ifp = oi->interface; + struct bfd_info *bfd_info; + char src[64]; + + if (!oi->bfd_info) + return; + bfd_info = (struct bfd_info *)oi->bfd_info; + + if (IS_OSPF6_DEBUG_ZEBRA(SEND)) + { + inet_ntop (AF_INET6, &on->linklocal_addr, src, sizeof (src)); + zlog_debug ("%s nbr (%s) with BFD", + bfd_get_command_dbg_str(command), src); + } + + bfd_peer_sendmsg (zclient, bfd_info, AF_INET6, &on->linklocal_addr, + on->ospf6_if->linklocal_addr, ifp->name, + 0, 0, command, 0); +} + +/* + * ospf6_bfd_trigger_event - Neighbor is registered/deregistered with BFD when + * neighbor state is changed to/from 2way. + */ +void +ospf6_bfd_trigger_event(struct ospf6_neighbor *on, int old_state, int state) +{ + if ((old_state < OSPF6_NEIGHBOR_TWOWAY) && (state >= OSPF6_NEIGHBOR_TWOWAY)) + ospf6_bfd_reg_dereg_nbr(on, ZEBRA_BFD_DEST_REGISTER); + else if ((old_state >= OSPF6_NEIGHBOR_TWOWAY) && + (state < OSPF6_NEIGHBOR_TWOWAY)) + ospf6_bfd_reg_dereg_nbr(on, ZEBRA_BFD_DEST_DEREGISTER); +} + +/* + * ospf6_bfd_reg_dereg_all_nbr - Register/Deregister all neighbors associated + * with a interface with BFD through + * zebra for starting/stopping the monitoring of + * the neighbor rechahability. + */ +static void +ospf6_bfd_reg_dereg_all_nbr (struct ospf6_interface *oi, int command) +{ + struct ospf6_neighbor *on; + struct listnode *node; + + for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, node, on)) + { + if (on->state < OSPF6_NEIGHBOR_TWOWAY) + continue; + + ospf6_bfd_reg_dereg_nbr(on, command); + } +} + +/* + * ospf6_bfd_nbr_replay - Replay all the neighbors that have BFD enabled + * to zebra + */ +static int +ospf6_bfd_nbr_replay (int command, struct zclient *client, zebra_size_t length) +{ + struct listnode *inode, *nnode; + struct interface *ifp; + struct ospf6_interface *oi; + struct ospf6_neighbor *on; + char dst[64]; + + if (IS_OSPF6_DEBUG_ZEBRA(RECV)) + zlog_debug("Zebra: BFD Dest replay request"); + + /* Replay the neighbor, if BFD is enabled on the interface*/ + for (ALL_LIST_ELEMENTS_RO (iflist, inode, ifp)) + { + oi = (struct ospf6_interface *) ifp->info; + + if (!oi || !oi->bfd_info) + continue; + + for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, nnode, on)) + { + if (on->state < OSPF6_NEIGHBOR_TWOWAY) + continue; + + if (IS_OSPF6_DEBUG_ZEBRA(SEND)) + { + inet_ntop (AF_INET6, &on->linklocal_addr, dst, sizeof (dst)); + zlog_debug ("Replaying nbr (%s) to BFD", dst); + } + + ospf6_bfd_reg_dereg_nbr(on, ZEBRA_BFD_DEST_UPDATE); + } + } + return 0; +} + +/* + * ospf6_bfd_interface_dest_down - Find the neighbor for which the BFD status + * has changed and bring down the neighbor + * connectivity. + */ +static int +ospf6_bfd_interface_dest_down (int command, struct zclient *zclient, + zebra_size_t length) +{ + struct interface *ifp; + struct ospf6_interface *oi; + struct ospf6_neighbor *on; + struct prefix dp; + struct prefix sp; + struct listnode *node, *nnode; + char dst[64]; + + ifp = bfd_get_peer_info(zclient->ibuf, &dp, &sp); + + if ((ifp == NULL) || (dp.family != AF_INET6)) + return 0; + + if (IS_OSPF6_DEBUG_ZEBRA (RECV)) + { + char buf[128]; + prefix2str(&dp, buf, sizeof(buf)); + zlog_debug("Zebra: interface %s bfd destination %s down", ifp->name, buf); + } + + + oi = (struct ospf6_interface *) ifp->info; + if (!oi || !oi->bfd_info) + return 0; + + for (ALL_LIST_ELEMENTS (oi->neighbor_list, node, nnode, on)) + { + if (memcmp(&(on->linklocal_addr), &dp.u.prefix6, sizeof(struct in6_addr))) + continue; + + if (IS_OSPF6_DEBUG_NEIGHBOR (EVENT)) + { + inet_ntop (AF_INET6, &on->linklocal_addr, dst, sizeof (dst)); + zlog_debug ("[%s:%s]: BFD Down", ifp->name, dst); + } + + THREAD_OFF (on->inactivity_timer); + thread_add_event (master, inactivity_timer, on, 0); + } + + return 0; +} + +/* + * ospf6_bfd_write_config - Write the interface BFD configuration. + */ +void +ospf6_bfd_write_config(struct vty *vty, struct ospf6_interface *oi) +{ + struct bfd_info *bfd_info; + + if (!oi->bfd_info) + return; + + bfd_info = (struct bfd_info *)oi->bfd_info; + + if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG)) + vty_out (vty, " ipv6 ospf6 bfd %d %d %d%s", + bfd_info->detect_mult, bfd_info->required_min_rx, + bfd_info->desired_min_tx, VTY_NEWLINE); + else + vty_out (vty, " ipv6 ospf6 bfd%s", VTY_NEWLINE); +} + +/* + * ospf6_bfd_if_param_set - Set the configured BFD paramter values for + * interface. + */ +static void +ospf6_bfd_if_param_set (struct ospf6_interface *oi, u_int32_t min_rx, + u_int32_t min_tx, u_int8_t detect_mult, + int defaults) +{ + int command = 0; + + bfd_set_param((struct bfd_info **)&(oi->bfd_info), min_rx, min_tx, detect_mult, + defaults, &command); + if (command) + ospf6_bfd_reg_dereg_all_nbr(oi, command); +} + +DEFUN (ipv6_ospf6_bfd, + ipv6_ospf6_bfd_cmd, + "ipv6 ospf6 bfd", + IP6_STR + OSPF6_STR + "Enables BFD support\n" + ) +{ + struct ospf6_interface *oi; + struct interface *ifp; + + ifp = (struct interface *) vty->index; + assert (ifp); + + oi = (struct ospf6_interface *) ifp->info; + if (oi == NULL) + oi = ospf6_interface_create (ifp); + assert (oi); + + ospf6_bfd_if_param_set (oi, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, + BFD_DEF_DETECT_MULT, 1); + return CMD_SUCCESS; +} + +DEFUN (ipv6_ospf6_bfd_param, + ipv6_ospf6_bfd_param_cmd, + "ipv6 ospf6 bfd " BFD_CMD_DETECT_MULT_RANGE BFD_CMD_MIN_RX_RANGE BFD_CMD_MIN_TX_RANGE, + IP6_STR + OSPF6_STR + "Enables BFD support\n" + "Detect Multiplier\n" + "Required min receive interval\n" + "Desired min transmit interval\n") +{ + struct ospf6_interface *oi; + struct interface *ifp; + u_int32_t rx_val; + u_int32_t tx_val; + u_int8_t dm_val; + int ret; + + ifp = (struct interface *) vty->index; + assert (ifp); + + oi = (struct ospf6_interface *) ifp->info; + if (oi == NULL) + oi = ospf6_interface_create (ifp); + assert (oi); + + if ((ret = bfd_validate_param (vty, argv[0], argv[1], argv[2], &dm_val, + &rx_val, &tx_val)) != CMD_SUCCESS) + return ret; + + ospf6_bfd_if_param_set (oi, rx_val, tx_val, dm_val, 0); + + return CMD_SUCCESS; +} + +DEFUN (no_ipv6_ospf6_bfd, + no_ipv6_ospf6_bfd_cmd, + "no ipv6 ospf6 bfd", + NO_STR + IP6_STR + OSPF6_STR + "Disables BFD support\n" + ) +{ + struct ospf6_interface *oi; + struct interface *ifp; + + ifp = (struct interface *) vty->index; + assert (ifp); + + oi = (struct ospf6_interface *) ifp->info; + if (oi == NULL) + oi = ospf6_interface_create (ifp); + assert (oi); + + if (oi->bfd_info) + { + ospf6_bfd_reg_dereg_all_nbr(oi, ZEBRA_BFD_DEST_DEREGISTER); + bfd_info_free(&(oi->bfd_info)); + } + + return CMD_SUCCESS; +} + +void +ospf6_bfd_init(void) +{ + /* Initialize BFD client functions */ + zclient->interface_bfd_dest_down = ospf6_bfd_interface_dest_down; + zclient->bfd_dest_replay = ospf6_bfd_nbr_replay; + + /* Install BFD command */ + install_element (INTERFACE_NODE, &ipv6_ospf6_bfd_cmd); + install_element (INTERFACE_NODE, &ipv6_ospf6_bfd_param_cmd); + install_element (INTERFACE_NODE, &no_ipv6_ospf6_bfd_cmd); +} diff --git a/ospf6d/ospf6_bfd.h b/ospf6d/ospf6_bfd.h new file mode 100644 index 0000000000..eaaf157852 --- /dev/null +++ b/ospf6d/ospf6_bfd.h @@ -0,0 +1,36 @@ +/** + * ospf6_bfd.h: OSPF6 BFD definitions and structures + * + * @copyright Copyright (C) 2015 Cumulus Networks, Inc. + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef OSPF6_BFD_H +#define OSPF6_BFD_H + +extern void +ospf6_bfd_init(void); + +extern void +ospf6_bfd_trigger_event(struct ospf6_neighbor *nbr, int old_state, int state); + +extern void +ospf6_bfd_write_config(struct vty *vty, struct ospf6_interface *oi); + +#endif /* OSPF6_BFD_H */ diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index 5043be4358..a45bdd5d6e 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -28,6 +28,7 @@ #include "thread.h" #include "prefix.h" #include "plist.h" +#include "bfd.h" #include "ospf6_lsa.h" #include "ospf6_lsdb.h" @@ -41,6 +42,7 @@ #include "ospf6_intra.h" #include "ospf6_spf.h" #include "ospf6d.h" +#include "ospf6_bfd.h" unsigned char conf_debug_ospf6_interface = 0; @@ -260,6 +262,8 @@ ospf6_interface_delete (struct ospf6_interface *oi) if (oi->plist_name) XFREE (MTYPE_PREFIX_LIST_STR, oi->plist_name); + bfd_info_free(&(oi->bfd_info)); + XFREE (MTYPE_OSPF6_IF, oi); } @@ -1859,6 +1863,8 @@ config_write_ospf6_interface (struct vty *vty) else if (oi->type == OSPF_IFTYPE_BROADCAST) vty_out (vty, " ipv6 ospf6 network broadcast%s", VNL); + ospf6_bfd_write_config(vty, oi); + vty_out (vty, "!%s", VNL); } return 0; diff --git a/ospf6d/ospf6_interface.h b/ospf6d/ospf6_interface.h index dde589b8fa..6ef9e37822 100644 --- a/ospf6d/ospf6_interface.h +++ b/ospf6d/ospf6_interface.h @@ -113,6 +113,9 @@ struct ospf6_interface /* prefix-list name to filter connected prefix */ char *plist_name; + + /* BFD information */ + void *bfd_info; }; /* interface state */ diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c index 7f6c6c5cd8..c5edd226d5 100644 --- a/ospf6d/ospf6_neighbor.c +++ b/ospf6d/ospf6_neighbor.c @@ -39,6 +39,7 @@ #include "ospf6_intra.h" #include "ospf6_flood.h" #include "ospf6d.h" +#include "ospf6_bfd.h" unsigned char conf_debug_ospf6_neighbor = 0; @@ -199,7 +200,7 @@ ospf6_neighbor_state_change (u_char next_state, struct ospf6_neighbor *on, int e (next_state < prev_state)) ospf6TrapNbrStateChange (on); #endif - + ospf6_bfd_trigger_event(on, prev_state, next_state); } /* RFC2328 section 10.4 */ diff --git a/ospf6d/ospf6d.c b/ospf6d/ospf6d.c index 0f456b1a7c..98d4e1787d 100644 --- a/ospf6d/ospf6d.c +++ b/ospf6d/ospf6d.c @@ -43,6 +43,7 @@ #include "ospf6_abr.h" #include "ospf6_flood.h" #include "ospf6d.h" +#include "ospf6_bfd.h" #ifdef HAVE_SNMP #include "ospf6_snmp.h" @@ -1780,6 +1781,7 @@ ospf6_init (void) ospf6_snmp_init (master); #endif /*HAVE_SNMP*/ + ospf6_bfd_init(); install_node (&debug_node, config_write_ospf6_debug); install_element_ospf6_debug_message (); diff --git a/ospfd/Makefile.am b/ospfd/Makefile.am index 4e1a4fe9f0..8a325ed7d3 100644 --- a/ospfd/Makefile.am +++ b/ospfd/Makefile.am @@ -14,7 +14,8 @@ libospf_la_SOURCES = \ ospf_nsm.c ospf_dump.c ospf_network.c ospf_packet.c ospf_lsa.c \ ospf_spf.c ospf_route.c ospf_ase.c ospf_abr.c ospf_ia.c ospf_flood.c \ ospf_lsdb.c ospf_asbr.c ospf_routemap.c ospf_snmp.c \ - ospf_opaque.c ospf_te.c ospf_vty.c ospf_api.c ospf_apiserver.c + ospf_opaque.c ospf_te.c ospf_vty.c ospf_api.c ospf_apiserver.c \ + ospf_bfd.c ospfdheaderdir = $(pkgincludedir)/ospfd @@ -25,7 +26,8 @@ ospfdheader_HEADERS = \ noinst_HEADERS = \ ospf_interface.h ospf_neighbor.h ospf_network.h ospf_packet.h \ ospf_zebra.h ospf_spf.h ospf_route.h ospf_ase.h ospf_abr.h ospf_ia.h \ - ospf_flood.h ospf_snmp.h ospf_te.h ospf_vty.h ospf_apiserver.h + ospf_flood.h ospf_snmp.h ospf_te.h ospf_vty.h ospf_apiserver.h \ + ospf_bfd.h ospfd_SOURCES = ospf_main.c diff --git a/ospfd/ospf_bfd.c b/ospfd/ospf_bfd.c new file mode 100644 index 0000000000..054a806bbd --- /dev/null +++ b/ospfd/ospf_bfd.c @@ -0,0 +1,352 @@ +/** + * ospf_bfd.c: OSPF BFD handling routines + * + * @copyright Copyright (C) 2015 Cumulus Networks, Inc. + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include + +#include "command.h" +#include "linklist.h" +#include "memory.h" +#include "prefix.h" +#include "thread.h" +#include "buffer.h" +#include "stream.h" +#include "zclient.h" +#include "vty.h" +#include "table.h" +#include "bfd.h" +#include "ospfd.h" +#include "ospf_asbr.h" +#include "ospf_lsa.h" +#include "ospf_lsdb.h" +#include "ospf_neighbor.h" +#include "ospf_interface.h" +#include "ospf_nsm.h" +#include "ospf_bfd.h" +#include "ospf_dump.h" +#include "ospf_vty.h" + +extern struct zclient *zclient; + +/* + * ospf_bfd_reg_dereg_nbr - Register/Deregister a neighbor with BFD through + * zebra for starting/stopping the monitoring of + * the neighbor rechahability. + */ +static void +ospf_bfd_reg_dereg_nbr (struct ospf_neighbor *nbr, int command) +{ + struct ospf_interface *oi = nbr->oi; + struct interface *ifp = oi->ifp; + struct ospf_if_params *params; + struct bfd_info *bfd_info; + + /* Check if BFD is enabled */ + params = IF_DEF_PARAMS (ifp); + + /* Check if BFD is enabled */ + if (!params->bfd_info) + return; + bfd_info = (struct bfd_info *)params->bfd_info; + + if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) + zlog_debug ("%s nbr (%s) with BFD", + bfd_get_command_dbg_str(command), + inet_ntoa (nbr->src)); + + bfd_peer_sendmsg (zclient, bfd_info, AF_INET, + &nbr->src, NULL, ifp->name, 0, 0, command, 0); +} + +/* + * ospf_bfd_trigger_event - Neighbor is registered/deregistered with BFD when + * neighbor state is changed to/from 2way. + */ +void +ospf_bfd_trigger_event(struct ospf_neighbor *nbr, int old_state, int state) +{ + if ((old_state < NSM_TwoWay) && (state >= NSM_TwoWay)) + ospf_bfd_reg_dereg_nbr(nbr, ZEBRA_BFD_DEST_REGISTER); + else if ((old_state >= NSM_TwoWay) && (state < NSM_TwoWay)) + ospf_bfd_reg_dereg_nbr(nbr, ZEBRA_BFD_DEST_DEREGISTER); +} + +/* + * ospf_bfd_reg_dereg_all_nbr - Register/Deregister all neighbors associated + * with a interface with BFD through + * zebra for starting/stopping the monitoring of + * the neighbor rechahability. + */ +static int +ospf_bfd_reg_dereg_all_nbr (struct interface *ifp, int command) +{ + struct ospf_interface *oi; + struct route_table *nbrs; + struct ospf_neighbor *nbr; + struct route_node *irn; + struct route_node *nrn; + + for (irn = route_top (IF_OIFS (ifp)); irn; irn = route_next (irn)) + { + if ((oi = irn->info) == NULL) + continue; + + if ((nbrs = oi->nbrs) == NULL) + continue; + + for (nrn = route_top (nbrs); nrn; nrn = route_next (nrn)) + { + if ((nbr = nrn->info) == NULL || nbr == oi->nbr_self) + continue; + + if (nbr->state < NSM_TwoWay) + continue; + + ospf_bfd_reg_dereg_nbr(nbr, command); + } + } + + return 0; +} + +/* + * ospf_bfd_nbr_replay - Replay all the neighbors that have BFD enabled + * to zebra + */ +static int +ospf_bfd_nbr_replay (int command, struct zclient *client, zebra_size_t length) +{ + struct listnode *inode, *node, *onode; + struct ospf *ospf; + struct ospf_interface *oi; + struct route_table *nbrs; + struct route_node *rn; + struct ospf_neighbor *nbr; + struct ospf_if_params *params; + + if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) + { + zlog_debug("Zebra: BFD Dest replay request"); + } + + /* Replay the neighbor, if BFD is enabled in BGP */ + for (ALL_LIST_ELEMENTS (om->ospf, node, onode, ospf)) + { + for (ALL_LIST_ELEMENTS_RO (ospf->oiflist, inode, oi)) + { + if ((nbrs = oi->nbrs) == NULL) + continue; + + params = IF_DEF_PARAMS (oi->ifp); + if (!params->bfd_info) + continue; + + for (rn = route_top (nbrs); rn; rn = route_next (rn)) + { + if ((nbr = rn->info) == NULL || nbr == oi->nbr_self) + continue; + + if (nbr->state < NSM_TwoWay) + continue; + + if (IS_DEBUG_OSPF(zebra, ZEBRA_INTERFACE)) + zlog_debug ("Replaying nbr (%s) to BFD", inet_ntoa (nbr->src)); + + ospf_bfd_reg_dereg_nbr(nbr, ZEBRA_BFD_DEST_UPDATE); + } + } + } + return 0; +} + +/* + * ospf_bfd_interface_dest_down - Find the neighbor for which the BFD status + * has changed and bring down the neighbor + * connectivity. + */ +static int +ospf_bfd_interface_dest_down (int command, struct zclient *zclient, + zebra_size_t length) +{ + struct interface *ifp; + struct ospf_interface *oi; + struct ospf_if_params *params; + struct ospf_neighbor *nbr; + struct route_node *node; + struct prefix p; + + ifp = bfd_get_peer_info (zclient->ibuf, &p, NULL); + + if ((ifp == NULL) || (p.family != AF_INET)) + return 0; + + if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) + { + char buf[128]; + prefix2str(&p, buf, sizeof(buf)); + zlog_debug("Zebra: interface %s bfd destination %s down", ifp->name, buf); + } + + params = IF_DEF_PARAMS (ifp); + if (!params->bfd_info) + return 0; + + for (node = route_top (IF_OIFS (ifp)); node; node = route_next (node)) + { + if ((oi = node->info) == NULL) + continue; + + nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &p.u.prefix4); + if (!nbr) + continue; + + if (IS_DEBUG_OSPF (nsm, NSM_EVENTS)) + zlog_debug ("NSM[%s:%s]: BFD Down", + IF_NAME (nbr->oi), inet_ntoa (nbr->address.u.prefix4)); + + OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_InactivityTimer); + } + + return 0; +} + +/* + * ospf_bfd_write_config - Write the interface BFD configuration. + */ +void +ospf_bfd_write_config(struct vty *vty, struct ospf_if_params *params) + +{ + struct bfd_info *bfd_info; + + if (!params->bfd_info) + return; + + bfd_info = (struct bfd_info *)params->bfd_info; + + if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG)) + vty_out (vty, " ip ospf bfd %d %d %d%s", + bfd_info->detect_mult, bfd_info->required_min_rx, + bfd_info->desired_min_tx, VTY_NEWLINE); + else + vty_out (vty, " ip ospf bfd%s", VTY_NEWLINE); +} + + +/* + * ospf_bfd_if_param_set - Set the configured BFD paramter values for + * interface. + */ +static void +ospf_bfd_if_param_set (struct interface *ifp, u_int32_t min_rx, + u_int32_t min_tx, u_int8_t detect_mult, int defaults) +{ + struct ospf_if_params *params; + int command = 0; + + params = IF_DEF_PARAMS (ifp); + + bfd_set_param(&(params->bfd_info), min_rx, min_tx, detect_mult, + defaults, &command); + if (command) + ospf_bfd_reg_dereg_all_nbr(ifp, command); +} + + +DEFUN (ip_ospf_bfd, + ip_ospf_bfd_cmd, + "ip ospf bfd", + "IP Information\n" + "OSPF interface commands\n" + "Enables BFD support\n") +{ + struct interface *ifp = (struct interface *) vty->index; + + assert (ifp); + ospf_bfd_if_param_set (ifp, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX, + BFD_DEF_DETECT_MULT, 1); + + return CMD_SUCCESS; +} + +DEFUN (ip_ospf_bfd_param, + ip_ospf_bfd_param_cmd, + "ip ospf bfd " BFD_CMD_DETECT_MULT_RANGE BFD_CMD_MIN_RX_RANGE BFD_CMD_MIN_TX_RANGE, + "IP Information\n" + "OSPF interface commands\n" + "Enables BFD support\n" + "Detect Multiplier\n" + "Required min receive interval\n" + "Desired min transmit interval\n") +{ + struct interface *ifp = (struct interface *) vty->index; + u_int32_t rx_val; + u_int32_t tx_val; + u_int8_t dm_val; + int ret; + + assert (ifp); + + if ((ret = bfd_validate_param (vty, argv[0], argv[1], argv[2], &dm_val, + &rx_val, &tx_val)) != CMD_SUCCESS) + return ret; + + ospf_bfd_if_param_set (ifp, rx_val, tx_val, dm_val, 0); + + return CMD_SUCCESS; +} + +DEFUN (no_ip_ospf_bfd, + no_ip_ospf_bfd_cmd, + "no ip ospf bfd", + NO_STR + "IP Information\n" + "OSPF interface commands\n" + "Disables BFD support\n") +{ + struct interface *ifp = (struct interface *)vty->index; + struct ospf_if_params *params; + + assert (ifp); + + params = IF_DEF_PARAMS (ifp); + if (params->bfd_info) + { + ospf_bfd_reg_dereg_all_nbr(ifp, ZEBRA_BFD_DEST_DEREGISTER); + bfd_info_free(&(params->bfd_info)); + } + + return CMD_SUCCESS; +} + +void +ospf_bfd_init(void) +{ + /* Initialize BFD client functions */ + zclient->interface_bfd_dest_down = ospf_bfd_interface_dest_down; + zclient->bfd_dest_replay = ospf_bfd_nbr_replay; + + /* Install BFD command */ + install_element (INTERFACE_NODE, &ip_ospf_bfd_cmd); + install_element (INTERFACE_NODE, &ip_ospf_bfd_param_cmd); + install_element (INTERFACE_NODE, &no_ip_ospf_bfd_cmd); +} diff --git a/ospfd/ospf_bfd.h b/ospfd/ospf_bfd.h new file mode 100644 index 0000000000..436597c0ba --- /dev/null +++ b/ospfd/ospf_bfd.h @@ -0,0 +1,36 @@ +/** + * ospf_bfd.h: OSPF BFD definitions and structures + * + * @copyright Copyright (C) 2015 Cumulus Networks, Inc. + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * GNU Zebra 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 GNU Zebra; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef _ZEBRA_OSPF_BFD_H +#define _ZEBRA_OSPF_BFD_H + +extern void +ospf_bfd_init(void); + +extern void +ospf_bfd_write_config(struct vty *vty, struct ospf_if_params *params); + +extern void +ospf_bfd_trigger_event(struct ospf_neighbor *nbr, int old_state, int state); + +#endif /* _ZEBRA_OSPF_BFD_H */ diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c index 14af7e3425..61fd629b8a 100644 --- a/ospfd/ospf_interface.c +++ b/ospfd/ospf_interface.c @@ -31,6 +31,7 @@ #include "command.h" #include "stream.h" #include "log.h" +#include "bfd.h" #include "ospfd/ospfd.h" #include "ospfd/ospf_spf.h" @@ -560,6 +561,7 @@ void ospf_del_if_params (struct ospf_if_params *oip) { list_delete (oip->auth_crypt); + bfd_info_free(&(oip->bfd_info)); XFREE (MTYPE_OSPF_IF_PARAMS, oip); } diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h index e2d929020f..addc8c7ba3 100644 --- a/ospfd/ospf_interface.h +++ b/ospfd/ospf_interface.h @@ -45,7 +45,6 @@ struct ospf_if_params DECLARE_IF_PARAM (u_int32_t, transmit_delay); /* Interface Transmisson Delay */ DECLARE_IF_PARAM (u_int32_t, output_cost_cmd);/* Command Interface Output Cost */ DECLARE_IF_PARAM (u_int32_t, retransmit_interval); /* Retransmission Interval */ - DECLARE_IF_PARAM (u_char, bfd); /* Respond to BFD events */ DECLARE_IF_PARAM (u_char, passive_interface); /* OSPF Interface is passive: no sending or receiving (no need to join multicast groups) */ DECLARE_IF_PARAM (u_char, priority); /* OSPF Interface priority */ /* Enable OSPF on this interface with area if_area */ @@ -79,6 +78,9 @@ struct ospf_if_params /* Other, non-configuration state */ u_int32_t network_lsa_seqnum; /* Network LSA seqnum */ + + /* BFD configuration */ + void *bfd_info; }; enum diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c index d34e65dc42..77490b310a 100644 --- a/ospfd/ospf_main.c +++ b/ospfd/ospf_main.c @@ -49,6 +49,7 @@ #include "ospfd/ospf_dump.h" #include "ospfd/ospf_zebra.h" #include "ospfd/ospf_vty.h" +#include "ospfd/ospf_bfd.h" /* ospfd privileges */ zebra_capabilities_t _caps_p [] = @@ -312,6 +313,9 @@ main (int argc, char **argv) ospf_vty_show_init (); ospf_vty_clear_init (); + /* OSPF BFD init */ + ospf_bfd_init(); + ospf_route_map_init (); #ifdef HAVE_SNMP ospf_snmp_init (); diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c index b733878496..baf01b22e4 100644 --- a/ospfd/ospf_nsm.c +++ b/ospfd/ospf_nsm.c @@ -48,6 +48,7 @@ #include "ospfd/ospf_flood.h" #include "ospfd/ospf_abr.h" #include "ospfd/ospf_snmp.h" +#include "ospfd/ospf_bfd.h" static void nsm_clear_adj (struct ospf_neighbor *); @@ -811,6 +812,8 @@ nsm_change_state (struct ospf_neighbor *nbr, int state) if (state == NSM_Down) nbr->crypt_seqnum = 0; + ospf_bfd_trigger_event(nbr, old_state, state); + /* Preserve old status? */ } diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 17b5eb27cf..06cf7fa272 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -50,6 +50,7 @@ /*#include "ospfd/ospf_routemap.h" */ #include "ospfd/ospf_vty.h" #include "ospfd/ospf_dump.h" +#include "ospfd/ospf_bfd.h" #define QUAGGA_REDIST_STR_OSPFD \ "(kernel|connected|static|rip|isis|bgp|babel)" @@ -7072,39 +7073,6 @@ ALIAS (no_ip_ospf_priority, "OSPF interface commands\n" "Router priority\n") -DEFUN (ip_ospf_bfd, - ip_ospf_bfd_cmd, - "ip ospf bfd", - "IP Information\n" - "OSPF interface commands\n" - "Respond to BFD session event\n") -{ - struct interface *ifp = vty->index; - struct ospf_if_params *params; - - params = IF_DEF_PARAMS (ifp); - SET_IF_PARAM (params, bfd); - - return CMD_SUCCESS; -} - -DEFUN (no_ip_ospf_bfd, - no_ip_ospf_bfd_cmd, - "no ip ospf bfd", - NO_STR - "IP Information\n" - "OSPF interface commands\n" - "Respond to BFD session event\n") -{ - struct interface *ifp = vty->index; - struct ospf_if_params *params; - - params = IF_DEF_PARAMS (ifp); - UNSET_IF_PARAM (params, bfd); - - return CMD_SUCCESS; -} - DEFUN (ip_ospf_retransmit_interval, ip_ospf_retransmit_interval_addr_cmd, @@ -8795,8 +8763,7 @@ config_write_interface (struct vty *vty) } /* bfd print. */ - if (OSPF_IF_PARAM_CONFIGURED (params, bfd)) - vty_out (vty, " ip ospf bfd%s", VTY_NEWLINE); + ospf_bfd_write_config(vty, params); /* MTU ignore print. */ if (OSPF_IF_PARAM_CONFIGURED (params, mtu_ignore) && @@ -9544,8 +9511,6 @@ ospf_vty_if_init (void) install_element (INTERFACE_NODE, &no_ospf_retransmit_interval_cmd); install_element (INTERFACE_NODE, &ospf_transmit_delay_cmd); install_element (INTERFACE_NODE, &no_ospf_transmit_delay_cmd); - install_element (INTERFACE_NODE, &ip_ospf_bfd_cmd); - install_element (INTERFACE_NODE, &no_ip_ospf_bfd_cmd); } static void diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index 38a4228ce6..58e55564f4 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -327,52 +327,6 @@ ospf_interface_address_delete (int command, struct zclient *zclient, return 0; } -static int -ospf_interface_bfd_dest_down (int command, struct zclient *zclient, - zebra_size_t length) -{ - struct interface *ifp; - struct ospf_interface *oi; - struct ospf_if_params *params; - struct ospf_neighbor *nbr; - struct route_node *node; - struct prefix p; - - ifp = zebra_interface_bfd_read (zclient->ibuf, &p, NULL); - - if (ifp == NULL) - return 0; - - if (IS_DEBUG_OSPF (zebra, ZEBRA_INTERFACE)) - { - char buf[128]; - prefix2str(&p, buf, sizeof(buf)); - zlog_debug("Zebra: interface %s bfd destination %s down", ifp->name, buf); - } - - params = IF_DEF_PARAMS (ifp); - if (!OSPF_IF_PARAM_CONFIGURED (params, bfd)) - return 0; - - for (node = route_top (IF_OIFS (ifp)); node; node = route_next (node)) - { - if ((oi = node->info) == NULL) - continue; - - nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &p.u.prefix4); - if (!nbr) - continue; - - if (IS_DEBUG_OSPF (nsm, NSM_EVENTS)) - zlog_debug ("NSM[%s:%s]: BFD Down", - IF_NAME (nbr->oi), inet_ntoa (nbr->address.u.prefix4)); - - OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_InactivityTimer); - } - - return 0; -} - void ospf_zebra_add (struct prefix_ipv4 *p, struct ospf_route *or) { @@ -1590,7 +1544,6 @@ ospf_zebra_init (u_short instance) zclient->interface_down = ospf_interface_state_down; zclient->interface_address_add = ospf_interface_address_add; zclient->interface_address_delete = ospf_interface_address_delete; - zclient->interface_bfd_dest_down = ospf_interface_bfd_dest_down; zclient->ipv4_route_add = ospf_zebra_read_ipv4; zclient->ipv4_route_delete = ospf_zebra_read_ipv4; diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c index 4681649475..0a90afcaca 100644 --- a/zebra/zebra_ptm.c +++ b/zebra/zebra_ptm.c @@ -303,8 +303,6 @@ zebra_ptm_handle_bfd_msg(void *arg, void *in_ctxt) ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_BFDSTATUS_STR, bfdst_str); if (bfdst_str[0] == '\0') { - zlog_debug("%s: Key %s not found in PTM msg", __func__, - ZEBRA_PTM_BFDSTATUS_STR); return -1; } diff --git a/zebra/zebra_ptm_redistribute.c b/zebra/zebra_ptm_redistribute.c index 5d231de85d..40394f059c 100644 --- a/zebra/zebra_ptm_redistribute.c +++ b/zebra/zebra_ptm_redistribute.c @@ -78,7 +78,8 @@ zebra_interface_bfd_update (struct interface *ifp, struct prefix *dp, for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) { /* Supporting for OSPF and BGP */ - if (client->proto != ZEBRA_ROUTE_OSPF && client->proto != ZEBRA_ROUTE_BGP) + if (client->proto != ZEBRA_ROUTE_OSPF && client->proto != ZEBRA_ROUTE_BGP + && client->proto != ZEBRA_ROUTE_OSPF6) continue; /* Notify to the protocol daemons. */ @@ -113,7 +114,9 @@ zebra_bfd_peer_replay_req (void) for (ALL_LIST_ELEMENTS (zebrad.client_list, node, nnode, client)) { /* Supporting for BGP */ - if (client->proto != ZEBRA_ROUTE_BGP) + if ((client->proto != ZEBRA_ROUTE_BGP) && + (client->proto != ZEBRA_ROUTE_OSPF) && + (client->proto != ZEBRA_ROUTE_OSPF6)) continue; /* Notify to the protocol daemons. */