This patch adds support for a new BFD session down message from zebra to

protocols. BGP and OSPF are integrated to respond this BFD session down message
originated in Zebra via ptmd.

BGP and OSPF now have a bfd command, which tells OSPF/BGP to respond to the
BFD session down message.

OSPF:

interface <>
 ip ospf bfd

BGP:

router bgp <>
  neighbor <> bfd

Please note that these commands don't enable BFD as a protocol. BFD configuration
and paramter tuning are via BFD applicable UI.

Signed-off-by: Vipin Kumar <vipin@cumulusnetworks.com>
Reviewed-by: Shrijeet Mukherjee <shm@cumulusnetworks.com>
This commit is contained in:
Donald Sharp 2015-05-19 17:47:23 -07:00
parent 04b02fda9f
commit d5a5c8f05b
18 changed files with 276 additions and 4 deletions

View File

@ -2436,6 +2436,28 @@ DEFUN (no_neighbor_shutdown,
return peer_flag_unset_vty (vty, argv[0], PEER_FLAG_SHUTDOWN);
}
/* neighbor bfd. */
DEFUN (neighbor_bfd,
neighbor_bfd_cmd,
NEIGHBOR_CMD2 "bfd",
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"Respond to BFD session event\n")
{
return peer_flag_set_vty (vty, argv[0], PEER_FLAG_BFD);
}
DEFUN (no_neighbor_bfd,
no_neighbor_bfd_cmd,
NO_NEIGHBOR_CMD2 "bfd",
NO_STR
NEIGHBOR_STR
NEIGHBOR_ADDR_STR2
"Respond to BFD session event\n")
{
return peer_flag_unset_vty (vty, argv[0], PEER_FLAG_BFD);
}
/* Deprecated neighbor capability route-refresh. */
DEFUN_DEPRECATED (neighbor_capability_route_refresh,
neighbor_capability_route_refresh_cmd,
@ -10273,6 +10295,10 @@ bgp_vty_init (void)
install_element (BGP_NODE, &neighbor_passive_cmd);
install_element (BGP_NODE, &no_neighbor_passive_cmd);
/* "neighbor bfd" commands. */
install_element (BGP_NODE, &neighbor_bfd_cmd);
install_element (BGP_NODE, &no_neighbor_bfd_cmd);
/* "neighbor shutdown" commands. */
install_element (BGP_NODE, &neighbor_shutdown_cmd);
install_element (BGP_NODE, &no_neighbor_shutdown_cmd);

View File

@ -268,6 +268,47 @@ bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length)
return 0;
}
static int
bgp_interface_bfd_dest_down (int command, struct zclient *zclient,
zebra_size_t length)
{
struct interface *ifp;
struct prefix p;
ifp = zebra_interface_bfd_read (zclient->ibuf, &p);
if (ifp == NULL)
return 0;
if (BGP_DEBUG(zebra, ZEBRA))
{
char buf[128];
prefix2str(&p, buf, sizeof(buf));
zlog_debug("Zebra: interface %s bfd destination %s down", ifp->name, buf);
}
/* Bring the peer down if BFD is enabled in BGP */
{
struct listnode *mnode, *node, *nnode;
struct bgp *bgp;
struct peer *peer;
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;
if (ifp == peer->nexthop.ifp)
BGP_EVENT_ADD (peer, BGP_Stop);
}
}
}
return 0;
}
static int
bgp_interface_address_add (int command, struct zclient *zclient,
zebra_size_t length)
@ -1502,6 +1543,7 @@ bgp_zebra_init (void)
zclient->ipv4_route_delete = zebra_read_ipv4;
zclient->interface_up = bgp_interface_up;
zclient->interface_down = bgp_interface_down;
zclient->interface_bfd_dest_down = bgp_interface_bfd_dest_down;
#ifdef HAVE_IPV6
zclient->ipv6_route_add = zebra_read_ipv6;
zclient->ipv6_route_delete = zebra_read_ipv6;

View File

@ -2616,6 +2616,7 @@ static const struct peer_flag_action peer_flag_action_list[] =
{ PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
{ PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
{ PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
{ PEER_FLAG_BFD, 0, peer_change_none },
{ 0, 0, 0 }
};
@ -5253,6 +5254,12 @@ bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
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))
vty_out (vty, " neighbor %s bfd%s", addr, VTY_NEWLINE);
/* Password. */
if (peer->password)
if (!peer_group_active (peer)

View File

@ -457,6 +457,7 @@ 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 */
/* NSF mode (graceful restart) */
u_char nsf[AFI_MAX][SAFI_MAX];

View File

@ -761,6 +761,35 @@ memconstant(const void *s, int c, size_t n)
return 1;
}
struct interface*
zebra_interface_bfd_read (struct stream *s, struct prefix *p)
{
unsigned int ifindex;
struct interface *ifp;
int plen;
/* Get interface index. */
ifindex = stream_getl (s);
/* Lookup index. */
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 interface address. */
p->family = stream_getc (s);
plen = prefix_blen (p);
stream_get (&p->u.prefix, s, plen);
p->prefixlen = stream_getc (s);
return ifp;
}
struct connected *
zebra_interface_address_read (int type, struct stream *s)
{
@ -1026,6 +1055,10 @@ 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);
break;
case ZEBRA_INTERFACE_NBR_ADDRESS_ADD:
if (zclient->interface_nbr_address_add)
(*zclient->interface_nbr_address_add) (command, zclient, length);

View File

@ -78,6 +78,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_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);
@ -160,6 +161,7 @@ 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 *);
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);

View File

@ -429,7 +429,8 @@ struct in_pktinfo
#define ZEBRA_NEXTHOP_UPDATE 26
#define ZEBRA_INTERFACE_NBR_ADDRESS_ADD 27
#define ZEBRA_INTERFACE_NBR_ADDRESS_DELETE 28
#define ZEBRA_MESSAGE_MAX 29
#define ZEBRA_INTERFACE_BFD_DEST_DOWN 29
#define ZEBRA_MESSAGE_MAX 30
/* Marker value used in new Zserv, in the byte location corresponding
* the command value in the old zserv header. To allow old and new

View File

@ -45,6 +45,7 @@ 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 */
DECLARE_IF_PARAM (u_char, type); /* type of interface */

View File

@ -5607,6 +5607,40 @@ 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,
"ip ospf retransmit-interval <3-65535> A.B.C.D",
@ -6910,6 +6944,10 @@ config_write_interface (struct vty *vty)
vty_out (vty, "%s", VTY_NEWLINE);
}
/* bfd print. */
if (OSPF_IF_PARAM_CONFIGURED (params, bfd))
vty_out (vty, " ip ospf bfd%s", VTY_NEWLINE);
/* MTU ignore print. */
if (OSPF_IF_PARAM_CONFIGURED (params, mtu_ignore) &&
params->mtu_ignore != OSPF_MTU_IGNORE_DEFAULT)
@ -7579,6 +7617,8 @@ 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

View File

@ -44,6 +44,9 @@
#include "ospfd/ospf_lsa.h"
#include "ospfd/ospf_dump.h"
#include "ospfd/ospf_route.h"
#include "ospfd/ospf_lsdb.h"
#include "ospfd/ospf_neighbor.h"
#include "ospfd/ospf_nsm.h"
#include "ospfd/ospf_zebra.h"
#ifdef HAVE_SNMP
#include "ospfd/ospf_snmp.h"
@ -324,6 +327,52 @@ 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);
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)
{
@ -1324,6 +1373,7 @@ ospf_zebra_init ()
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;

View File

@ -604,6 +604,23 @@ if_refresh (struct interface *ifp)
if_get_flags (ifp);
}
/* BFD session goes down, send message to the protocols. */
void
if_bfd_session_down (struct interface *ifp, struct prefix *p)
{
if (IS_ZEBRA_DEBUG_EVENT)
{
char buf[INET6_ADDRSTRLEN];
zlog_debug ("MESSAGE: ZEBRA_INTERFACE_BFD_DEST_DOWN %s/%d on %s",
inet_ntop (p->family, &p->u.prefix, buf, INET6_ADDRSTRLEN),
p->prefixlen, ifp->name);
}
zebra_interface_bfd_update (ifp, p);
}
/* Output prefix string to vty. */
static int
prefix_vty_out (struct vty *vty, struct prefix *p)

View File

@ -218,6 +218,7 @@ extern void if_add_update (struct interface *ifp);
extern void if_up (struct interface *);
extern void if_down (struct interface *);
extern void if_refresh (struct interface *);
extern void if_bfd_session_down(struct interface *, struct prefix *);
extern void if_flags_update (struct interface *, uint64_t);
extern int if_subnet_add (struct interface *, struct connected *);
extern int if_subnet_delete (struct interface *, struct connected *);

View File

@ -432,3 +432,20 @@ zebra_interface_address_delete_update (struct interface *ifp,
zsend_interface_address (ZEBRA_INTERFACE_ADDRESS_DELETE, client, ifp, ifc);
}
}
void
zebra_interface_bfd_update (struct interface *ifp, struct prefix *p)
{
struct listnode *node, *nnode;
struct zserv *client;
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)
continue;
/* Notify to the protocol daemons. */
zsend_interface_bfd_update (ZEBRA_INTERFACE_BFD_DEST_DOWN, client, ifp, p);
}
}

View File

@ -45,7 +45,7 @@ extern void zebra_interface_address_add_update (struct interface *,
struct connected *);
extern void zebra_interface_address_delete_update (struct interface *,
struct connected *c);
extern void zebra_interface_bfd_update (struct interface *, struct prefix *);
extern int zebra_check_addr (struct prefix *);
#endif /* _ZEBRA_REDISTRIBUTE_H */

View File

@ -53,3 +53,5 @@ void zebra_interface_address_delete_update (struct interface *a,
struct connected *b)
{ return; }
#endif
void zebra_interface_bfd_update (struct interface *a, struct prefix *b)
{ return; }

View File

@ -262,7 +262,7 @@ zebra_ptm_process_msg (char *buf)
dest_prefix.u.prefix4 = dest_addr;
dest_prefix.prefixlen = IPV4_MAX_PREFIXLEN;
/* Send BFD message with ifp and dest_prefix to protocols */
if_bfd_session_down(ifp, &dest_prefix);
} else {
if_down (ifp);
}

View File

@ -481,6 +481,36 @@ zsend_interface_update (int cmd, struct zserv *client, struct interface *ifp)
return zebra_server_send_message(client);
}
int
zsend_interface_bfd_update (int cmd, struct zserv *client,
struct interface *ifp, struct prefix *p)
{
int blen;
struct stream *s;
/* Check this client need interface information. */
if (! client->ifinfo)
return 0;
s = client->obuf;
stream_reset (s);
zserv_create_header (s, cmd);
stream_putl (s, ifp->ifindex);
/* BFD destination prefix information. */
stream_putc (s, p->family);
blen = prefix_blen (p);
stream_put (s, &p->u.prefix, blen);
stream_putc (s, p->prefixlen);
/* Write packet size. */
stream_putw_at (s, 0, stream_get_endp (s));
client->if_bfd_cnt++;
return zebra_server_send_message(client);
}
/*
* The zebra server sends the clients a ZEBRA_IPV4_ROUTE_ADD or a
* ZEBRA_IPV6_ROUTE_ADD via zsend_route_multipath in the following

View File

@ -90,6 +90,7 @@ struct zserv
u_int32_t ifdown_cnt;
u_int32_t ifadd_cnt;
u_int32_t ifdel_cnt;
u_int32_t if_bfd_cnt;
time_t connect_time;
time_t last_read_time;
@ -144,7 +145,8 @@ extern int zsend_interface_update (int, struct zserv *, struct interface *);
extern int zsend_route_multipath (int, struct zserv *, struct prefix *,
struct rib *);
extern int zsend_router_id_update(struct zserv *, struct prefix *);
extern int zsend_interface_bfd_update(int, struct zserv *, struct interface *,
struct prefix *);
extern pid_t pid;
extern void zserv_create_header(struct stream *s, uint16_t cmd);