[ovs-dev,v3,14/19] keepalive: Check the link status as part of PMD health checks.

Message ID 1501834086-31829-15-git-send-email-bhanuprakash.bodireddy@intel.com
State Superseded
Headers show

Commit Message

Bodireddy, Bhanuprakash Aug. 4, 2017, 8:08 a.m.
This commit adds the initial support in to performing PMD health checks.
The ports handled by the PMD threads are checked for the link status and
the same is updated in to keepalive info structure.

Signed-off-by: Bhanuprakash Bodireddy <bhanuprakash.bodireddy@intel.com>
---
 lib/dpif-netdev.c | 37 +++++++++++++++++++++++++++++++++++--
 lib/keepalive.c   | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/keepalive.h   | 18 +++++++++++++++++-
 3 files changed, 104 insertions(+), 3 deletions(-)

Patch

diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index cf955e5..a6edf4d 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -52,6 +52,7 @@ 
 #include "keepalive.h"
 #include "latch.h"
 #include "netdev.h"
+#include "netdev-provider.h"
 #include "netdev-vport.h"
 #include "netlink.h"
 #include "odp-execute.h"
@@ -981,9 +982,41 @@  sorted_poll_thread_list(struct dp_netdev *dp,
 }
 
 static void
-pmd_health_check(struct dp_netdev_pmd_thread *pmd OVS_UNUSED)
+pmd_health_check(struct dp_netdev_pmd_thread *pmd)
 {
-    /* Nothing */
+    int port_link_status = 0;
+    struct rxq_poll *poll;
+
+    struct svec pmd_poll_list;
+    svec_init(&pmd_poll_list);
+    HMAP_FOR_EACH (poll, node, &pmd->poll_list) {
+        svec_add(&pmd_poll_list, netdev_rxq_get_name(poll->rxq->rx));
+    }
+
+    /* With MQ enabled, remove the duplicates. */
+    svec_sort_unique(&pmd_poll_list);
+
+    const char *port_name;
+    int i = 0;
+    SVEC_FOR_EACH (i, port_name, &pmd_poll_list) {
+        struct netdev *dev = netdev_from_name(port_name);
+        if (dev) {
+            char *link_state = netdev_get_carrier(dev) ? "up" : "down";
+            ka_info_update_port_status(port_name, 0, link_state,
+                                        pmd->core_id, i);
+            netdev_close(dev);
+        }
+    }
+    svec_destroy(&pmd_poll_list);
+
+    port_link_status = ka_get_polled_ports_status(pmd->core_id);
+
+    int pmd_hc_state = ka_get_pmd_health_check_state(pmd->core_id);
+    if (PMD_HC_COMPLETE == pmd_hc_state) {
+        if (port_link_status == ACTIVE_RUN_STATE) {
+            ka_set_pmd_state_ts(pmd->core_id, KA_STATE_ALIVE, 0);
+        }
+    }
 }
 
 static void
diff --git a/lib/keepalive.c b/lib/keepalive.c
index b4d33cc..c306839 100644
--- a/lib/keepalive.c
+++ b/lib/keepalive.c
@@ -437,6 +437,58 @@  ka_stats_run(void)
     return ka_stats;
 }
 
+enum pmdhealth_status ka_get_polled_ports_status(unsigned core_id)
+{
+    if (OVS_UNLIKELY(!ka_info)) {
+        return FAILURE_STATE;
+    }
+
+    int failed = 0;
+    int n_ports = ka_info->ext_stats[core_id].num_poll_ports;
+    for (int i = 0; i < n_ports; i++) {
+        int state;
+        state =
+          ka_info->ext_stats[core_id].port_stats[i].state[PORT_LINK_CHECK];
+        if (state == FAILURE_STATE) {
+            failed = 1;
+            break;
+        }
+    }
+
+    if (!failed) {
+        return ACTIVE_RUN_STATE;
+    } else {
+        return FAILURE_STATE;
+    }
+}
+
+void
+ka_info_update_port_status(const char *port, int qid OVS_UNUSED,
+                           char *link_state, int core_id, int idx)
+{
+    if (OVS_UNLIKELY(!ka_info)) {
+        return;
+    }
+
+    ka_info->ext_stats[core_id].num_poll_ports = idx;
+
+    if (OVS_LIKELY(core_id != NON_PMD_CORE_ID)) {
+        ka_info->ext_stats[core_id].port_stats[idx].port = port;
+        ka_info->ext_stats[core_id].port_stats[idx].link_state =
+                                                           link_state;
+    }
+
+    int state;
+    if (!strcmp(link_state, "down")) {
+        state = FAILURE_STATE;
+    } else {
+        state = ACTIVE_RUN_STATE;
+    }
+
+    ka_info->ext_stats[core_id].port_stats[idx].state[PORT_LINK_CHECK] =
+                                                               state;
+}
+
 static void
 ka_unixctl_pmd_health_show(struct unixctl_conn *conn, int argc OVS_UNUSED,
                            const char *argv[] OVS_UNUSED, void *ka_info_)
diff --git a/lib/keepalive.h b/lib/keepalive.h
index 61697b2..ff4aa3c 100644
--- a/lib/keepalive.h
+++ b/lib/keepalive.h
@@ -47,6 +47,12 @@  enum pmdhealth_check {
     PMD_HC_COMPLETE
 };
 
+enum port_health_check {
+    PORT_LINK_CHECK = 0,
+    PORT_STATS_CHECK,
+    PORT_NUM_CHECKS
+};
+
 struct ka_process_info {
     char name[16];
     int tid;
@@ -60,10 +66,12 @@  struct ka_process_info {
 
 struct poll_port_stats {
     const char *port;
-    int qid;
+    char *link_state;
+    int state[PORT_NUM_CHECKS];
 };
 
 struct pmd_extended_stats {
+    char *health_status;
     struct poll_port_stats *port_stats;
     int num_poll_ports;
 };
@@ -92,6 +100,11 @@  enum keepalive_status {
     ka_init_success
 };
 
+enum pmdhealth_status {
+    FAILURE_STATE = 0,
+    ACTIVE_RUN_STATE
+};
+
 void ka_init(const struct smap *);
 void ka_destroy(void);
 void ka_set_pmd_state_ts(unsigned, enum keepalive_state, uint64_t);
@@ -120,4 +133,7 @@  struct smap *ka_stats_run(void);
 void ka_load_process_list(struct hmap **);
 
 void dispatch_heartbeats(void);
+void ka_info_update_port_status(const char *,int,char *,int,int);
+enum pmdhealth_status ka_get_polled_ports_status(unsigned);
+
 #endif /* keepalive.h */