diff options
-rw-r--r-- | bgpd/bgp_bfd.c | 354 | ||||
-rw-r--r-- | bgpd/bgp_bfd.h | 24 | ||||
-rw-r--r-- | bgpd/bgpd.c | 19 | ||||
-rw-r--r-- | bgpd/bgpd.h | 9 | ||||
-rw-r--r-- | lib/Makefile.am | 4 | ||||
-rw-r--r-- | lib/bfd.c | 287 | ||||
-rw-r--r-- | lib/bfd.h | 77 | ||||
-rw-r--r-- | lib/memtypes.c | 2 | ||||
-rw-r--r-- | lib/zclient.c | 40 | ||||
-rw-r--r-- | lib/zclient.h | 3 | ||||
-rw-r--r-- | ospf6d/Makefile.am | 4 | ||||
-rw-r--r-- | ospf6d/ospf6_bfd.c | 341 | ||||
-rw-r--r-- | ospf6d/ospf6_bfd.h | 36 | ||||
-rw-r--r-- | ospf6d/ospf6_interface.c | 6 | ||||
-rw-r--r-- | ospf6d/ospf6_interface.h | 3 | ||||
-rw-r--r-- | ospf6d/ospf6_neighbor.c | 3 | ||||
-rw-r--r-- | ospf6d/ospf6d.c | 2 | ||||
-rw-r--r-- | ospfd/Makefile.am | 6 | ||||
-rw-r--r-- | ospfd/ospf_bfd.c | 352 | ||||
-rw-r--r-- | ospfd/ospf_bfd.h | 36 | ||||
-rw-r--r-- | ospfd/ospf_interface.c | 2 | ||||
-rw-r--r-- | ospfd/ospf_interface.h | 4 | ||||
-rw-r--r-- | ospfd/ospf_main.c | 4 | ||||
-rw-r--r-- | ospfd/ospf_nsm.c | 3 | ||||
-rw-r--r-- | ospfd/ospf_vty.c | 39 | ||||
-rw-r--r-- | ospfd/ospf_zebra.c | 47 | ||||
-rw-r--r-- | zebra/zebra_ptm.c | 2 | ||||
-rw-r--r-- | zebra/zebra_ptm_redistribute.c | 7 |
28 files changed, 1285 insertions, 431 deletions
diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c index 02047f7f0..87feebe8a 100644 --- a/bgpd/bgp_bfd.c +++ b/bgpd/bgp_bfd.c @@ -32,8 +32,9 @@ #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" @@ -41,46 +42,23 @@ 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. */ 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 8c72c231e..97ad093ee 100644 --- a/bgpd/bgp_bfd.h +++ b/bgpd/bgp_bfd.h @@ -24,31 +24,10 @@ #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); extern void @@ -58,9 +37,6 @@ 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); extern void diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 5a633ed60..dec6b7d68 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 1778aadbe..b20b08012 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 1ed1d0a70..76aedf2c0 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 000000000..78e015898 --- /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 <zebra.h> + +#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 000000000..6ad1868dc --- /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 57eb31ff3..f0f11c2ca 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 1b03510ed..39b6f8ec5 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 ab8c03e2d..26cae0434 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 726ce543e..ec729d899 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 000000000..e30f4962d --- /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 <zebra.h> + +#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 000000000..eaaf15785 --- /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 5043be435..a45bdd5d6 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 dde589b8f..6ef9e3782 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 7f6c6c5cd..c5edd226d 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 0f456b1a7..98d4e1787 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 4e1a4fe9f..8a325ed7d 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 000000000..054a806bb --- /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 <zebra.h> + +#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 000000000..436597c0b --- /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 14af7e342..61fd629b8 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 e2d929020..addc8c7ba 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 d34e65dc4..77490b310 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 b73387849..baf01b22e 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 17b5eb27c..06cf7fa27 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 38a4228ce..58e55564f 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 468164947..0a90afcac 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 5d231de85..40394f059 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. */ |