From: Donald Sharp Date: Wed, 20 May 2015 00:47:23 +0000 (-0700) Subject: This patch adds support for a new BFD session down message from zebra to X-Git-Tag: frr-2.0-rc1~1509 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=d5a5c8f05bc4637dcb113f8285f7db6cfb924b6c;p=mirror%2Ffrr.git 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 Reviewed-by: Shrijeet Mukherjee --- diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index f32a215215..ecb638f6a3 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 369bcddf0a..bd63c6790c 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -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; diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 550ef526f8..ec7bd34973 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 4faf452b2b..beecef5256 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 72367206b7..ac418addf3 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 9b627b65f9..9b359893ec 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 7d68530baa..794a457ea8 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 ed698c87e0..75a8d060ff 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 839a2b6997..7766e04003 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 94edc28632..3785278241 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 10344c6281..da5e41e8dc 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 7a05348ca5..d20d991515 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 19176db7fa..5c9412c13b 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 9ed99bc594..8ed39fce28 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 54198c8e6f..2c31a85b3b 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 6201b60f4e..368da4e72b 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 059fede6e3..56e5b19f12 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 589d2e56d2..4e42b85864 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);