diff mbox

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

Message ID 1497813871-27572-14-git-send-email-bhanuprakash.bodireddy@intel.com
State RFC
Headers show

Commit Message

Bodireddy, Bhanuprakash June 18, 2017, 7:24 p.m. UTC
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(-)
diff mbox

Patch

diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index 06d2e23..4d8d3e7 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -51,6 +51,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"
@@ -972,9 +973,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 997bebf..9251849 100644
--- a/lib/keepalive.c
+++ b/lib/keepalive.c
@@ -428,6 +428,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 8877ca6..69697bd 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);
@@ -121,4 +134,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 */