diff options
-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); |