mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-06 18:04:03 +00:00
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:
parent
04b02fda9f
commit
d5a5c8f05b
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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];
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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 *);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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; }
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user