diff options
author | Donald Sharp <sharpd@cumulusnetworks.com> | 2015-07-22 22:07:08 +0200 |
---|---|---|
committer | Donald Sharp <sharpd@cumulusnetworks.com> | 2015-07-22 22:07:08 +0200 |
commit | c8ed14ddb63a0ecbab5835ce2bb044afbc15895d (patch) | |
tree | 59ac029713ed5582789a3769a4bde20c88b2a6b9 | |
parent | Fixup of peer memory leaks in bgp (diff) | |
download | frr-c8ed14ddb63a0ecbab5835ce2bb044afbc15895d.tar.xz frr-c8ed14ddb63a0ecbab5835ce2bb044afbc15895d.zip |
ptm-integration.patch
Integrates Prescriptive Topology Module(ptm) into quagga.
If this module is enabled, link ups are notified only after the link is verified
as being connected to the neighbor specified. The neighbor specification and
checking is done by the ptm daemon.
<This is a recommit of this patch because it was changed in situ>
-rw-r--r-- | zebra/interface.c | 2 | ||||
-rw-r--r-- | zebra/main.c | 1 | ||||
-rw-r--r-- | zebra/zebra_ptm.c | 314 | ||||
-rw-r--r-- | zebra/zebra_ptm.h | 22 |
4 files changed, 212 insertions, 127 deletions
diff --git a/zebra/interface.c b/zebra/interface.c index 3d3ced3ff..70cdf36f8 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -63,7 +63,7 @@ if_zebra_new_hook (struct interface *ifp) zebra_if->multicast = IF_ZEBRA_MULTICAST_UNSPEC; zebra_if->shutdown = IF_ZEBRA_SHUTDOWN_OFF; - ifp->ptm_enable = ptm_enable; + ifp->ptm_enable = zebra_ptm_get_enable_state(); #ifdef RTADV { /* Set default router advertise values. */ diff --git a/zebra/main.c b/zebra/main.c index 1977e4e3a..f8f593278 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -177,6 +177,7 @@ sigint (void) irdp_finish(); #endif + zebra_ptm_finish(); exit (0); } diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c index 0a90afcac..531646448 100644 --- a/zebra/zebra_ptm.c +++ b/zebra/zebra_ptm.c @@ -22,6 +22,7 @@ #include <zebra.h> #include <sys/un.h> /* for sockaddr_un */ #include <net/if.h> +#include "vty.h" #include "zebra/zserv.h" #include "zebra/interface.h" #include "zebra/debug.h" @@ -30,6 +31,7 @@ #include "command.h" #include "stream.h" #include "ptm_lib.h" +#include "buffer.h" #include "zebra/zebra_ptm_redistribute.h" #define ZEBRA_PTM_RECONNECT_TIME_INITIAL 1 /* initial reconnect is 1s */ @@ -42,6 +44,7 @@ const char ZEBRA_PTM_GET_STATUS_CMD[] = "get-status"; const char ZEBRA_PTM_BFD_START_CMD[] = "start-bfd-sess"; const char ZEBRA_PTM_BFD_STOP_CMD[] = "stop-bfd-sess"; +const char ZEBRA_PTM_CMD_STR[] = "cmd"; const char ZEBRA_PTM_PORT_STR[] = "port"; const char ZEBRA_PTM_CBL_STR[] = "cbl status"; const char ZEBRA_PTM_PASS_STR[] = "pass"; @@ -66,18 +69,13 @@ const char ZEBRA_PTM_BFD_IFNAME_FIELD[] = "ifName"; const char ZEBRA_PTM_BFD_MAX_HOP_CNT_FIELD[] = "maxHopCnt"; extern struct zebra_t zebrad; -int ptm_enable; -int zebra_ptm_sock = -1; -struct thread *zebra_ptm_thread = NULL; - -static int zebra_ptm_reconnect_time = ZEBRA_PTM_RECONNECT_TIME_INITIAL; -int zebra_ptm_pid = 0; static ptm_lib_handle_t *ptm_hdl; +struct zebra_ptm_cb ptm_cb; + static int zebra_ptm_socket_init(void); int zebra_ptm_sock_read(struct thread *); -int zebra_ptm_sock_write(struct thread *); static void zebra_ptm_install_commands (void); static int zebra_ptm_handle_cbl_msg(void *arg, void *in_ctxt); static int zebra_ptm_handle_bfd_msg(void *arg, void *in_ctxt); @@ -90,53 +88,151 @@ zebra_ptm_init (void) { char buf[64]; - zebra_ptm_pid = getpid(); + memset(&ptm_cb, 0, sizeof(struct zebra_ptm_cb)); + + ptm_cb.out_data = calloc(1, ZEBRA_PTM_SEND_MAX_SOCKBUF); + if (!ptm_cb.out_data) + { + zlog_warn("%s: Allocation of send data failed", __func__); + return; + } + + ptm_cb.in_data = calloc(1, ZEBRA_PTM_MAX_SOCKBUF); + if (!ptm_cb.in_data) + { + zlog_warn("%s: Allocation of recv data failed", __func__); + free(ptm_cb.out_data); + return; + } + + ptm_cb.pid = getpid(); zebra_ptm_install_commands(); sprintf(buf, "%s", "quagga"); ptm_hdl = ptm_lib_register(buf, NULL, zebra_ptm_handle_bfd_msg, zebra_ptm_handle_cbl_msg); + ptm_cb.wb = buffer_new(0); + + ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_INITIAL; + + ptm_cb.ptm_sock = -1; +} + +void +zebra_ptm_finish(void) +{ + if (ptm_cb.ptm_sock != -1) + close(ptm_cb.ptm_sock); + + if (ptm_cb.wb) + buffer_free(ptm_cb.wb); + + if (ptm_cb.out_data) + free(ptm_cb.out_data); + + if (ptm_cb.in_data) + free(ptm_cb.in_data); + + /* Release threads. */ + if (ptm_cb.t_read) + thread_cancel (ptm_cb.t_read); + if (ptm_cb.t_write) + thread_cancel (ptm_cb.t_write); + if (ptm_cb.t_timer) + thread_cancel (ptm_cb.t_timer); +} + +static int +zebra_ptm_flush_messages (struct thread *thread) +{ + ptm_cb.t_write = NULL; + + if (ptm_cb.ptm_sock == -1) + return -1; + + errno = 0; + + switch (buffer_flush_available(ptm_cb.wb, ptm_cb.ptm_sock)) + { + case BUFFER_ERROR: + zlog_warn ("%s ptm socket error: %s", __func__, + safe_strerror (errno)); + close(ptm_cb.ptm_sock); + ptm_cb.ptm_sock = -1; + ptm_cb.t_timer = thread_add_timer (zebrad.master, zebra_ptm_connect, + NULL, ptm_cb.reconnect_time); + return (-1); + case BUFFER_PENDING: + ptm_cb.t_write = thread_add_write(zebrad.master, zebra_ptm_flush_messages, + NULL, ptm_cb.ptm_sock); + break; + case BUFFER_EMPTY: + break; + } + + return(0); +} + +static int +zebra_ptm_send_message(char *data, int size) +{ + errno = 0; + switch (buffer_write(ptm_cb.wb, ptm_cb.ptm_sock, data, size)) + { + case BUFFER_ERROR: + zlog_warn ("%s ptm socket error: %s", __func__, safe_strerror (errno)); + close(ptm_cb.ptm_sock); + ptm_cb.ptm_sock = -1; + ptm_cb.t_timer = thread_add_timer (zebrad.master, zebra_ptm_connect, + NULL, ptm_cb.reconnect_time); + return -1; + case BUFFER_EMPTY: + THREAD_OFF(ptm_cb.t_write); + break; + case BUFFER_PENDING: + THREAD_WRITE_ON(zebrad.master, ptm_cb.t_write, + zebra_ptm_flush_messages, NULL, ptm_cb.ptm_sock); + break; + } + + return 0; } int zebra_ptm_connect (struct thread *t) { int init = 0; - char *data; void *out_ctxt; int len = ZEBRA_PTM_SEND_MAX_SOCKBUF; - if (zebra_ptm_sock == -1) { + if (ptm_cb.ptm_sock == -1) { zebra_ptm_socket_init(); init = 1; } - if (zebra_ptm_sock != -1) { + if (ptm_cb.ptm_sock != -1) { if (init) { + ptm_cb.t_read = thread_add_read (zebrad.master, zebra_ptm_sock_read, + NULL, ptm_cb.ptm_sock); zebra_bfd_peer_replay_req(); } - if (ptm_enable) { - data = calloc(1, len); - if (!data) { - zlog_debug("%s: Allocation of send data failed", __func__); - return -1; - } + if (ptm_cb.ptm_enable) { ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt); - ptm_lib_append_msg(ptm_hdl, out_ctxt, "cmd", ZEBRA_PTM_GET_STATUS_CMD); - ptm_lib_complete_msg(ptm_hdl, out_ctxt, data, &len); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, + ZEBRA_PTM_GET_STATUS_CMD); + ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &len); - zebra_ptm_thread = thread_add_write (zebrad.master, zebra_ptm_sock_write, - data, zebra_ptm_sock); + zebra_ptm_send_message(ptm_cb.out_data, len); } - zebra_ptm_reconnect_time = ZEBRA_PTM_RECONNECT_TIME_INITIAL; + ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_INITIAL; } else { - zebra_ptm_reconnect_time *= 2; - if (zebra_ptm_reconnect_time > ZEBRA_PTM_RECONNECT_TIME_MAX) - zebra_ptm_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; - zebra_ptm_thread = thread_add_timer (zebrad.master, zebra_ptm_connect, NULL, - zebra_ptm_reconnect_time); + ptm_cb.t_timer = thread_add_timer (zebrad.master, zebra_ptm_connect, NULL, + ptm_cb.reconnect_time); } return(errno); @@ -150,7 +246,7 @@ DEFUN (zebra_ptm_enable, struct listnode *i; struct interface *ifp; - ptm_enable = 1; + ptm_cb.ptm_enable = 1; for (ALL_LIST_ELEMENTS_RO (iflist, i, ifp)) if (!ifp->ptm_enable) @@ -174,7 +270,7 @@ DEFUN (no_zebra_ptm_enable, struct interface *ifp; int send_linkup; - ptm_enable = 0; + ptm_cb.ptm_enable = 0; for (ALL_LIST_ELEMENTS_RO (iflist, i, ifp)) { if (ifp->ptm_enable) @@ -184,8 +280,9 @@ DEFUN (no_zebra_ptm_enable, ifp->ptm_enable = 0; if (if_is_operative (ifp) && send_linkup) { - zlog_debug ("%s: Bringing up interface %s", __func__, - ifp->name); + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug ("%s: Bringing up interface %s", __func__, + ifp->name); if_up (ifp); } } @@ -197,7 +294,7 @@ DEFUN (no_zebra_ptm_enable, void zebra_ptm_write (struct vty *vty) { - if (ptm_enable) + if (ptm_cb.ptm_enable) vty_out (vty, "ptm-enable%s", VTY_NEWLINE); return; @@ -210,7 +307,7 @@ zebra_ptm_socket_init (void) int sock; struct sockaddr_un addr; - zebra_ptm_sock = -1; + ptm_cb.ptm_sock = -1; sock = socket (PF_UNIX, (SOCK_STREAM | SOCK_NONBLOCK), 0); if (sock < 0) @@ -231,9 +328,7 @@ zebra_ptm_socket_init (void) close (sock); return -1; } - zlog_debug ("%s: connection to ptm socket %s succeeded", - __func__, ZEBRA_PTM_SOCK_NAME); - zebra_ptm_sock = sock; + ptm_cb.ptm_sock = sock; return sock; } @@ -245,7 +340,7 @@ zebra_ptm_install_commands (void) } /* BFD session goes down, send message to the protocols. */ -void +static void if_bfd_session_down (struct interface *ifp, struct prefix *dp, struct prefix *sp) { if (IS_ZEBRA_DEBUG_EVENT) @@ -255,8 +350,8 @@ if_bfd_session_down (struct interface *ifp, struct prefix *dp, struct prefix *sp if (ifp) { zlog_debug ("MESSAGE: ZEBRA_INTERFACE_BFD_DEST_DOWN %s/%d on %s", - inet_ntop (dp->family, &dp->u.prefix, buf, INET6_ADDRSTRLEN), - dp->prefixlen, ifp->name); + inet_ntop (dp->family, &dp->u.prefix, buf[0], + INET6_ADDRSTRLEN), dp->prefixlen, ifp->name); } else { @@ -322,8 +417,9 @@ zebra_ptm_handle_bfd_msg(void *arg, void *in_ctxt) return -1; } - zlog_debug("%s: Recv Port [%s] bfd status [%s] peer [%s] local [%s]", - __func__, port_str, bfdst_str, dest_str, src_str); + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s: Recv Port [%s] bfd status [%s] peer [%s] local [%s]", + __func__, port_str, bfdst_str, dest_str, src_str); /* we only care if bfd session goes down */ if (!strcmp (bfdst_str, ZEBRA_PTM_BFDSTATUS_DOWN_STR)) { @@ -374,11 +470,19 @@ zebra_ptm_handle_cbl_msg(void *arg, void *in_ctxt) struct interface *ifp; char cbl_str[32]; char port_str[128]; + char cmd_str[32]; + + ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_CMD_STR, cmd_str); + + /* Drop command response messages */ + if (cmd_str[0] != '\0') { + return 0; + } ptm_lib_find_key_in_msg(in_ctxt, ZEBRA_PTM_PORT_STR, port_str); if (port_str[0] == '\0') { - zlog_debug("%s: Key %s not found in PTM msg", __func__, + zlog_debug("%s: key %s not found in PTM msg", __func__, ZEBRA_PTM_PORT_STR); return 0; } @@ -391,7 +495,8 @@ zebra_ptm_handle_cbl_msg(void *arg, void *in_ctxt) return 0; } - zlog_debug("%s: Recv Port [%s] cbl status [%s]", __func__, + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("%s: Recv Port [%s] cbl status [%s]", __func__, port_str, cbl_str); ifp = if_lookup_by_name(port_str); @@ -415,46 +520,10 @@ zebra_ptm_handle_cbl_msg(void *arg, void *in_ctxt) } int -zebra_ptm_sock_write (struct thread *thread) -{ - int sock; - int nbytes; - char *data; - - sock = THREAD_FD (thread); - data = THREAD_ARG (thread); - - if (sock == -1) - return -1; - - errno = 0; - - nbytes = send(sock, data, strlen(data), 0); - - if (nbytes <= 0) { - if (errno && errno != EWOULDBLOCK && errno != EAGAIN) { - zlog_warn ("%s routing socket error: %s", __func__, - safe_strerror (errno)); - zebra_ptm_sock = -1; - zebra_ptm_thread = thread_add_timer (zebrad.master, zebra_ptm_connect, - NULL, zebra_ptm_reconnect_time); - return (-1); - } - } - - zlog_debug ("%s: Sent message (%d) %s", __func__, strlen(data), data); - zebra_ptm_thread = thread_add_read (zebrad.master, zebra_ptm_sock_read, - NULL, sock); - free (data); - return(0); -} - -int zebra_ptm_sock_read (struct thread *thread) { int sock, done = 0; int rc; - char *rcvptr; errno = 0; sock = THREAD_FD (thread); @@ -464,9 +533,7 @@ zebra_ptm_sock_read (struct thread *thread) /* PTM communicates in CSV format */ while(!done) { - rcvptr = calloc(1, ZEBRA_PTM_MAX_SOCKBUF); - - rc = ptm_lib_process_msg(ptm_hdl, sock, rcvptr, ZEBRA_PTM_MAX_SOCKBUF, + rc = ptm_lib_process_msg(ptm_hdl, sock, ptm_cb.in_data, ZEBRA_PTM_MAX_SOCKBUF, NULL); if (rc <= 0) break; @@ -477,17 +544,16 @@ zebra_ptm_sock_read (struct thread *thread) zlog_warn ("%s routing socket error: %s(%d) bytes %d", __func__, safe_strerror (errno), errno, rc); - close (zebra_ptm_sock); - zebra_ptm_sock = -1; - zebra_ptm_thread = thread_add_timer (zebrad.master, zebra_ptm_connect, - NULL, zebra_ptm_reconnect_time); + close (ptm_cb.ptm_sock); + ptm_cb.ptm_sock = -1; + ptm_cb.t_timer = thread_add_timer (zebrad.master, zebra_ptm_connect, + NULL, ptm_cb.reconnect_time); return (-1); } } - free(rcvptr); - zebra_ptm_thread = thread_add_read (zebrad.master, zebra_ptm_sock_read, - NULL, sock); + ptm_cb.t_read = thread_add_read (zebrad.master, zebra_ptm_sock_read, + NULL, ptm_cb.ptm_sock); return 0; } @@ -497,7 +563,6 @@ int zebra_ptm_bfd_dst_register (struct zserv *client, int sock, u_short length, int command) { - char *data; struct stream *s; struct prefix src_p; struct prefix dst_p; @@ -518,30 +583,24 @@ zebra_ptm_bfd_dst_register (struct zserv *client, int sock, u_short length, else client->bfd_peer_add_cnt++; - zlog_debug("bfd_dst_register msg from client %s: length=%d", - zebra_route_string(client->proto), length); - - if (zebra_ptm_sock == -1) - { - zebra_ptm_thread = thread_add_timer (zebrad.master, zebra_ptm_connect, - NULL, zebra_ptm_reconnect_time); - return -1; - } + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("bfd_dst_register msg from client %s: length=%d", + zebra_route_string(client->proto), length); - data = calloc(1, data_len); - if (!data) + if (ptm_cb.ptm_sock == -1) { - zlog_debug("%s: Allocation of send data failed", __func__); + ptm_cb.t_timer = thread_add_timer (zebrad.master, zebra_ptm_connect, + NULL, ptm_cb.reconnect_time); return -1; } ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt); sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_START_CMD); - ptm_lib_append_msg(ptm_hdl, out_ctxt, "cmd", tmp_buf); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, tmp_buf); sprintf(tmp_buf, "quagga"); ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD, tmp_buf); - sprintf(tmp_buf, "%d", zebra_ptm_pid); + sprintf(tmp_buf, "%d", ptm_cb.pid); ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEQID_FIELD, tmp_buf); @@ -650,9 +709,12 @@ zebra_ptm_bfd_dst_register (struct zserv *client, int sock, u_short length, if_name); } - ptm_lib_complete_msg(ptm_hdl, out_ctxt, data, &data_len); - zebra_ptm_thread = thread_add_write (zebrad.master, zebra_ptm_sock_write, - data, zebra_ptm_sock); + ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &data_len); + + if (IS_ZEBRA_DEBUG_SEND) + zlog_debug ("%s: Sent message (%d) %s", __func__, data_len, + ptm_cb.out_data); + zebra_ptm_send_message(ptm_cb.out_data, data_len); return 0; } @@ -660,7 +722,6 @@ zebra_ptm_bfd_dst_register (struct zserv *client, int sock, u_short length, int zebra_ptm_bfd_dst_deregister (struct zserv *client, int sock, u_short length) { - char *data; struct stream *s; struct prefix src_p; struct prefix dst_p; @@ -674,33 +735,27 @@ zebra_ptm_bfd_dst_deregister (struct zserv *client, int sock, u_short length) client->bfd_peer_del_cnt++; - zlog_debug("bfd_dst_deregister msg from client %s: length=%d", - zebra_route_string(client->proto), length); - - if (zebra_ptm_sock == -1) - { - zebra_ptm_thread = thread_add_timer (zebrad.master, zebra_ptm_connect, - NULL, zebra_ptm_reconnect_time); - return -1; - } + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug("bfd_dst_deregister msg from client %s: length=%d", + zebra_route_string(client->proto), length); - data = calloc(1, data_len); - if (!data) + if (ptm_cb.ptm_sock == -1) { - zlog_debug("%s: Allocation of send data failed", __func__); + ptm_cb.t_timer = thread_add_timer (zebrad.master, zebra_ptm_connect, + NULL, ptm_cb.reconnect_time); return -1; } ptm_lib_init_msg(ptm_hdl, 0, PTMLIB_MSG_TYPE_CMD, NULL, &out_ctxt); sprintf(tmp_buf, "%s", ZEBRA_PTM_BFD_STOP_CMD); - ptm_lib_append_msg(ptm_hdl, out_ctxt, "cmd", tmp_buf); + ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_CMD_STR, tmp_buf); sprintf(tmp_buf, "%s", "quagga"); ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_CLIENT_FIELD, tmp_buf); - sprintf(tmp_buf, "%d", zebra_ptm_pid); + sprintf(tmp_buf, "%d", ptm_cb.pid); ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEQID_FIELD, tmp_buf); @@ -793,8 +848,17 @@ zebra_ptm_bfd_dst_deregister (struct zserv *client, int sock, u_short length) if_name); } - ptm_lib_complete_msg(ptm_hdl, out_ctxt, data, &data_len); - zebra_ptm_thread = thread_add_write (zebrad.master, zebra_ptm_sock_write, - data, zebra_ptm_sock); + ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &data_len); + if (IS_ZEBRA_DEBUG_SEND) + zlog_debug ("%s: Sent message (%d) %s", __func__, data_len, + ptm_cb.out_data); + + zebra_ptm_send_message(ptm_cb.out_data, data_len); return 0; } + +int +zebra_ptm_get_enable_state(void) +{ + return ptm_cb.ptm_enable; +} diff --git a/zebra/zebra_ptm.h b/zebra/zebra_ptm.h index 85a0bdced..e26edf092 100644 --- a/zebra/zebra_ptm.h +++ b/zebra/zebra_ptm.h @@ -26,11 +26,31 @@ extern const char ZEBRA_PTM_SOCK_NAME[]; #define ZEBRA_PTM_MAX_SOCKBUF 3200 /* 25B *128 ports */ #define ZEBRA_PTM_SEND_MAX_SOCKBUF 512 -extern int ptm_enable; + +/* Zebra ptm context block */ +struct zebra_ptm_cb +{ + int ptm_sock; /* ptm file descriptor. */ + + struct buffer *wb; /* Buffer of data waiting to be written to ptm. */ + + struct thread *t_read; /* Thread for read */ + struct thread *t_write; /* Thread for write */ + struct thread *t_timer; /* Thread for timer */ + + char *out_data; + char *in_data; + int reconnect_time; + + int ptm_enable; + int pid; +}; void zebra_ptm_init (void); +void zebra_ptm_finish(void); int zebra_ptm_connect (struct thread *t); void zebra_ptm_write (struct vty *vty); +int zebra_ptm_get_enable_state(void); int zebra_ptm_bfd_dst_register (struct zserv *client, int sock, u_short length, int command); |