summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_bfd.c354
-rw-r--r--bgpd/bgp_bfd.h24
-rw-r--r--bgpd/bgpd.c19
-rw-r--r--bgpd/bgpd.h9
-rw-r--r--lib/Makefile.am4
-rw-r--r--lib/bfd.c287
-rw-r--r--lib/bfd.h77
-rw-r--r--lib/memtypes.c2
-rw-r--r--lib/zclient.c40
-rw-r--r--lib/zclient.h3
-rw-r--r--ospf6d/Makefile.am4
-rw-r--r--ospf6d/ospf6_bfd.c341
-rw-r--r--ospf6d/ospf6_bfd.h36
-rw-r--r--ospf6d/ospf6_interface.c6
-rw-r--r--ospf6d/ospf6_interface.h3
-rw-r--r--ospf6d/ospf6_neighbor.c3
-rw-r--r--ospf6d/ospf6d.c2
-rw-r--r--ospfd/Makefile.am6
-rw-r--r--ospfd/ospf_bfd.c352
-rw-r--r--ospfd/ospf_bfd.h36
-rw-r--r--ospfd/ospf_interface.c2
-rw-r--r--ospfd/ospf_interface.h4
-rw-r--r--ospfd/ospf_main.c4
-rw-r--r--ospfd/ospf_nsm.c3
-rw-r--r--ospfd/ospf_vty.c39
-rw-r--r--ospfd/ospf_zebra.c47
-rw-r--r--zebra/zebra_ptm.c2
-rw-r--r--zebra/zebra_ptm_redistribute.c7
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. */