summaryrefslogtreecommitdiffstats
path: root/zebra/zebra_ptm.c
diff options
context:
space:
mode:
authorradhika <radhika@cumulusnetworks.com>2015-10-09 20:18:09 +0200
committerradhika <radhika@cumulusnetworks.com>2015-10-09 20:18:09 +0200
commit950bd436b609a4359081fa1dab8c152ef91da5e6 (patch)
tree1e01a3d7c5354156ae83c158da800f8b7c449397 /zebra/zebra_ptm.c
parentMerge branch 'cmaster' of ssh://stash.cumulusnetworks.com:7999/quag/quagga in... (diff)
downloadfrr-950bd436b609a4359081fa1dab8c152ef91da5e6.tar.xz
frr-950bd436b609a4359081fa1dab8c152ef91da5e6.zip
Fix Quagga ptm status per interface to show more meaningful status
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.
Diffstat (limited to 'zebra/zebra_ptm.c')
-rw-r--r--zebra/zebra_ptm.c136
1 files changed, 98 insertions, 38 deletions
diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c
index 0fecd17d5..039e80ddb 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);
+ }
+ }
+ }
+}