summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_vty.c26
-rw-r--r--bgpd/bgp_zebra.c42
-rw-r--r--bgpd/bgpd.c7
-rw-r--r--bgpd/bgpd.h1
-rw-r--r--lib/zclient.c33
-rw-r--r--lib/zclient.h2
-rw-r--r--lib/zebra.h3
-rw-r--r--ospfd/ospf_interface.h1
-rw-r--r--ospfd/ospf_vty.c40
-rw-r--r--ospfd/ospf_zebra.c50
-rw-r--r--zebra/interface.c17
-rw-r--r--zebra/interface.h1
-rw-r--r--zebra/redistribute.c17
-rw-r--r--zebra/redistribute.h2
-rw-r--r--zebra/redistribute_null.c2
-rw-r--r--zebra/zebra_ptm.c2
-rw-r--r--zebra/zserv.c30
-rw-r--r--zebra/zserv.h4
18 files changed, 276 insertions, 4 deletions
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index f32a21521..ecb638f6a 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -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);
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 369bcddf0..bd63c6790 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -269,6 +269,47 @@ bgp_interface_down (int command, struct zclient *zclient, zebra_size_t length)
}
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;
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 550ef526f..ec7bd3497 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -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)
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 4faf452b2..beecef525 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -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];
diff --git a/lib/zclient.c b/lib/zclient.c
index 72367206b..ac418addf 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -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);
diff --git a/lib/zclient.h b/lib/zclient.h
index 9b627b65f..9b359893e 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -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);
diff --git a/lib/zebra.h b/lib/zebra.h
index 7d68530ba..794a457ea 100644
--- a/lib/zebra.h
+++ b/lib/zebra.h
@@ -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
diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h
index ed698c87e..75a8d060f 100644
--- a/ospfd/ospf_interface.h
+++ b/ospfd/ospf_interface.h
@@ -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 */
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 839a2b699..7766e0400 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -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
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index 94edc2863..378527824 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -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;
diff --git a/zebra/interface.c b/zebra/interface.c
index 10344c628..da5e41e8d 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -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)
diff --git a/zebra/interface.h b/zebra/interface.h
index 7a05348ca..d20d99151 100644
--- a/zebra/interface.h
+++ b/zebra/interface.h
@@ -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 *);
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index 19176db7f..5c9412c13 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -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);
+ }
+}
diff --git a/zebra/redistribute.h b/zebra/redistribute.h
index 9ed99bc59..8ed39fce2 100644
--- a/zebra/redistribute.h
+++ b/zebra/redistribute.h
@@ -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 */
diff --git a/zebra/redistribute_null.c b/zebra/redistribute_null.c
index 54198c8e6..2c31a85b3 100644
--- a/zebra/redistribute_null.c
+++ b/zebra/redistribute_null.c
@@ -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; }
diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c
index 6201b60f4..368da4e72 100644
--- a/zebra/zebra_ptm.c
+++ b/zebra/zebra_ptm.c
@@ -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);
}
diff --git a/zebra/zserv.c b/zebra/zserv.c
index 059fede6e..56e5b19f1 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -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
diff --git a/zebra/zserv.h b/zebra/zserv.h
index 589d2e56d..4e42b8586 100644
--- a/zebra/zserv.h
+++ b/zebra/zserv.h
@@ -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);