From 950bd436b609a4359081fa1dab8c152ef91da5e6 Mon Sep 17 00:00:00 2001 From: radhika Date: Fri, 9 Oct 2015 11:18:09 -0700 Subject: [PATCH] Fix Quagga ptm status per interface to show more meaningful status MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Ticket: CM-6812 Reviewed By: Donald Testing Done: Double commit of 2119c8fccda5f1497820009c6f1f82eda3c8d0f1 from 2.5br to master In Quagga, the ptm status is shown as pass for all the interfaces that PTM is not tracking. When ptm is enabled in Quagga all the interfaces are initialized as pass and changed to fail/pass when ptm cable check updates are received. For all the interfaces for which no status was received from PTM remain at pass status. Interface show in quagga indicates wrong status and it should be n/a for all the untracked interfaces. To fix the problem introduced a third state “unknown” and this is default ptm status for all the interfaces. The ptm status is updated accordingly to pass/fail when the updates are received from PTM. Also, reset all interface ptm status to unknown when the connection with ptm is lost and the status gets updated when the connection with PTM is re-established. --- zebra/interface.c | 13 +---- zebra/zebra_ptm.c | 136 +++++++++++++++++++++++++++++++++------------- zebra/zebra_ptm.h | 6 ++ 3 files changed, 106 insertions(+), 49 deletions(-) diff --git a/zebra/interface.c b/zebra/interface.c index 4329efd2a0..9dc13f7b19 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -611,7 +611,7 @@ if_up (struct interface *ifp) struct prefix *p; /* Notify the protocol daemons. */ - if (ifp->ptm_enable && !ifp->ptm_status) { + if (ifp->ptm_enable && (ifp->ptm_status == ZEBRA_PTM_STATUS_DOWN)) { zlog_warn("%s: interface %s hasn't passed ptm check\n", __func__, ifp->name); return; @@ -836,16 +836,7 @@ if_dump_vty (struct vty *vty, struct interface *ifp) vty_out (vty, "down%s", VTY_NEWLINE); } - vty_out (vty, " PTM status: "); - if (ifp->ptm_enable) { - if (ifp->ptm_status) { - vty_out (vty, "pass%s", VTY_NEWLINE); - } else { - vty_out (vty, "fail%s", VTY_NEWLINE); - } - } else { - vty_out (vty, "disabled%s", VTY_NEWLINE); - } + zebra_ptm_show_status(vty, ifp); if (ifp->desc) vty_out (vty, " Description: %s%s", ifp->desc, diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c index 0fecd17d5d..039e80ddbb 100644 --- a/zebra/zebra_ptm.c +++ b/zebra/zebra_ptm.c @@ -82,6 +82,8 @@ int zebra_ptm_sock_read(struct thread *); static void zebra_ptm_install_commands (void); static int zebra_ptm_handle_msg_cb(void *arg, void *in_ctxt); void zebra_bfd_peer_replay_req (void); +void zebra_ptm_send_status_req(void); +void zebra_ptm_reset_status(int ptm_disable); const char ZEBRA_PTM_SOCK_NAME[] = "\0/var/run/ptmd.socket"; @@ -161,6 +163,7 @@ zebra_ptm_flush_messages (struct thread *thread) safe_strerror (errno)); close(ptm_cb.ptm_sock); ptm_cb.ptm_sock = -1; + zebra_ptm_reset_status(0); ptm_cb.t_timer = thread_add_timer (zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time); return (-1); @@ -185,6 +188,7 @@ zebra_ptm_send_message(char *data, int size) zlog_warn ("%s ptm socket error: %s", __func__, safe_strerror (errno)); close(ptm_cb.ptm_sock); ptm_cb.ptm_sock = -1; + zebra_ptm_reset_status(0); ptm_cb.t_timer = thread_add_timer (zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time); return -1; @@ -204,8 +208,6 @@ int zebra_ptm_connect (struct thread *t) { int init = 0; - void *out_ctxt; - int len = ZEBRA_PTM_SEND_MAX_SOCKBUF; if (ptm_cb.ptm_sock == -1) { zebra_ptm_socket_init(); @@ -218,15 +220,7 @@ zebra_ptm_connect (struct thread *t) NULL, ptm_cb.ptm_sock); zebra_bfd_peer_replay_req(); } - - 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, ZEBRA_PTM_CMD_STR, - ZEBRA_PTM_GET_STATUS_CMD); - ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &len); - - zebra_ptm_send_message(ptm_cb.out_data, len); - } + zebra_ptm_send_status_req(); ptm_cb.reconnect_time = ZEBRA_PTM_RECONNECT_TIME_INITIAL; } else { ptm_cb.reconnect_time *= 2; @@ -254,7 +248,8 @@ DEFUN (zebra_ptm_enable, if (!ifp->ptm_enable) { ifp->ptm_enable = 1; - ifp->ptm_status = 1; /* to bring down ports that may fail check */ + /* Assign a default unknown status */ + ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; } zebra_ptm_connect(NULL); @@ -268,28 +263,8 @@ DEFUN (no_zebra_ptm_enable, NO_STR "Enable neighbor check with specified topology\n") { - struct listnode *i; - struct interface *ifp; - int send_linkup; - ptm_cb.ptm_enable = 0; - for (ALL_LIST_ELEMENTS_RO (iflist, i, ifp)) - { - if (ifp->ptm_enable) - { - if (!if_is_operative(ifp)) - send_linkup = 1; - - ifp->ptm_enable = 0; - 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); - } - } - } - + zebra_ptm_reset_status(1); return CMD_SUCCESS; } @@ -436,22 +411,30 @@ static int zebra_ptm_handle_cbl_msg(void *arg, void *in_ctxt, struct interface *ifp, char *cbl_str) { + int send_linkup = 0; + if (IS_ZEBRA_DEBUG_EVENT) zlog_debug("%s: Recv Port [%s] cbl status [%s]", __func__, ifp->name, cbl_str); - if (!strcmp(cbl_str, ZEBRA_PTM_PASS_STR) && (!ifp->ptm_status)) { - ifp->ptm_status = 1; - if (ifp->ptm_enable && if_is_no_ptm_operative (ifp)) + if (!strcmp(cbl_str, ZEBRA_PTM_PASS_STR) && + (ifp->ptm_status != ZEBRA_PTM_STATUS_UP)) { + + if (ifp->ptm_status == ZEBRA_PTM_STATUS_DOWN) + send_linkup = 1; + ifp->ptm_status = ZEBRA_PTM_STATUS_UP; + if (ifp->ptm_enable && if_is_no_ptm_operative (ifp) && send_linkup) if_up (ifp); - } else if (!strcmp (cbl_str, ZEBRA_PTM_FAIL_STR) && (ifp->ptm_status)) { - ifp->ptm_status = 0; + } else if (!strcmp (cbl_str, ZEBRA_PTM_FAIL_STR) && + (ifp->ptm_status != ZEBRA_PTM_STATUS_DOWN)) { + ifp->ptm_status = ZEBRA_PTM_STATUS_DOWN; if (ifp->ptm_enable && if_is_no_ptm_operative (ifp)) if_down (ifp); } return 0; } + /* * zebra_ptm_handle_msg_cb - The purpose of this callback function is to handle * all the command responses and notifications received from PTM. @@ -541,6 +524,7 @@ zebra_ptm_sock_read (struct thread *thread) close (ptm_cb.ptm_sock); ptm_cb.ptm_sock = -1; + zebra_ptm_reset_status(0); ptm_cb.t_timer = thread_add_timer (zebrad.master, zebra_ptm_connect, NULL, ptm_cb.reconnect_time); return (-1); @@ -861,3 +845,79 @@ zebra_ptm_get_enable_state(void) { return ptm_cb.ptm_enable; } + +/* + * zebra_ptm_get_status_str - Convert status to a display string. + */ +static const char * +zebra_ptm_get_status_str(int status) +{ + switch (status) + { + case ZEBRA_PTM_STATUS_DOWN: + return "fail"; + case ZEBRA_PTM_STATUS_UP: + return "pass"; + case ZEBRA_PTM_STATUS_UNKNOWN: + default: + return "n/a"; + } +} + +void +zebra_ptm_show_status(struct vty *vty, struct interface *ifp) +{ + vty_out (vty, " PTM status: "); + if (ifp->ptm_enable) { + vty_out (vty, "%s%s", zebra_ptm_get_status_str (ifp->ptm_status), + VTY_NEWLINE); + } else { + vty_out (vty, "disabled%s", VTY_NEWLINE); + } +} + +void +zebra_ptm_send_status_req(void) +{ + void *out_ctxt; + int len = ZEBRA_PTM_SEND_MAX_SOCKBUF; + + 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, ZEBRA_PTM_CMD_STR, + ZEBRA_PTM_GET_STATUS_CMD); + ptm_lib_complete_msg(ptm_hdl, out_ctxt, ptm_cb.out_data, &len); + + zebra_ptm_send_message(ptm_cb.out_data, len); + } +} + +void +zebra_ptm_reset_status(int ptm_disable) +{ + struct listnode *i; + struct interface *ifp; + int send_linkup; + + for (ALL_LIST_ELEMENTS_RO (iflist, i, ifp)) + { + send_linkup = 0; + if (ifp->ptm_enable) + { + if (!if_is_operative(ifp)) + send_linkup = 1; + + if (ptm_disable) + ifp->ptm_enable = 0; + 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); + } + } + } +} diff --git a/zebra/zebra_ptm.h b/zebra/zebra_ptm.h index e26edf0928..6767d822e0 100644 --- a/zebra/zebra_ptm.h +++ b/zebra/zebra_ptm.h @@ -46,6 +46,10 @@ struct zebra_ptm_cb int pid; }; +#define ZEBRA_PTM_STATUS_DOWN 0 +#define ZEBRA_PTM_STATUS_UP 1 +#define ZEBRA_PTM_STATUS_UNKNOWN 2 + void zebra_ptm_init (void); void zebra_ptm_finish(void); int zebra_ptm_connect (struct thread *t); @@ -55,4 +59,6 @@ int zebra_ptm_get_enable_state(void); int zebra_ptm_bfd_dst_register (struct zserv *client, int sock, u_short length, int command); int zebra_ptm_bfd_dst_deregister (struct zserv *client, int sock, u_short length); +void +zebra_ptm_show_status(struct vty *vty, struct interface *ifp); #endif -- 2.39.5