]> git.puffer.fish Git - matthieu/frr.git/commitdiff
This patch adds support for a new BFD session down message from zebra to
authorDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 20 May 2015 00:47:23 +0000 (17:47 -0700)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Wed, 20 May 2015 00:47:23 +0000 (17:47 -0700)
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>
18 files changed:
bgpd/bgp_vty.c
bgpd/bgp_zebra.c
bgpd/bgpd.c
bgpd/bgpd.h
lib/zclient.c
lib/zclient.h
lib/zebra.h
ospfd/ospf_interface.h
ospfd/ospf_vty.c
ospfd/ospf_zebra.c
zebra/interface.c
zebra/interface.h
zebra/redistribute.c
zebra/redistribute.h
zebra/redistribute_null.c
zebra/zebra_ptm.c
zebra/zserv.c
zebra/zserv.h

index f32a215215bc0193f549e197c3f336b94eee6936..ecb638f6a31a3f16bb97ad6349f78525b95dfc75 100644 (file)
@@ -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);
index 369bcddf0a6540d04d8844db5048a89a6456df6c..bd63c6790c12fd8d0844d3d238da04e21329d6f7 100644 (file)
@@ -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;
index 550ef526f831942728f359d07679978b2b778c04..ec7bd3497355c61cf02e24f15a41801a1960fbd7 100644 (file)
@@ -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)
index 4faf452b2bd6b0c879cce40837451c56e6dc1ff9..beecef5256e52df1c23f10e71c3b5ea5142f6b44 100644 (file)
@@ -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];
index 72367206b763c3d896a418eb5a698ce37b794dc3..ac418addf302b16fae719e6779f78d128a66084c 100644 (file)
@@ -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);
index 9b627b65f96076f34d3c26494a592daafe175d44..9b359893eccac894e07026ff9016f9248eb16dc9 100644 (file)
@@ -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);
index 7d68530baa4885b03875f6f81f88e340b22a69f1..794a457ea8e70ce9189b26da713d8ee47bf3e17f 100644 (file)
@@ -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
index ed698c87e0f2882b05358fb24342620ca22017d5..75a8d060ffc4db8e16551a3808932d65f056b53d 100644 (file)
@@ -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 */
index 839a2b699703952b33e7e7237315b2002bdb0309..7766e04003e845788581a451cdf0cbcd894879ab 100644 (file)
@@ -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
index 94edc28632c7f18af0997d89a4a096ac70a67f02..378527824188570f09b943b2fb27c605d64303b9 100644 (file)
@@ -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;
 
index 10344c62818cc6ae90ce240188c09d2f5935b23a..da5e41e8dcebdfe042fe563d23a4f3cd232b410e 100644 (file)
@@ -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)
index 7a05348ca552624a0d81a90ef29c3e1aa4a1dde1..d20d991515c4017e9ec7554bd8a115574ccd2116 100644 (file)
@@ -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 *);
index 19176db7fa6f573f3fd96527b4d97c30cebd7b2d..5c9412c13bbe7bcfe3b8c1c0d35a623aad6e7762 100644 (file)
@@ -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);
+    }
+}
index 9ed99bc5945122ca7f592cc60e324efe270b264f..8ed39fce28d416740cadcca2d42a0aa50bf387c0 100644 (file)
@@ -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 */
index 54198c8e6fb924903b9a37dbaba4594c2f7ae0c7..2c31a85b3b530d49ecb5a7ea18a7d2a205ad5b42 100644 (file)
@@ -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; }
index 6201b60f4eddbbf6b9fdda71f2c7fa44b0688516..368da4e72b62040ade52b61f33db5a9e35100083 100644 (file)
@@ -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);
             }
index 059fede6e34a762b9f61284614a0893b765d06e4..56e5b19f12a20c6c0a77f29b1821b2d63063fa10 100644 (file)
@@ -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
index 589d2e56d220af297c4dd8a3f8b354b8bc881bb1..4e42b85864931a256b895a983677d0e5b45144cb 100644 (file)
@@ -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);