]> git.puffer.fish Git - matthieu/frr.git/commitdiff
Addition on hidden command "bfd multihop/singlehop" and "ptm-enable" per interface...
authorradhika <radhika@cumulusnetworks.com>
Thu, 21 Apr 2016 22:39:38 +0000 (15:39 -0700)
committerradhika <radhika@cumulusnetworks.com>
Thu, 21 Apr 2016 22:39:38 +0000 (15:39 -0700)
CM-10435
Issue: IBGP BFD sessions are created as multi-hop even though peer is single-hop away. This is causing an interop issue with ICOS.
Root Cause: By design all IBGP peers are registered with BFD as multi-hop.
Fix:
• Changed the default behavior of always treating IBGP BFD sessions as mult-hop. shared_network variable is used to determine whether the IBGP peer is single hop or multi-hop away. The logic for determining whether EBGP peer is single hop or multi-hop has not been changed.
• Since the default behavior has been changed, it will cause interop issues between 2.5 and 3.0 IBGP BFD sessions. A new hidden command “bfd multihop/singlehop” has been introduced to overcome the interop issues.

dell-s6000-10(config-router)# neighbor 30.0.2.6 bfd
<2-255> Detect Multiplier
<cr>
dell-s6000-10(config-router)# neighbor 30.0.2.6 bfd multihop
dell-s6000-10(config-router)# no neighbor 30.0.2.6 bfd multihop
dell-s6000-10(config-router)#
dell-s6000-10(config-router)# neighbor 30.0.2.6 bfd multihop
dell-s6000-10(config-router)# do show running-config
!
router bgp 100
neighbor igroup peer-group
neighbor igroup bfd 5 500 500
neighbor igroup bfd multihop
neighbor 30.0.2.2 remote-as 100
neighbor 30.0.2.2 peer-group igroup
neighbor 3101:abc:bcad::2 remote-as 100
neighbor 3101:abc:bcad::2 peer-group igroup
neighbor 30.0.2.6 remote-as 200
neighbor 30.0.2.6 bfd multihop
neighbor 3102:abc:bcad::6 remote-as 200
neighbor 3102:abc:bcad::6 bfd
neighbor 3102:abc:bcad::6 ebgp-multihop 255
!

CM-10260
Issue: “Unable to connect to socket” message keeps getting logged when ptmd process doesn’t exist.
Root Cause: BFD clients (bgpd, ospfd and ospf6d) during initialization try to register with BFD/PTM by default. This results in continuous logging If PTM does not exist since there is no max on number of retries.
Fix:
• Stop the retries to connect to PTM after max reconnect timer of 5 mins is reached.
• Added zebra debug event wrapper to message logging to prevent it from showing by default.

CM-4541
Issue: Addition of a new command "ptm-enable" or "no ptm-enable" per interface to enable/disable PTM link status checks for an interface.
Fix: Currently there is only one ptm-enable global command that enables/disables PTM status updates for all interfaces. This new command will give the handle to individually stop interface from reacting on the PTM status updates.
• by default interface uses the ptm-enable global configuration
• "no ptm-enable" on an interface will disable PTM status updates from taking affect for that interface. This can bring the interface up if it was brought down due to PTM status update.
• "ptm-enable" on an interface will cause the interface to fallback to the global ptm-enable configuration value and will bring the interface up or down based on the last stored PTM status update if global ptm is enabled.

Ticket: CM-10435, CM-10260 and CM-4541
Signed-off-by: Radhika Mahankali
Reviewed-by: Donald Sharp, Kanna Rajagopal
bgpd/bgp_bfd.c
lib/bfd.c
lib/bfd.h
zebra/interface.c
zebra/interface.h
zebra/zebra_ptm.c
zebra/zebra_ptm.h

index 118d8f64c243637cbf85da3a5081e093e5cf4ee8..da50fd2bae85e4970201fef290d61aaef248d8a5 100644 (file)
@@ -65,6 +65,7 @@ bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer)
   bfd_info->required_min_rx = conf_bfd_info->required_min_rx;
   bfd_info->desired_min_tx = conf_bfd_info->desired_min_tx;
   bfd_info->detect_mult = conf_bfd_info->detect_mult;
+  bfd_info->type = conf_bfd_info->type;
 }
 
 /*
@@ -73,8 +74,16 @@ bgp_bfd_peer_group2peer_copy(struct peer *conf, struct peer *peer)
 static int
 bgp_bfd_is_peer_multihop(struct peer *peer)
 {
-  if((peer->conf_if == NULL) && ((peer->sort == BGP_PEER_IBGP) ||
-                          is_ebgp_multihop_configured(peer)))
+  struct bfd_info *bfd_info;
+
+  bfd_info = (struct bfd_info *)peer->bfd_info;
+
+  if (!bfd_info)
+    return 0;
+
+  if((bfd_info->type == BFD_TYPE_MULTIHOP) ||
+      ((peer->sort == BGP_PEER_IBGP) && !peer->shared_network) ||
+      is_ebgp_multihop_configured(peer))
     return 1;
   else
     return 0;
@@ -89,24 +98,37 @@ bgp_bfd_peer_sendmsg (struct peer *peer, int command)
 {
   struct bfd_info *bfd_info;
   vrf_id_t vrf_id = VRF_DEFAULT;
+  int multihop;
 
   bfd_info = (struct bfd_info *)peer->bfd_info;
 
   if (peer->bgp && (peer->bgp->inst_type == BGP_INSTANCE_TYPE_VRF))
     vrf_id = peer->bgp->vrf_id;
 
+  if (command == ZEBRA_BFD_DEST_DEREGISTER)
+    {
+      multihop = CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP);
+      UNSET_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP);
+    }
+  else
+    {
+      multihop = bgp_bfd_is_peer_multihop(peer);
+      if ((command == ZEBRA_BFD_DEST_REGISTER) && multihop)
+        SET_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP);
+    }
+
   if (peer->su.sa.sa_family == AF_INET)
     bfd_peer_sendmsg (zclient, bfd_info, AF_INET,
                       &peer->su.sin.sin_addr,
                       (peer->su_local) ? &peer->su_local->sin.sin_addr : NULL,
                       (peer->nexthop.ifp) ? peer->nexthop.ifp->name : NULL,
-                      peer->ttl, bgp_bfd_is_peer_multihop(peer), command, 1, vrf_id);
+                      peer->ttl, multihop, command, 1, vrf_id);
   else if (peer->su.sa.sa_family == AF_INET6)
     bfd_peer_sendmsg (zclient, bfd_info, AF_INET6,
                       &peer->su.sin6.sin6_addr,
                       (peer->su_local) ? &peer->su_local->sin6.sin6_addr : NULL,
                       (peer->nexthop.ifp) ? peer->nexthop.ifp->name : NULL,
-                      peer->ttl, bgp_bfd_is_peer_multihop(peer), command, 1, vrf_id);
+                      peer->ttl, multihop, command, 1, vrf_id);
 }
 
 /*
@@ -170,6 +192,46 @@ bgp_bfd_update_peer (struct peer *peer)
   bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_UPDATE);
 }
 
+/*
+ * bgp_bfd_update_type - update session type with BFD through zebra.
+ */
+static void
+bgp_bfd_update_type (struct peer *peer)
+{
+  struct bfd_info *bfd_info;
+  int multihop;
+
+  if (!peer->bfd_info)
+    return;
+  bfd_info = (struct bfd_info *)peer->bfd_info;
+
+  /* Check if the peer has been registered with BFD*/
+  if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_REG))
+    return;
+
+  if (bfd_info->type == BFD_TYPE_NOT_CONFIGURED)
+    {
+      multihop = bgp_bfd_is_peer_multihop(peer);
+      if ((multihop && !CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP)) ||
+            (!multihop && CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP)))
+        {
+          bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_DEREGISTER);
+          bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_REGISTER);
+        }
+    }
+  else
+    {
+      if ((bfd_info->type == BFD_TYPE_MULTIHOP &&
+            !CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP)) ||
+          (bfd_info->type == BFD_TYPE_SINGLEHOP &&
+            CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP)))
+        {
+          bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_DEREGISTER);
+          bgp_bfd_peer_sendmsg(peer, ZEBRA_BFD_DEST_REGISTER);
+        }
+    }
+}
+
 /*
  * bgp_bfd_dest_replay - Replay all the peers that have BFD enabled
  *                       to zebra
@@ -367,7 +429,7 @@ bgp_bfd_peer_param_set (struct peer *peer, u_int32_t min_rx, u_int32_t min_tx,
 }
 
 /*
- * bgp_bfd_peer_param_unset - Unset the configured BFD paramter values for peer.
+ * bgp_bfd_peer_param_unset - Delete the configured BFD paramter values for peer.
  */
 static int
 bgp_bfd_peer_param_unset (struct peer *peer)
@@ -396,6 +458,61 @@ bgp_bfd_peer_param_unset (struct peer *peer)
   return 0;
 }
 
+/*
+ * bgp_bfd_peer_param_type_set - set the BFD session type (multihop or singlehop)
+ */
+static int
+bgp_bfd_peer_param_type_set (struct peer *peer, enum bfd_sess_type type)
+{
+  struct peer_group *group;
+  struct listnode *node, *nnode;
+  int command = 0;
+  struct bfd_info *bfd_info;
+
+  if (!peer->bfd_info)
+    bfd_set_param((struct bfd_info **)&(peer->bfd_info), BFD_DEF_MIN_RX,
+                    BFD_DEF_MIN_TX, BFD_DEF_DETECT_MULT, 1, &command);
+
+  bfd_info = (struct bfd_info *)peer->bfd_info;
+  bfd_info->type = type;
+
+  if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
+    {
+      group = peer->group;
+      for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
+        {
+          command = 0;
+          if (!peer->bfd_info)
+            bfd_set_param((struct bfd_info **)&(peer->bfd_info),
+                           BFD_DEF_MIN_RX, BFD_DEF_MIN_TX,
+                           BFD_DEF_DETECT_MULT, 1, &command);
+
+          bfd_info = (struct bfd_info *)peer->bfd_info;
+          bfd_info->type = type;
+
+          if (peer->status == Established)
+            {
+              if (command == ZEBRA_BFD_DEST_REGISTER)
+                bgp_bfd_register_peer(peer);
+              else
+                bgp_bfd_update_type(peer);
+            }
+        }
+    }
+  else
+    {
+      if (peer->status == Established)
+        {
+          if (command == ZEBRA_BFD_DEST_REGISTER)
+            bgp_bfd_register_peer(peer);
+          else
+            bgp_bfd_update_type(peer);
+        }
+    }
+
+  return 0;
+}
+
 /*
  * bgp_bfd_peer_config_write - Write the peer BFD configuration.
  */
@@ -413,7 +530,14 @@ bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr)
     vty_out (vty, " neighbor %s bfd %d %d %d%s", addr,
       bfd_info->detect_mult, bfd_info->required_min_rx,
       bfd_info->desired_min_tx, VTY_NEWLINE);
-  else
+
+  if (bfd_info->type != BFD_TYPE_NOT_CONFIGURED)
+    vty_out (vty, " neighbor %s bfd %s%s", addr,
+      (bfd_info->type == BFD_TYPE_MULTIHOP) ? "multihop" : "singlehop",
+      VTY_NEWLINE);
+
+  if (!CHECK_FLAG (bfd_info->flags, BFD_FLAG_PARAM_CFG) &&
+        (bfd_info->type == BFD_TYPE_NOT_CONFIGURED))
     vty_out (vty, " neighbor %s bfd%s", addr, VTY_NEWLINE);
 }
 
@@ -482,6 +606,36 @@ DEFUN (neighbor_bfd_param,
 
 }
 
+DEFUN_HIDDEN (neighbor_bfd_type,
+       neighbor_bfd_type_cmd,
+       NEIGHBOR_CMD2 "bfd " BFD_CMD_TYPE,
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Enables BFD support\n"
+       "Session type\n")
+{
+  struct peer *peer;
+  enum bfd_sess_type type;
+  int ret;
+
+  peer = peer_and_group_lookup_vty (vty, argv[0]);
+  if (!peer)
+    return CMD_WARNING;
+
+  if (!strcmp(argv[1], "singlehop"))
+    type = BFD_TYPE_SINGLEHOP;
+  else if (!strcmp(argv[1], "multihop"))
+    type = BFD_TYPE_MULTIHOP;
+  else
+    return CMD_WARNING;
+
+  ret = bgp_bfd_peer_param_type_set (peer, type);
+  if (ret != 0)
+    return bgp_vty_return (vty, ret);
+
+  return CMD_SUCCESS;
+}
+
 DEFUN (no_neighbor_bfd,
        no_neighbor_bfd_cmd,
        NO_NEIGHBOR_CMD2 "bfd",
@@ -515,6 +669,32 @@ ALIAS (no_neighbor_bfd,
        "Required min receive interval\n"
        "Desired min transmit interval\n")
 
+DEFUN_HIDDEN (no_neighbor_bfd_type,
+       no_neighbor_bfd_type_cmd,
+       NO_NEIGHBOR_CMD2 "bfd " BFD_CMD_TYPE,
+       NO_STR
+       NEIGHBOR_STR
+       NEIGHBOR_ADDR_STR2
+       "Disables BFD support\n"
+       "Session type\n")
+{
+  struct peer *peer;
+  int ret;
+
+  peer = peer_and_group_lookup_vty (vty, argv[0]);
+  if (! peer)
+    return CMD_WARNING;
+
+  if (!peer->bfd_info)
+    return 0;
+
+  ret = bgp_bfd_peer_param_type_set(peer, BFD_TYPE_NOT_CONFIGURED);
+  if (ret != 0)
+    return bgp_vty_return (vty, ret);
+
+  return CMD_SUCCESS;
+}
+
 void
 bgp_bfd_init(void)
 {
@@ -525,8 +705,10 @@ bgp_bfd_init(void)
   /* "neighbor bfd" commands. */
   install_element (BGP_NODE, &neighbor_bfd_cmd);
   install_element (BGP_NODE, &neighbor_bfd_param_cmd);
+  install_element (BGP_NODE, &neighbor_bfd_type_cmd);
   install_element (BGP_NODE, &no_neighbor_bfd_cmd);
   install_element (BGP_NODE, &no_neighbor_bfd_val_cmd);
+  install_element (BGP_NODE, &no_neighbor_bfd_type_cmd);
 
   /* Send the client registration */
   bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER);
index 4a29b3267dca0fcba9b8f8b7e2c9b708fb382af3..ddf03d4f1c44546987a9bca6209091ae54d21e91 100644 (file)
--- a/lib/bfd.c
+++ b/lib/bfd.c
@@ -45,6 +45,7 @@ bfd_info_create(void)
   assert(bfd_info);
 
   bfd_info->status = BFD_STATUS_UNKNOWN;
+  bfd_info->type = BFD_TYPE_NOT_CONFIGURED;
   bfd_info->last_update = 0;
   return bfd_info;
 }
index b001ae9670e30d4b3f34e3cd0db7793982c9388a..31e542d8b79363b8f7d9790e93a01f2a0b2650d5 100644 (file)
--- a/lib/bfd.h
+++ b/lib/bfd.h
@@ -29,6 +29,7 @@
 #define BFD_CMD_DETECT_MULT_RANGE "<2-255> "
 #define BFD_CMD_MIN_RX_RANGE "<50-60000> "
 #define BFD_CMD_MIN_TX_RANGE "<50-60000>"
+#define BFD_CMD_TYPE "(multihop|singlehop)"
 
 #define BFD_DEF_MIN_RX 300
 #define BFD_MIN_MIN_RX 50
 
 #define BFD_FLAG_PARAM_CFG (1 << 0) /* parameters have been configured */
 #define BFD_FLAG_BFD_REG   (1 << 1) /* Peer registered with BFD */
+#define BFD_FLAG_BFD_TYPE_MULTIHOP (1 << 2) /* Peer registered with BFD as multihop */
 
 #define BFD_STATUS_UNKNOWN (1 << 0) /* BFD session status never received */
 #define BFD_STATUS_DOWN    (1 << 1) /* BFD session status is down */
 #define BFD_STATUS_UP      (1 << 2) /* BFD session status is up */
 
+enum bfd_sess_type {
+  BFD_TYPE_NOT_CONFIGURED,
+  BFD_TYPE_SINGLEHOP,
+  BFD_TYPE_MULTIHOP
+};
+
 struct bfd_info
 {
-  u_int16_t flags;
-  u_int8_t  detect_mult;
-  u_int32_t desired_min_tx;
-  u_int32_t required_min_rx;
-  time_t    last_update;
-  u_int8_t  status;
+  u_int16_t           flags;
+  u_int8_t            detect_mult;
+  u_int32_t           desired_min_tx;
+  u_int32_t           required_min_rx;
+  time_t              last_update;
+  u_int8_t            status;
+  enum bfd_sess_type  type;
 };
 
 extern struct bfd_info *
index a6f130da68ce80ebfabc448acfb8f4b0db80a33c..760b1a9852c02ed4d7633e1ec941ed05f05bad98 100644 (file)
@@ -66,6 +66,7 @@ if_zebra_new_hook (struct interface *ifp)
 
   zebra_if->multicast = IF_ZEBRA_MULTICAST_UNSPEC;
   zebra_if->shutdown = IF_ZEBRA_SHUTDOWN_OFF;
+  zebra_ptm_if_init(zebra_if);
 
   ifp->ptm_enable = zebra_ptm_get_enable_state();
 #if defined (HAVE_RTADV)
@@ -453,6 +454,8 @@ if_add_update (struct interface *ifp)
   else if (if_data->multicast == IF_ZEBRA_MULTICAST_OFF)
     if_unset_flags (ifp, IFF_MULTICAST);
 
+  zebra_ptm_if_set_ptm_state(ifp, if_data);
+
   zebra_interface_add_update (ifp);
 
   if (! CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE))
@@ -1842,6 +1845,7 @@ DEFUN (no_ip_address,
   return ip_address_uninstall (vty, vty->index, argv[0], NULL, NULL);
 }
 
+
 #ifdef HAVE_NETLINK
 DEFUN (ip_address_label,
        ip_address_label_cmd,
@@ -2085,6 +2089,8 @@ if_config_write (struct vty *vty)
        {
          if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)
            vty_out (vty, " shutdown%s", VTY_NEWLINE);
+
+          zebra_ptm_if_write(vty, if_data);
        }
 
       if (ifp->desc)
index 9beabb62f8bdb78c57bbff25751ceba6741ada3b..bb76612ff1b8e2924dda155aa22c09711ba1a11e 100644 (file)
@@ -211,6 +211,9 @@ struct zebra_if
    */
   u_char primary_state;
 #endif /* SUNOS_5 */
+
+  /* ptm enable configuration */
+  u_char ptm_enable;
 };
 
 
index a124f739da0bc7ea34613dff62b7dc7d1b6d4469..949514f27bc98bd9dbaa3e07da13967d93892d30 100644 (file)
@@ -227,13 +227,15 @@ zebra_ptm_connect (struct thread *t)
     }
     zebra_ptm_send_status_req();
     ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_INITIAL;
-  } else {
+  } else if (ptm_cb.reconnect_time < ZEBRA_PTM_RECONNECT_TIME_MAX){
     ptm_cb.reconnect_time *= 2;
     if (ptm_cb.reconnect_time > ZEBRA_PTM_RECONNECT_TIME_MAX)
       ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_MAX;
 
     ptm_cb.t_timer = thread_add_timer (zebrad.master, zebra_ptm_connect, NULL,
                                         ptm_cb.reconnect_time);
+  } else if (ptm_cb.reconnect_time >= ZEBRA_PTM_RECONNECT_TIME_MAX){
+    ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_INITIAL;
   }
 
   return(errno);
@@ -246,17 +248,23 @@ DEFUN (zebra_ptm_enable,
 {
   struct listnode *i;
   struct interface *ifp;
+  struct zebra_if *if_data;
   vrf_iter_t iter;
 
-  ptm_cb.ptm_enable = 1;
+  ptm_cb.ptm_enable = ZEBRA_IF_PTM_ENABLE_ON;
 
   for (iter = vrf_first (); iter != VRF_ITER_INVALID; iter = vrf_next (iter))
     for (ALL_LIST_ELEMENTS_RO (vrf_iter2iflist (iter), i, ifp))
       if (!ifp->ptm_enable)
         {
-         ifp->ptm_enable = 1;
+          if_data = (struct zebra_if *)ifp->info;
+          if (if_data &&
+               (if_data->ptm_enable == ZEBRA_IF_PTM_ENABLE_UNSPEC))
+            {
+              ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_ON;
+            }
           /* Assign a default unknown status */
-         ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN;
+          ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN;
         }
 
   zebra_ptm_connect(NULL);
@@ -270,11 +278,84 @@ DEFUN (no_zebra_ptm_enable,
        NO_STR
        "Enable neighbor check with specified topology\n")
 {
-  ptm_cb.ptm_enable = 0;
+  ptm_cb.ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF;
   zebra_ptm_reset_status(1);
   return CMD_SUCCESS;
 }
 
+DEFUN (zebra_ptm_enable_if,
+       zebra_ptm_enable_if_cmd,
+       "ptm-enable",
+       "Enable neighbor check with specified topology\n")
+{
+  struct interface *ifp;
+  struct zebra_if *if_data;
+  int old_ptm_enable;
+  int send_linkdown = 0;
+
+  ifp = (struct interface *) vty->index;
+  if (ifp->ifindex == IFINDEX_INTERNAL)
+    {
+      return CMD_SUCCESS;
+    }
+
+  old_ptm_enable = ifp->ptm_enable;
+  ifp->ptm_enable = ptm_cb.ptm_enable;
+
+  if (if_is_no_ptm_operative(ifp))
+    send_linkdown = 1;
+
+  if (!old_ptm_enable && ptm_cb.ptm_enable)
+    {
+      if (!if_is_operative (ifp) && send_linkdown)
+        {
+         if (IS_ZEBRA_DEBUG_EVENT)
+           zlog_debug ("%s: Bringing down interface %s\n", __func__,
+                    ifp->name);
+          if_down (ifp);
+        }
+    }
+
+  if_data = ifp->info;
+  if_data->ptm_enable = ZEBRA_IF_PTM_ENABLE_UNSPEC;
+
+  return CMD_SUCCESS;
+}
+
+DEFUN (no_zebra_ptm_enable_if,
+       no_zebra_ptm_enable_if_cmd,
+       "no ptm-enable",
+       NO_STR
+       "Enable neighbor check with specified topology\n")
+{
+  struct interface *ifp;
+  int send_linkup = 0;
+  struct zebra_if *if_data;
+
+  ifp = (struct interface *) vty->index;
+
+  if ((ifp->ifindex != IFINDEX_INTERNAL) && (ifp->ptm_enable))
+    {
+      if (!if_is_operative(ifp))
+        send_linkup = 1;
+
+      ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF;
+      if (if_is_no_ptm_operative (ifp) && send_linkup)
+        {
+         if (IS_ZEBRA_DEBUG_EVENT)
+           zlog_debug ("%s: Bringing up interface %s\n", __func__,
+                    ifp->name);
+          if_up (ifp);
+        }
+    }
+
+  if_data = ifp->info;
+  if_data->ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF;
+
+  return CMD_SUCCESS;
+}
+
+
 void
 zebra_ptm_write (struct vty *vty)
 {
@@ -307,7 +388,8 @@ zebra_ptm_socket_init (void)
                 sizeof (addr.sun_family)+sizeof (ZEBRA_PTM_SOCK_NAME)-1);
   if (ret < 0)
     {
-      zlog_warn("%s: Unable to connect to socket %s [%s]",
+      if (IS_ZEBRA_DEBUG_EVENT)
+        zlog_debug("%s: Unable to connect to socket %s [%s]",
                      __func__, ZEBRA_PTM_SOCK_NAME, safe_strerror(errno));
       close (sock);
       return -1;
@@ -321,6 +403,8 @@ zebra_ptm_install_commands (void)
 {
   install_element (CONFIG_NODE, &zebra_ptm_enable_cmd);
   install_element (CONFIG_NODE, &no_zebra_ptm_enable_cmd);
+  install_element (INTERFACE_NODE, &zebra_ptm_enable_if_cmd);
+  install_element (INTERFACE_NODE, &no_zebra_ptm_enable_if_cmd);
 }
 
 /* BFD session goes down, send message to the protocols. */
@@ -981,21 +1065,41 @@ zebra_ptm_reset_status(int ptm_disable)
       {
         send_linkup = 0;
         if (ifp->ptm_enable)
-         {
-           if (!if_is_operative(ifp))
-             send_linkup = 1;
+          {
+            if (!if_is_operative(ifp))
+              send_linkup = 1;
 
             if (ptm_disable)
-             ifp->ptm_enable = 0;
+              ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_OFF;
             ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN;
 
-           if (if_is_operative (ifp) && send_linkup)
-              {
-                 if (IS_ZEBRA_DEBUG_EVENT)
-                  zlog_debug ("%s: Bringing up interface %s", __func__,
-                              ifp->name);
-                if_up (ifp);
+            if (if_is_operative (ifp) && send_linkup)
+             {
+               if (IS_ZEBRA_DEBUG_EVENT)
+                 zlog_debug ("%s: Bringing up interface %s", __func__,
+                               ifp->name);
+               if_up (ifp);
              }
           }
       }
 }
+
+void
+zebra_ptm_if_init(struct zebra_if *zebra_ifp)
+{
+  zebra_ifp->ptm_enable = ZEBRA_IF_PTM_ENABLE_UNSPEC;
+}
+
+void
+zebra_ptm_if_set_ptm_state(struct interface *ifp, struct zebra_if *zebra_ifp)
+{
+  if (zebra_ifp && zebra_ifp->ptm_enable != ZEBRA_IF_PTM_ENABLE_UNSPEC)
+    ifp->ptm_enable = zebra_ifp->ptm_enable;
+}
+
+void
+zebra_ptm_if_write (struct vty *vty, struct zebra_if *zebra_ifp)
+{
+  if (zebra_ifp->ptm_enable == ZEBRA_IF_PTM_ENABLE_OFF)
+    vty_out (vty, " no ptm-enable%s", VTY_NEWLINE);
+}
index dec1fe31af7ab15bee947d4bea84b924d08f9c0f..190ae996ec7726ed07c20a24bea0782bb483f459 100644 (file)
@@ -50,6 +50,11 @@ struct zebra_ptm_cb
 #define ZEBRA_PTM_STATUS_UP 1
 #define ZEBRA_PTM_STATUS_UNKNOWN 2
 
+/* For interface ptm-enable configuration. */
+#define ZEBRA_IF_PTM_ENABLE_OFF    0
+#define ZEBRA_IF_PTM_ENABLE_ON     1
+#define ZEBRA_IF_PTM_ENABLE_UNSPEC 2
+
 void zebra_ptm_init (void);
 void zebra_ptm_finish(void);
 int zebra_ptm_connect (struct thread *t);
@@ -64,4 +69,7 @@ void
 zebra_ptm_show_status(struct vty *vty, struct interface *ifp);
 int zebra_ptm_bfd_client_register (struct zserv *client, int sock,
                                     u_short length);
+void zebra_ptm_if_init(struct zebra_if *zebra_ifp);
+void zebra_ptm_if_set_ptm_state(struct interface *ifp, struct zebra_if *zebra_ifp);
+void zebra_ptm_if_write (struct vty *vty, struct zebra_if *zebra_ifp);
 #endif