Addition on hidden command "bfd multihop/singlehop" and "ptm-enable" per interface command

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🔤bcad::2 remote-as 100
neighbor 3101🔤bcad::2 peer-group igroup
neighbor 30.0.2.6 remote-as 200
neighbor 30.0.2.6 bfd multihop
neighbor 3102🔤bcad::6 remote-as 200
neighbor 3102🔤bcad::6 bfd
neighbor 3102🔤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
This commit is contained in:
radhika 2016-04-21 15:39:38 -07:00
parent 9fe88bc7ca
commit 986aa00f94
7 changed files with 341 additions and 28 deletions

View 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);

View File

@ -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;
}

View File

@ -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
@ -42,19 +43,27 @@
#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 *

View 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)

View File

@ -211,6 +211,9 @@ struct zebra_if
*/
u_char primary_state;
#endif /* SUNOS_5 */
/* ptm enable configuration */
u_char ptm_enable;
};

View 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);
}

View 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