diff options
author | Donald Sharp <sharpd@cumulusnetworks.com> | 2015-05-20 02:47:23 +0200 |
---|---|---|
committer | Donald Sharp <sharpd@cumulusnetworks.com> | 2015-05-20 02:47:23 +0200 |
commit | d5a5c8f05bc4637dcb113f8285f7db6cfb924b6c (patch) | |
tree | bd1312d37bb30dfac8d41ee56ae88bce27889996 | |
parent | zebra: zebra-client-info-detail.patch (diff) | |
download | frr-d5a5c8f05bc4637dcb113f8285f7db6cfb924b6c.tar.xz frr-d5a5c8f05bc4637dcb113f8285f7db6cfb924b6c.zip |
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>
-rw-r--r-- | bgpd/bgp_vty.c | 26 | ||||
-rw-r--r-- | bgpd/bgp_zebra.c | 42 | ||||
-rw-r--r-- | bgpd/bgpd.c | 7 | ||||
-rw-r--r-- | bgpd/bgpd.h | 1 | ||||
-rw-r--r-- | lib/zclient.c | 33 | ||||
-rw-r--r-- | lib/zclient.h | 2 | ||||
-rw-r--r-- | lib/zebra.h | 3 | ||||
-rw-r--r-- | ospfd/ospf_interface.h | 1 | ||||
-rw-r--r-- | ospfd/ospf_vty.c | 40 | ||||
-rw-r--r-- | ospfd/ospf_zebra.c | 50 | ||||
-rw-r--r-- | zebra/interface.c | 17 | ||||
-rw-r--r-- | zebra/interface.h | 1 | ||||
-rw-r--r-- | zebra/redistribute.c | 17 | ||||
-rw-r--r-- | zebra/redistribute.h | 2 | ||||
-rw-r--r-- | zebra/redistribute_null.c | 2 | ||||
-rw-r--r-- | zebra/zebra_ptm.c | 2 | ||||
-rw-r--r-- | zebra/zserv.c | 30 | ||||
-rw-r--r-- | zebra/zserv.h | 4 |
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); |