Support of BFD status in Quagga

Ticket:CM-6802, CM-6952
Reviewed By: Donald, Kanna
Testing Done:

Double commit of b76943235e09472ec174edcf7204fc82d27fe966 from br2.5. But, manually resolved all the compilation errors. Also, modified the shows to support the json format which was not supported in br2.5.

CM-6802 – Currently, BFD session status can be monitored only through ptmctl. There is no way to check the BFD status of a peer/neighbor through Quagga. Debugging becomes easier if BFD status is shown in Quagga too. BFD status is relevant when it is shown against the BGP peer/OSPF neighbor. For, this following code changes have been done:
   - Only down messages from PTM were being propagated from Zebra daemon to clients (bgpd, ospfd and ospf6d). Now, both up and down messages are redistributed to the clients from zebra. BFD status field has been added to the messaging. Handling of BFD session up messages has been added to the client code. BGP/OSPF neighbor is brought down only if the old BFD session status is ‘Up’ to handle extra/initial down messages.
   - BFD status and last update timestamp fields have been added to the common BFD info structure. Also, common show functions for showing BFD information have been added to BFD lib.
   - Modified the BGP neighbor show functions to call common BFD lib functions.
   - For ospf and ospf6, BFD information was maintained only at interface level. To show BFD status per neighbor, BFD information has been added at neighbor level too. “show ip ospf interface”, “show ip ospf neighbor detail”, “show ipv6 ospf6 interface” and “show ipv6 ospf6 neighbor detail” output have been modified to show BFD information.

CM-6952 - IBGP peers were always assumed to be multi-hop since there was no easy way to determine whether an IBGP peer was single hop or multihop unlike EBGP. But, this is causing problem with IBGP link local peers since BFD doesn't allow multihop BFD session with link local IP addresses. Link local peers were discovered when the interface peering was enabled. Interface peering is always singlehop. So, added checks to treat all interface based peers as single hop irrespective of whether the peer is IBGP or EBGP.
This commit is contained in:
radhika 2015-08-31 14:56:11 -07:00
parent 89ca90fad9
commit 68fe91d6c7
22 changed files with 497 additions and 140 deletions

View File

@ -73,7 +73,8 @@ bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer)
static int
bgp_bfd_is_peer_multihop(struct peer *peer)
{
if((peer->sort == BGP_PEER_IBGP) || is_ebgp_multihop_configured(peer))
if((peer->conf_if == NULL) && ((peer->sort == BGP_PEER_IBGP) ||
is_ebgp_multihop_configured(peer)))
return 1;
else
return 0;
@ -191,19 +192,46 @@ bgp_bfd_dest_replay (int command, struct zclient *client, zebra_size_t length)
}
/*
* bgp_interface_bfd_dest_down - Find the peer for which the BFD status
* has changed and bring down the peer
* connectivity.
* bgp_bfd_peer_status_update - Update the BFD status if it has changed. Bring
* down the peer if the BFD session went down from * up.
*/
static void
bgp_bfd_peer_status_update (struct peer *peer, int status)
{
struct bfd_info *bfd_info;
int old_status;
bfd_info = (struct bfd_info *)peer->bfd_info;
if (bfd_info->status == status)
return;
old_status = bfd_info->status;
bfd_info->status = status;
bfd_info->last_update = bgp_clock();
if ((status == BFD_STATUS_DOWN) && (old_status == BFD_STATUS_UP))
{
peer->last_reset = PEER_DOWN_BFD_DOWN;
BGP_EVENT_ADD (peer, BGP_Stop);
}
}
/*
* bgp_bfd_dest_update - Find the peer for which the BFD status
* has changed and bring down the peer
* connectivity if the BFD session went down.
*/
static int
bgp_interface_bfd_dest_down (int command, struct zclient *zclient,
bgp_bfd_dest_update (int command, struct zclient *zclient,
zebra_size_t length)
{
struct interface *ifp;
struct prefix dp;
struct prefix sp;
int status;
ifp = bfd_get_peer_info (zclient->ibuf, &dp, &sp);
ifp = bfd_get_peer_info (zclient->ibuf, &dp, &sp, &status);
if (BGP_DEBUG (zebra, ZEBRA))
{
@ -211,14 +239,14 @@ bgp_interface_bfd_dest_down (int command, struct zclient *zclient,
prefix2str(&dp, buf[0], sizeof(buf[0]));
if (ifp)
{
zlog_debug("Zebra: interface %s bfd destination %s down",
ifp->name, buf[0]);
zlog_debug("Zebra: interface %s bfd destination %s %s",
ifp->name, buf[0], bfd_get_status_str(status));
}
else
{
prefix2str(&sp, buf[1], sizeof(buf[1]));
zlog_debug("Zebra: source %s bfd destination %s down",
buf[1], buf[0]);
zlog_debug("Zebra: source %s bfd destination %s %s",
buf[1], buf[0], bfd_get_status_str(status));
}
}
@ -253,8 +281,7 @@ bgp_interface_bfd_dest_down (int command, struct zclient *zclient,
if (ifp && (ifp == peer->nexthop.ifp))
{
peer->last_reset = PEER_DOWN_BFD_DOWN;
BGP_EVENT_ADD (peer, BGP_Stop);
bgp_bfd_peer_status_update(peer, status);
}
else
{
@ -279,8 +306,7 @@ bgp_interface_bfd_dest_down (int command, struct zclient *zclient,
else
continue;
peer->last_reset = PEER_DOWN_BFD_DOWN;
BGP_EVENT_ADD (peer, BGP_Stop);
bgp_bfd_peer_status_update(peer, status);
}
}
}
@ -299,8 +325,8 @@ bgp_bfd_peer_param_set (struct peer *peer, u_int32_t min_rx, u_int32_t min_tx,
struct listnode *node, *nnode;
int command = 0;
bfd_set_param(&(peer->bfd_info), min_rx, min_tx, detect_mult,
defaults, &command);
bfd_set_param((struct bfd_info **)&(peer->bfd_info), min_rx, min_tx,
detect_mult, defaults, &command);
if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
{
@ -308,8 +334,8 @@ bgp_bfd_peer_param_set (struct peer *peer, u_int32_t min_rx, u_int32_t min_tx,
for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
{
command = 0;
bfd_set_param(&(peer->bfd_info), min_rx, min_tx, detect_mult,
defaults, &command);
bfd_set_param((struct bfd_info **)&(peer->bfd_info), min_rx, min_tx,
detect_mult, defaults, &command);
if ((peer->status == Established) &&
(command == ZEBRA_BFD_DEST_REGISTER))
@ -386,38 +412,8 @@ bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr)
void
bgp_bfd_show_info(struct vty *vty, struct peer *peer, u_char use_json, json_object *json_neigh)
{
struct bfd_info *bfd_info;
json_object *json_bfd = NULL;
if (!peer->bfd_info)
return;
if (use_json)
json_bfd = json_object_new_object();
bfd_info = (struct bfd_info *)peer->bfd_info;
if (use_json)
{
if (bgp_bfd_is_peer_multihop(peer))
json_object_string_add(json_bfd, "bfdMultiHop", "yes");
else
json_object_string_add(json_bfd, "bfdMultiHop", "no");
json_object_int_add(json_bfd, "detectMultiplier", bfd_info->detect_mult);
json_object_int_add(json_bfd, "rxMinInterval", bfd_info->required_min_rx);
json_object_int_add(json_bfd, "txMinInterval", bfd_info->desired_min_tx);
json_object_object_add(json_neigh, "peerBfdInfo", json_bfd);
}
else
{
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);
}
bfd_show_info(vty, (struct bfd_info *)peer->bfd_info,
bgp_bfd_is_peer_multihop(peer), 0, use_json, json_neigh);
}
DEFUN (neighbor_bfd,
@ -501,7 +497,7 @@ void
bgp_bfd_init(void)
{
/* Initialize BFD client functions */
zclient->interface_bfd_dest_down = bgp_interface_bfd_dest_down;
zclient->interface_bfd_dest_update = bgp_bfd_dest_update;
zclient->bfd_dest_replay = bgp_bfd_dest_replay;
/* "neighbor bfd" commands. */

152
lib/bfd.c
View File

@ -44,6 +44,8 @@ bfd_info_create(void)
bfd_info = XCALLOC (MTYPE_BFD_INFO, sizeof (struct bfd_info));
assert(bfd_info);
bfd_info->status = BFD_STATUS_UNKNOWN;
bfd_info->last_update = 0;
return bfd_info;
}
@ -247,7 +249,8 @@ bfd_get_command_dbg_str(int command)
* 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)
bfd_get_peer_info (struct stream *s, struct prefix *dp, struct prefix *sp,
int *status)
{
unsigned int ifindex;
struct interface *ifp = NULL;
@ -275,6 +278,9 @@ bfd_get_peer_info (struct stream *s, struct prefix *dp, struct prefix *sp)
stream_get (&dp->u.prefix, s, plen);
dp->prefixlen = stream_getc (s);
/* Get BFD status. */
*status = stream_getl (s);
if (sp)
{
sp->family = stream_getc (s);
@ -285,3 +291,147 @@ bfd_get_peer_info (struct stream *s, struct prefix *dp, struct prefix *sp)
}
return ifp;
}
/*
* bfd_get_status_str - Convert BFD status to a display string.
*/
const char *
bfd_get_status_str(int status)
{
switch (status)
{
case BFD_STATUS_DOWN:
return "Down";
case BFD_STATUS_UP:
return "Up";
case BFD_STATUS_UNKNOWN:
default:
return "Unknown";
}
}
/*
* bfd_last_update - Calculate the last BFD update time and convert it
* into a dd:hh:mm:ss display format.
*/
static void
bfd_last_update (time_t last_update, char *buf, size_t len)
{
time_t curr;
time_t diff;
struct tm *tm;
struct timeval tv;
/* If no BFD satatus update has ever been received, print `never'. */
if (last_update == 0)
{
snprintf (buf, len, "never");
return;
}
/* Get current time. */
quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv);
curr = tv.tv_sec;
diff = curr - last_update;
tm = gmtime (&diff);
snprintf (buf, len, "%d:%02d:%02d:%02d",
tm->tm_yday, tm->tm_hour, tm->tm_min, tm->tm_sec);
}
/*
* bfd_show_param - Show the BFD parameter information.
*/
void
bfd_show_param(struct vty *vty, struct bfd_info *bfd_info, int bfd_tag,
int extra_space, u_char use_json, json_object *json_obj)
{
json_object *json_bfd = NULL;
if (!bfd_info)
return;
if (use_json)
{
if (bfd_tag)
json_bfd = json_object_new_object();
else
json_bfd = json_obj;
json_object_int_add(json_bfd, "detectMultiplier", bfd_info->detect_mult);
json_object_int_add(json_bfd, "rxMinInterval", bfd_info->required_min_rx);
json_object_int_add(json_bfd, "txMinInterval", bfd_info->desired_min_tx);
if (bfd_tag)
json_object_object_add(json_obj, "peerBfdInfo", json_bfd);
}
else
{
vty_out (vty, " %s%sDetect Mul: %d, Min Rx interval: %d,"
" Min Tx interval: %d%s",
(extra_space) ? " ": "", (bfd_tag) ? "BFD: " : " ",
bfd_info->detect_mult, bfd_info->required_min_rx,
bfd_info->desired_min_tx, VTY_NEWLINE);
}
}
/*
* bfd_show_status - Show the BFD status information.
*/
static void
bfd_show_status(struct vty *vty, struct bfd_info *bfd_info, int bfd_tag,
int extra_space, u_char use_json, json_object *json_bfd)
{
char time_buf[32];
if (!bfd_info)
return;
bfd_last_update(bfd_info->last_update, time_buf, 32);
if (use_json)
{
json_object_string_add(json_bfd, "status",
bfd_get_status_str(bfd_info->status));
json_object_string_add(json_bfd, "lastUpdate", time_buf);
}
else
{
vty_out (vty, " %s%sStatus: %s, Last update: %s%s",
(extra_space) ? " ": "", (bfd_tag) ? "BFD: " : " ",
bfd_get_status_str(bfd_info->status), time_buf, VTY_NEWLINE);
}
}
/*
* bfd_show_info - Show the BFD information.
*/
void
bfd_show_info(struct vty *vty, struct bfd_info *bfd_info, int multihop,
int extra_space, u_char use_json, json_object *json_obj)
{
json_object *json_bfd = NULL;
if (!bfd_info)
return;
if (use_json)
{
json_bfd = json_object_new_object();
if (multihop)
json_object_string_add(json_bfd, "type", "multi hop");
else
json_object_string_add(json_bfd, "type", "single hop");
}
else
{
vty_out (vty, " %sBFD: Type: %s%s", (extra_space) ? " " : "",
(multihop) ? "multi hop" : "single hop", VTY_NEWLINE);
}
bfd_show_param(vty, bfd_info, 0, extra_space, use_json, json_bfd);
bfd_show_status(vty, bfd_info, 0, extra_space, use_json, json_bfd);
if (use_json)
json_object_object_add(json_obj, "peerBfdInfo", json_bfd);
else
vty_out (vty, "%s", VTY_NEWLINE);
}

View File

@ -24,6 +24,8 @@
#ifndef _ZEBRA_BFD_H
#define _ZEBRA_BFD_H
#include "lib/json.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>"
@ -41,12 +43,18 @@
#define BFD_FLAG_PARAM_CFG (1 << 0) /* parameters have been configured */
#define BFD_FLAG_BFD_REG (1 << 1) /* Peer registered with BFD */
#define BFD_STATUS_UNKNOWN (1 << 0) /* BFD session status never received */
#define BFD_STATUS_DOWN (1 << 1) /* BFD session status is down */
#define BFD_STATUS_UP (1 << 2) /* BFD session status is up */
struct bfd_info
{
u_int16_t flags;
u_int8_t detect_mult;
u_int32_t desired_min_tx;
u_int32_t required_min_rx;
time_t last_update;
u_int8_t status;
};
extern struct bfd_info *
@ -72,6 +80,18 @@ 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);
bfd_get_peer_info (struct stream *s, struct prefix *dp, struct prefix *sp,
int *status);
const char *
bfd_get_status_str(int status);
extern void
bfd_show_param(struct vty *vty, struct bfd_info *bfd_info, int bfd_tag,
int extra_space, u_char use_json, json_object *json_obj);
extern void
bfd_show_info(struct vty *vty, struct bfd_info *bfd_info, int multihop,
int extra_space, u_char use_json, json_object *json_obj);
#endif /* _ZEBRA_BFD_H */

View File

@ -836,7 +836,7 @@ static const struct zebra_desc_table command_types[] = {
DESC_ENTRY (ZEBRA_INTERFACE_NBR_ADDRESS_ADD),
DESC_ENTRY (ZEBRA_INTERFACE_NBR_ADDRESS_DELETE),
DESC_ENTRY (ZEBRA_IMPORT_CHECK_UPDATE),
DESC_ENTRY (ZEBRA_INTERFACE_BFD_DEST_DOWN),
DESC_ENTRY (ZEBRA_INTERFACE_BFD_DEST_UPDATE),
DESC_ENTRY (ZEBRA_BFD_DEST_REGISTER),
DESC_ENTRY (ZEBRA_BFD_DEST_DEREGISTER),
DESC_ENTRY (ZEBRA_BFD_DEST_UPDATE),

View File

@ -1208,9 +1208,9 @@ zclient_read (struct thread *thread)
if (zclient->interface_address_delete)
(*zclient->interface_address_delete) (command, zclient, length);
break;
case ZEBRA_INTERFACE_BFD_DEST_DOWN:
if (zclient->interface_bfd_dest_down)
(*zclient->interface_bfd_dest_down) (command, zclient, length);
case ZEBRA_INTERFACE_BFD_DEST_UPDATE:
if (zclient->interface_bfd_dest_update)
(*zclient->interface_bfd_dest_update) (command, zclient, length);
break;
case ZEBRA_INTERFACE_NBR_ADDRESS_ADD:
if (zclient->interface_nbr_address_add)

View File

@ -85,7 +85,7 @@ struct zclient
int (*interface_down) (int, struct zclient *, uint16_t);
int (*interface_address_add) (int, struct zclient *, uint16_t);
int (*interface_address_delete) (int, struct zclient *, uint16_t);
int (*interface_bfd_dest_down) (int, struct zclient *, uint16_t);
int (*interface_bfd_dest_update) (int, struct zclient *, uint16_t);
int (*interface_nbr_address_add) (int, struct zclient *, uint16_t);
int (*interface_nbr_address_delete) (int, struct zclient *, uint16_t);
int (*ipv4_route_add) (int, struct zclient *, uint16_t);

View File

@ -429,7 +429,7 @@ struct in_pktinfo
#define ZEBRA_NEXTHOP_UPDATE 26
#define ZEBRA_INTERFACE_NBR_ADDRESS_ADD 27
#define ZEBRA_INTERFACE_NBR_ADDRESS_DELETE 28
#define ZEBRA_INTERFACE_BFD_DEST_DOWN 29
#define ZEBRA_INTERFACE_BFD_DEST_UPDATE 29
#define ZEBRA_IMPORT_ROUTE_REGISTER 30
#define ZEBRA_IMPORT_ROUTE_UNREGISTER 31
#define ZEBRA_IMPORT_CHECK_UPDATE 32

View File

@ -45,6 +45,27 @@
extern struct zclient *zclient;
/*
* ospf6_bfd_info_free - Free BFD info structure
*/
void
ospf6_bfd_info_free(void **bfd_info)
{
bfd_info_free((struct bfd_info **) bfd_info);
}
/*
* ospf6_bfd_show_info - Show BFD info structure
*/
void
ospf6_bfd_show_info(struct vty *vty, void *bfd_info, int param_only)
{
if (param_only)
bfd_show_param(vty, bfd_info, 1, 0, 0, NULL);
else
bfd_show_info(vty, bfd_info, 0, 1, 0, NULL);
}
/*
* ospf6_bfd_reg_dereg_nbr - Register/Deregister a neighbor with BFD through
* zebra for starting/stopping the monitoring of
@ -102,6 +123,11 @@ ospf6_bfd_reg_dereg_all_nbr (struct ospf6_interface *oi, int command)
for (ALL_LIST_ELEMENTS_RO (oi->neighbor_list, node, on))
{
if (command != ZEBRA_BFD_DEST_DEREGISTER)
ospf6_bfd_info_nbr_create(oi, on);
else
bfd_info_free((struct bfd_info **)&on->bfd_info);
if (on->state < OSPF6_NEIGHBOR_TWOWAY)
continue;
@ -151,13 +177,13 @@ ospf6_bfd_nbr_replay (int command, struct zclient *client, zebra_size_t length)
}
/*
* ospf6_bfd_interface_dest_down - Find the neighbor for which the BFD status
* has changed and bring down the neighbor
* connectivity.
* ospf6_bfd_interface_dest_update - Find the neighbor for which the BFD status
* has changed and bring down the neighbor
* connectivity if BFD down is received.
*/
static int
ospf6_bfd_interface_dest_down (int command, struct zclient *zclient,
zebra_size_t length)
ospf6_bfd_interface_dest_update (int command, struct zclient *zclient,
zebra_size_t length)
{
struct interface *ifp;
struct ospf6_interface *oi;
@ -166,8 +192,12 @@ ospf6_bfd_interface_dest_down (int command, struct zclient *zclient,
struct prefix sp;
struct listnode *node, *nnode;
char dst[64];
int status;
int old_status;
struct bfd_info *bfd_info;
struct timeval tv;
ifp = bfd_get_peer_info(zclient->ibuf, &dp, &sp);
ifp = bfd_get_peer_info(zclient->ibuf, &dp, &sp, &status);
if ((ifp == NULL) || (dp.family != AF_INET6))
return 0;
@ -176,7 +206,8 @@ ospf6_bfd_interface_dest_down (int command, struct zclient *zclient,
{
char buf[128];
prefix2str(&dp, buf, sizeof(buf));
zlog_debug("Zebra: interface %s bfd destination %s down", ifp->name, buf);
zlog_debug("Zebra: interface %s bfd destination %s %s", ifp->name, buf,
bfd_get_status_str(status));
}
@ -192,16 +223,56 @@ ospf6_bfd_interface_dest_down (int command, struct zclient *zclient,
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);
zlog_debug ("[%s:%s]: BFD %s", ifp->name, dst,
bfd_get_status_str(status));
}
THREAD_OFF (on->inactivity_timer);
thread_add_event (master, inactivity_timer, on, 0);
if (!on->bfd_info)
continue;
bfd_info = (struct bfd_info *)on->bfd_info;
if (bfd_info->status == status)
continue;
old_status = bfd_info->status;
bfd_info->status = status;
quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv);
bfd_info->last_update = tv.tv_sec;
if ((status == BFD_STATUS_DOWN) && (old_status == BFD_STATUS_UP))
{
THREAD_OFF (on->inactivity_timer);
thread_add_event (master, inactivity_timer, on, 0);
}
}
return 0;
}
/*
* ospf6_bfd_info_nbr_create - Create/update BFD information for a neighbor.
*/
void
ospf6_bfd_info_nbr_create (struct ospf6_interface *oi,
struct ospf6_neighbor *on)
{
struct bfd_info *oi_bfd_info;
struct bfd_info *on_bfd_info;
if (!oi->bfd_info)
return;
oi_bfd_info = (struct bfd_info *)oi->bfd_info;
if (!on->bfd_info)
on->bfd_info = bfd_info_create();
on_bfd_info = (struct bfd_info *)on->bfd_info;
on_bfd_info->detect_mult = oi_bfd_info->detect_mult;
on_bfd_info->desired_min_tx = oi_bfd_info->desired_min_tx;
on_bfd_info->required_min_rx = oi_bfd_info->required_min_rx;
}
/*
* ospf6_bfd_write_config - Write the interface BFD configuration.
*/
@ -321,7 +392,7 @@ DEFUN (no_ipv6_ospf6_bfd,
if (oi->bfd_info)
{
ospf6_bfd_reg_dereg_all_nbr(oi, ZEBRA_BFD_DEST_DEREGISTER);
bfd_info_free(&(oi->bfd_info));
bfd_info_free((struct bfd_info **)&(oi->bfd_info));
}
return CMD_SUCCESS;
@ -331,7 +402,7 @@ void
ospf6_bfd_init(void)
{
/* Initialize BFD client functions */
zclient->interface_bfd_dest_down = ospf6_bfd_interface_dest_down;
zclient->interface_bfd_dest_update = ospf6_bfd_interface_dest_update;
zclient->bfd_dest_replay = ospf6_bfd_nbr_replay;
/* Install BFD command */

View File

@ -33,4 +33,14 @@ 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);
extern void
ospf6_bfd_info_nbr_create (struct ospf6_interface *oi,
struct ospf6_neighbor *on);
extern void
ospf6_bfd_info_free(void **bfd_info);
extern void
ospf6_bfd_show_info(struct vty *vty, void *bfd_info, int param_only);
#endif /* OSPF6_BFD_H */

View File

@ -29,7 +29,6 @@
#include "prefix.h"
#include "plist.h"
#include "zclient.h"
#include "bfd.h"
#include "ospf6_lsa.h"
#include "ospf6_lsdb.h"
@ -263,7 +262,7 @@ 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));
ospf6_bfd_info_free(&(oi->bfd_info));
XFREE (MTYPE_OSPF6_IF, oi);
}
@ -977,7 +976,7 @@ ospf6_interface_show (struct vty *vty, struct interface *ifp)
for (lsa = ospf6_lsdb_head (oi->lsack_list); lsa;
lsa = ospf6_lsdb_next (lsa))
vty_out (vty, " %s%s", lsa->name, VNL);
ospf6_bfd_show_info(vty, oi->bfd_info, 1);
return 0;
}

View File

@ -115,7 +115,7 @@ struct ospf6_interface
char *plist_name;
/* BFD information */
struct bfd_info *bfd_info;
void *bfd_info;
};
/* interface state */

View File

@ -103,6 +103,8 @@ ospf6_neighbor_create (u_int32_t router_id, struct ospf6_interface *oi)
on->lsack_list = ospf6_lsdb_create (on);
listnode_add_sort (oi->neighbor_list, on);
ospf6_bfd_info_nbr_create(oi, on);
return on;
}
@ -139,6 +141,7 @@ ospf6_neighbor_delete (struct ospf6_neighbor *on)
THREAD_OFF (on->thread_send_lsupdate);
THREAD_OFF (on->thread_send_lsack);
ospf6_bfd_info_free(&on->bfd_info);
XFREE (MTYPE_OSPF6_NEIGHBOR, on);
}
@ -815,6 +818,7 @@ ospf6_neighbor_show_detail (struct vty *vty, struct ospf6_neighbor *on)
lsa = ospf6_lsdb_next (lsa))
vty_out (vty, " %s%s", lsa->name, VNL);
ospf6_bfd_show_info(vty, on->bfd_info, 0);
}
DEFUN (show_ipv6_ospf6_neighbor,

View File

@ -96,6 +96,9 @@ struct ospf6_neighbor
struct thread *thread_send_lsreq;
struct thread *thread_send_lsupdate;
struct thread *thread_send_lsack;
/* BFD information */
void *bfd_info;
};
/* Neighbor state */

View File

@ -47,6 +47,15 @@
extern struct zclient *zclient;
/*
* ospf_bfd_info_free - Free BFD info structure
*/
void
ospf_bfd_info_free(void **bfd_info)
{
bfd_info_free((struct bfd_info **) bfd_info);
}
/*
* ospf_bfd_reg_dereg_nbr - Register/Deregister a neighbor with BFD through
* zebra for starting/stopping the monitoring of
@ -118,6 +127,11 @@ ospf_bfd_reg_dereg_all_nbr (struct interface *ifp, int command)
if ((nbr = nrn->info) == NULL || nbr == oi->nbr_self)
continue;
if (command != ZEBRA_BFD_DEST_DEREGISTER)
ospf_bfd_info_nbr_create(oi, nbr);
else
bfd_info_free((struct bfd_info **)&nbr->bfd_info);
if (nbr->state < NSM_TwoWay)
continue;
@ -179,13 +193,14 @@ ospf_bfd_nbr_replay (int command, struct zclient *client, zebra_size_t length)
}
/*
* ospf_bfd_interface_dest_down - Find the neighbor for which the BFD status
* has changed and bring down the neighbor
* connectivity.
* ospf_bfd_interface_dest_update - Find the neighbor for which the BFD status
* has changed and bring down the neighbor
* connectivity if the BFD status changed to
* down.
*/
static int
ospf_bfd_interface_dest_down (int command, struct zclient *zclient,
zebra_size_t length)
ospf_bfd_interface_dest_update (int command, struct zclient *zclient,
zebra_size_t length)
{
struct interface *ifp;
struct ospf_interface *oi;
@ -193,8 +208,12 @@ ospf_bfd_interface_dest_down (int command, struct zclient *zclient,
struct ospf_neighbor *nbr;
struct route_node *node;
struct prefix p;
int status;
int old_status;
struct bfd_info *bfd_info;
struct timeval tv;
ifp = bfd_get_peer_info (zclient->ibuf, &p, NULL);
ifp = bfd_get_peer_info (zclient->ibuf, &p, NULL, &status);
if ((ifp == NULL) || (p.family != AF_INET))
return 0;
@ -203,7 +222,8 @@ ospf_bfd_interface_dest_down (int command, struct zclient *zclient,
{
char buf[128];
prefix2str(&p, buf, sizeof(buf));
zlog_debug("Zebra: interface %s bfd destination %s down", ifp->name, buf);
zlog_debug("Zebra: interface %s bfd destination %s %s", ifp->name, buf,
bfd_get_status_str(status));
}
params = IF_DEF_PARAMS (ifp);
@ -216,19 +236,59 @@ ospf_bfd_interface_dest_down (int command, struct zclient *zclient,
continue;
nbr = ospf_nbr_lookup_by_addr (oi->nbrs, &p.u.prefix4);
if (!nbr)
if (!nbr || !nbr->bfd_info)
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));
bfd_info = (struct bfd_info *)nbr->bfd_info;
if (bfd_info->status == status)
continue;
OSPF_NSM_EVENT_SCHEDULE (nbr, NSM_InactivityTimer);
old_status = bfd_info->status;
bfd_info->status = status;
quagga_gettime (QUAGGA_CLK_MONOTONIC, &tv);
bfd_info->last_update = tv.tv_sec;
if ((status == BFD_STATUS_DOWN) && (old_status == BFD_STATUS_UP))
{
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_info_nbr_create - Create/update BFD information for a neighbor.
*/
void
ospf_bfd_info_nbr_create (struct ospf_interface *oi, struct ospf_neighbor *nbr)
{
struct bfd_info *oi_bfd_info;
struct bfd_info *nbr_bfd_info;
struct interface *ifp = oi->ifp;
struct ospf_if_params *params;
/* Check if BFD is enabled */
params = IF_DEF_PARAMS (ifp);
/* Check if BFD is enabled */
if (!params->bfd_info)
return;
oi_bfd_info = (struct bfd_info *)params->bfd_info;
if (!nbr->bfd_info)
nbr->bfd_info = bfd_info_create();
nbr_bfd_info = (struct bfd_info *)nbr->bfd_info;
nbr_bfd_info->detect_mult = oi_bfd_info->detect_mult;
nbr_bfd_info->desired_min_tx = oi_bfd_info->desired_min_tx;
nbr_bfd_info->required_min_rx = oi_bfd_info->required_min_rx;
}
/*
* ospf_bfd_write_config - Write the interface BFD configuration.
*/
@ -251,6 +311,32 @@ ospf_bfd_write_config(struct vty *vty, struct ospf_if_params *params)
vty_out (vty, " ip ospf bfd%s", VTY_NEWLINE);
}
/*
* ospf_bfd_show_info - Show BFD info structure
*/
void
ospf_bfd_show_info(struct vty *vty, void *bfd_info, json_object *json_obj,
u_char use_json, int param_only)
{
if (param_only)
bfd_show_param(vty, (struct bfd_info *)bfd_info, 1, 0, use_json, json_obj);
else
bfd_show_info(vty, (struct bfd_info *)bfd_info, 0, 1, use_json, json_obj);
}
/*
* ospf_bfd_interface_show - Show the interface BFD configuration.
*/
void
ospf_bfd_interface_show(struct vty *vty, struct interface *ifp,
json_object *json_interface_sub, u_char use_json)
{
struct ospf_if_params *params;
params = IF_DEF_PARAMS (ifp);
ospf_bfd_show_info(vty, params->bfd_info, json_interface_sub, use_json, 1);
}
/*
* ospf_bfd_if_param_set - Set the configured BFD paramter values for
@ -265,13 +351,12 @@ ospf_bfd_if_param_set (struct interface *ifp, u_int32_t min_rx,
params = IF_DEF_PARAMS (ifp);
bfd_set_param(&(params->bfd_info), min_rx, min_tx, detect_mult,
defaults, &command);
bfd_set_param((struct bfd_info **)&(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",
@ -342,7 +427,7 @@ void
ospf_bfd_init(void)
{
/* Initialize BFD client functions */
zclient->interface_bfd_dest_down = ospf_bfd_interface_dest_down;
zclient->interface_bfd_dest_update = ospf_bfd_interface_dest_update;
zclient->bfd_dest_replay = ospf_bfd_nbr_replay;
/* Install BFD command */

View File

@ -24,6 +24,8 @@
#ifndef _ZEBRA_OSPF_BFD_H
#define _ZEBRA_OSPF_BFD_H
#include "json.h"
extern void
ospf_bfd_init(void);
@ -33,4 +35,18 @@ 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);
extern void
ospf_bfd_interface_show(struct vty *vty, struct interface *ifp,
json_object *json_interface_sub, u_char use_json);
extern void
ospf_bfd_info_nbr_create (struct ospf_interface *oi, struct ospf_neighbor *nbr);
extern void
ospf_bfd_show_info(struct vty *vty, void *bfd_info, json_object *json_obj,
u_char use_json, int param_only);
extern void
ospf_bfd_info_free(void **bfd_info);
#endif /* _ZEBRA_OSPF_BFD_H */

View File

@ -30,6 +30,7 @@
#include "stream.h"
#include "table.h"
#include "log.h"
#include "json.h"
#include "ospfd/ospfd.h"
#include "ospfd/ospf_interface.h"
@ -42,6 +43,7 @@
#include "ospfd/ospf_network.h"
#include "ospfd/ospf_flood.h"
#include "ospfd/ospf_dump.h"
#include "ospfd/ospf_bfd.h"
/* Fill in the the 'key' as appropriate to retrieve the entry for nbr
* from the ospf_interface's nbrs table. Indexed by interface address
@ -98,6 +100,7 @@ ospf_nbr_new (struct ospf_interface *oi)
nbr->crypt_seqnum = 0;
ospf_bfd_info_nbr_create(oi, nbr);
return nbr;
}
@ -141,6 +144,7 @@ ospf_nbr_free (struct ospf_neighbor *nbr)
/* Cancel all events. *//* Thread lookup cost would be negligible. */
thread_cancel_event (master, nbr);
ospf_bfd_info_free(&nbr->bfd_info);
XFREE (MTYPE_OSPF_NEIGHBOR, nbr);
}

View File

@ -88,6 +88,9 @@ struct ospf_neighbor
struct timeval ts_last_regress; /* last regressive NSM change */
const char *last_regress_str; /* Event which last regressed NSM */
u_int32_t state_change; /* NSM state change counter */
/* BFD information */
void *bfd_info;
};
/* Macros. */

View File

@ -3857,6 +3857,7 @@ show_ip_ospf_interface_sub (struct vty *vty, struct ospf *ospf, struct interface
vty_out (vty, " Neighbor Count is %d, Adjacent neighbor count is %d%s",
ospf_nbr_count (oi, 0), ospf_nbr_count (oi, NSM_Full),
VTY_NEWLINE);
ospf_bfd_interface_show(vty, ifp, json_interface_sub, use_json);
}
}
@ -4622,6 +4623,8 @@ show_ip_ospf_neighbor_detail_sub (struct vty *vty, struct ospf_interface *oi,
else
json_object_object_add(json, inet_ntoa (nbr->router_id), json_sub);
}
ospf_bfd_show_info(vty, nbr->bfd_info, json, use_json, 0);
}
static int

View File

@ -33,6 +33,7 @@
#include "ptm_lib.h"
#include "buffer.h"
#include "zebra/zebra_ptm_redistribute.h"
#include "bfd.h"
#define ZEBRA_PTM_RECONNECT_TIME_INITIAL 1 /* initial reconnect is 1s */
#define ZEBRA_PTM_RECONNECT_TIME_MAX 300
@ -68,6 +69,7 @@ const char ZEBRA_PTM_BFD_CLIENT_FIELD[] = "client";
const char ZEBRA_PTM_BFD_SEQID_FIELD[] = "seqid";
const char ZEBRA_PTM_BFD_IFNAME_FIELD[] = "ifName";
const char ZEBRA_PTM_BFD_MAX_HOP_CNT_FIELD[] = "maxHopCnt";
const char ZEBRA_PTM_BFD_SEND_EVENT[] = "sendEvent";
extern struct zebra_t zebrad;
@ -341,7 +343,8 @@ zebra_ptm_install_commands (void)
/* BFD session goes down, send message to the protocols. */
static void
if_bfd_session_down (struct interface *ifp, struct prefix *dp, struct prefix *sp)
if_bfd_session_update (struct interface *ifp, struct prefix *dp,
struct prefix *sp, int status)
{
if (IS_ZEBRA_DEBUG_EVENT)
{
@ -349,22 +352,24 @@ if_bfd_session_down (struct interface *ifp, struct prefix *dp, struct prefix *sp
if (ifp)
{
zlog_debug ("MESSAGE: ZEBRA_INTERFACE_BFD_DEST_DOWN %s/%d on %s",
inet_ntop (dp->family, &dp->u.prefix, buf[0],
INET6_ADDRSTRLEN), dp->prefixlen, ifp->name);
zlog_debug ("MESSAGE: ZEBRA_INTERFACE_BFD_DEST_UPDATE %s/%d on %s"
" %s event",
inet_ntop (dp->family, &dp->u.prefix, buf[0],
INET6_ADDRSTRLEN), dp->prefixlen, ifp->name,
bfd_get_status_str(status));
}
else
{
zlog_debug ("MESSAGE: ZEBRA_INTERFACE_BFD_DEST_DOWN %s/%d "
"with src %s/%d",
zlog_debug ("MESSAGE: ZEBRA_INTERFACE_BFD_DEST_UPDATE %s/%d "
"with src %s/%d %s event",
inet_ntop (dp->family, &dp->u.prefix, buf[0], INET6_ADDRSTRLEN),
dp->prefixlen,
inet_ntop (sp->family, &sp->u.prefix, buf[1], INET6_ADDRSTRLEN),
sp->prefixlen);
sp->prefixlen, bfd_get_status_str(status));
}
}
zebra_interface_bfd_update (ifp, dp, sp);
zebra_interface_bfd_update (ifp, dp, sp, status);
}
static int
@ -403,44 +408,25 @@ zebra_ptm_handle_bfd_msg(void *arg, void *in_ctxt, struct interface *ifp)
__func__, ifp ? ifp->name : "N/A", bfdst_str,
dest_str, src_str);
/* we only care if bfd session goes down */
if (!strcmp (bfdst_str, ZEBRA_PTM_BFDSTATUS_DOWN_STR)) {
if (inet_pton(AF_INET, dest_str, &dest_prefix.u.prefix4) > 0) {
dest_prefix.family = AF_INET;
dest_prefix.prefixlen = IPV4_MAX_PREFIXLEN;
}
#ifdef HAVE_IPV6
else if (inet_pton(AF_INET6, dest_str, &dest_prefix.u.prefix6) > 0) {
dest_prefix.family = AF_INET6;
dest_prefix.prefixlen = IPV6_MAX_PREFIXLEN;
}
#endif /* HAVE_IPV6 */
else {
zlog_err("%s: Peer addr %s not found", __func__,
dest_str);
if (str2prefix(dest_str, &dest_prefix) == 0) {
zlog_err("%s: Peer addr %s not found", __func__,
dest_str);
return -1;
}
memset(&src_prefix, 0, sizeof(struct prefix));
if (strcmp(ZEBRA_PTM_INVALID_SRC_IP, src_str)) {
if (str2prefix(src_str, &src_prefix) == 0) {
zlog_err("%s: Local addr %s not found", __func__,
src_str);
return -1;
}
}
memset(&src_prefix, 0, sizeof(struct prefix));
if (strcmp(ZEBRA_PTM_INVALID_SRC_IP, src_str)) {
if (inet_pton(AF_INET, src_str, &src_prefix.u.prefix4) > 0) {
src_prefix.family = AF_INET;
src_prefix.prefixlen = IPV4_MAX_PREFIXLEN;
}
#ifdef HAVE_IPV6
else if (inet_pton(AF_INET6, src_str, &src_prefix.u.prefix6) > 0) {
src_prefix.family = AF_INET6;
src_prefix.prefixlen = IPV6_MAX_PREFIXLEN;
}
#endif /* HAVE_IPV6 */
else {
zlog_err("%s: Local addr %s not found", __func__,
src_str);
return -1;
}
}
if_bfd_session_down(ifp, &dest_prefix, &src_prefix);
if (!strcmp (bfdst_str, ZEBRA_PTM_BFDSTATUS_DOWN_STR)) {
if_bfd_session_update(ifp, &dest_prefix, &src_prefix, BFD_STATUS_DOWN);
} else {
if_bfd_session_update(ifp, &dest_prefix, &src_prefix, BFD_STATUS_UP);
}
return 0;
@ -718,6 +704,10 @@ zebra_ptm_bfd_dst_register (struct zserv *client, int sock, u_short length,
if_name);
}
sprintf(tmp_buf, "%d", 1);
ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEND_EVENT,
tmp_buf);
ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &data_len);
if (IS_ZEBRA_DEBUG_SEND)

View File

@ -24,7 +24,7 @@
#include "zebra_ptm_redistribute.h"
void zebra_interface_bfd_update (struct interface *a, struct prefix *dp,
struct prefix *sp)
struct prefix *sp, int status)
{ return; }
void zebra_bfd_peer_replay_req (void)

View File

@ -32,7 +32,7 @@ extern struct zebra_t zebrad;
static int
zsend_interface_bfd_update (int cmd, struct zserv *client,
struct interface *ifp, struct prefix *dp,
struct prefix *sp)
struct prefix *sp, int status)
{
int blen;
struct stream *s;
@ -56,6 +56,9 @@ zsend_interface_bfd_update (int cmd, struct zserv *client,
stream_put (s, &dp->u.prefix, blen);
stream_putc (s, dp->prefixlen);
/* BFD status */
stream_putl(s, status);
/* BFD source prefix information. */
stream_putc (s, sp->family);
blen = prefix_blen (sp);
@ -71,7 +74,7 @@ zsend_interface_bfd_update (int cmd, struct zserv *client,
void
zebra_interface_bfd_update (struct interface *ifp, struct prefix *dp,
struct prefix *sp)
struct prefix *sp, int status)
{
struct listnode *node, *nnode;
struct zserv *client;
@ -84,8 +87,8 @@ zebra_interface_bfd_update (struct interface *ifp, struct prefix *dp,
continue;
/* Notify to the protocol daemons. */
zsend_interface_bfd_update (ZEBRA_INTERFACE_BFD_DEST_DOWN, client, ifp,
dp, sp);
zsend_interface_bfd_update (ZEBRA_INTERFACE_BFD_DEST_UPDATE, client, ifp,
dp, sp, status);
}
}

View File

@ -23,6 +23,6 @@
#ifndef _ZEBRA_PTM_REDISTRIBUTE_H
#define _ZEBRA_PTM_REDISTRIBUTE_H
extern void zebra_interface_bfd_update (struct interface *, struct prefix *,
struct prefix *);
struct prefix *, int);
extern void zebra_bfd_peer_replay_req (void);
#endif /* _ZEBRA_PTM_REDISTRIBUTE_H */