diff mbox

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

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

Commit Message

Bodireddy, Bhanuprakash June 12, 2017, 4:49 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 SHM block.

Signed-off-by: Bhanuprakash Bodireddy <bhanuprakash.bodireddy@intel.com>
---
 lib/dpif-netdev.c | 42 ++++++++++++++++++++++++++++--
 lib/keepalive.c   | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/keepalive.h   | 33 ++++++++++++++++++++++++
 3 files changed, 150 insertions(+), 2 deletions(-)
diff mbox

Patch

diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index c40affe..32cdb9f 100644
--- a/lib/dpif-netdev.c
+++ b/lib/dpif-netdev.c
@@ -72,6 +72,7 @@ 
 #include "seq.h"
 #include "smap.h"
 #include "sset.h"
+#include "svec.h"
 #include "timeval.h"
 #include "tnl-neigh-cache.h"
 #include "tnl-ports.h"
@@ -971,9 +972,46 @@  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) {
+        HMAP_FOR_EACH (poll, node, &pmd->poll_list) {
+            if (!strcmp(port_name, netdev_rxq_get_name(poll->rxq->rx))) {
+                char *link_state;
+                link_state =
+                    netdev_get_carrier(poll->rxq->port->netdev) ? "up" : "down";
+
+                ka_shm_update_port_status(netdev_rxq_get_name(poll->rxq->rx),
+                                  netdev_rxq_get_queue_id(poll->rxq->rx),
+                                  link_state, pmd->core_id, i);
+                break;
+            }
+        }
+    }
+    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 a4a6a93..86d39db 100644
--- a/lib/keepalive.c
+++ b/lib/keepalive.c
@@ -188,6 +188,18 @@  ka_set_pmd_state_ts(unsigned core_id, enum keepalive_state state,
     ka_shm->core_last_seen_times[core_id] = last_alive;
 }
 
+inline int
+ka_get_pmd_state(unsigned core_id)
+{
+    struct keepalive_shm *ka_shm = get_ka_shm();
+    if (!ka_shm) {
+        VLOG_ERR_RL(&rl, "KeepAlive: Invalid shared memory block.");
+        return KA_STATE_UNUSED;
+    }
+
+    return ka_shm->core_state[core_id];
+}
+
 /* Retrieve and return the keepalive timer interval from OVSDB. */
 static uint32_t
 get_ka_timer_interval(const struct smap *ovs_other_config OVS_UNUSED)
@@ -350,6 +362,71 @@  ka_stats_run(void)
     return ka_stats;
 }
 
+enum pmdhealth_status ka_get_polled_ports_status(unsigned core_id)
+{
+    struct keepalive_shm *ka_shm = get_ka_shm();
+    if (!ka_shm) {
+        VLOG_ERR_RL(&rl, "KeepAlive: Invalid shared memory block.");
+        return -1;
+    }
+
+    int failed = 0;
+    int n_ports = ka_shm->ext_stats[core_id].num_poll_ports;
+    for (int i = 0; i < n_ports; i++) {
+        int state;
+        state =
+          ka_shm->ext_stats[core_id].port_stats[i].state[PORT_STATUS_CHECK];
+        if (state == FAILURE_STATE) {
+            failed = 1;
+            break;
+        }
+    }
+
+    if (!failed) {
+        return ACTIVE_RUN_STATE;
+    } else {
+        return FAILURE_STATE;
+    }
+}
+
+void
+ka_shm_update_port_status(const char *port, int qid, char *link_state,
+                          int core_id, int idx)
+{
+    struct keepalive_shm *ka_shm = get_ka_shm();
+    if (!ka_shm) {
+        VLOG_ERR_RL(&rl, "KeepAlive: Invalid shared memory block.");
+        return;
+    }
+
+    /* XXX */
+    if (idx >= MAX_POLL_PORTS) {
+        VLOG_ERR_RL(&rl, "KeepAlive: Max poll ports per PMD thread reached.");
+        return;
+    }
+
+    ka_shm->ext_stats[core_id].num_poll_ports = idx;
+
+    if (core_id != NON_PMD_CORE_ID) {
+        ka_shm->ext_stats[core_id].port_stats[idx].port = port;
+        ka_shm->ext_stats[core_id].port_stats[idx].qid = qid;
+        ka_shm->ext_stats[core_id].port_stats[idx].link_state =
+                                                           link_state;
+    } else {
+        VLOG_ERR_RL(&rl, "KeepAlive: Invalid pmd core_id.");
+    }
+
+    int state;
+    if (!strcmp(link_state, "down")) {
+        state = FAILURE_STATE;
+    } else {
+        state = ACTIVE_RUN_STATE;
+    }
+
+    ka_shm->ext_stats[core_id].port_stats[idx].state[PORT_STATUS_CHECK] =
+                                                               state;
+}
+
 static void
 ka_unixctl_pmd_health_show(struct unixctl_conn *conn, int argc OVS_UNUSED,
                        const char *argv[] OVS_UNUSED, void *ka_shm_)
diff --git a/lib/keepalive.h b/lib/keepalive.h
index a9991cf..e05e36c 100644
--- a/lib/keepalive.h
+++ b/lib/keepalive.h
@@ -25,6 +25,8 @@ 
 #define KEEPALIVE_MAXCORES 128
 #endif /* DPDK_NETDEV */
 
+#define MAX_POLL_PORTS 20
+
 struct smap;
 
 enum keepalive_state {
@@ -38,6 +40,25 @@  enum keepalive_state {
     KA_STATE_CHECK = 7
 };
 
+enum port_health_check {
+    PORT_STATUS_CHECK = 0,
+    PORT_STATS_CHECK,
+    PORT_NUM_CHECKS
+};
+
+struct poll_port_stats {
+    const char *port;
+    char *link_state;
+    int qid;
+    int state[PORT_NUM_CHECKS];
+};
+
+struct pmd_extended_stats {
+    char *health_status;
+    int num_poll_ports;
+    struct poll_port_stats port_stats[MAX_POLL_PORTS];
+};
+
 struct keepalive_shm {
     enum keepalive_state core_state[KEEPALIVE_MAXCORES];
 
@@ -46,6 +67,9 @@  struct keepalive_shm {
 
     /* Store pmd thread tid */
     pid_t thread_id[KEEPALIVE_MAXCORES];
+
+    /* Additional statistics to monitor health */
+    struct pmd_extended_stats ext_stats[KEEPALIVE_MAXCORES];
 };
 
 enum keepalive_status {
@@ -60,9 +84,15 @@  enum pmdhealth_check {
    PMD_HC_COMPLETE
 };
 
+enum pmdhealth_status {
+    FAILURE_STATE = 0,
+    ACTIVE_RUN_STATE
+};
+
 void ka_init(const struct smap *);
 struct keepalive_shm *get_ka_shm(void);
 void ka_set_pmd_state_ts(unsigned, enum keepalive_state, uint64_t);
+int ka_get_pmd_state(unsigned);
 
 void ka_register_pmd_thread(unsigned);
 void ka_unregister_pmd_thread(unsigned);
@@ -84,4 +114,7 @@  int get_ka_init_status(void);
 void get_ka_stats(void);
 struct smap *ka_stats_run(void);
 
+void ka_shm_update_port_status(const char *,int,char *,int,int);
+enum pmdhealth_status ka_get_polled_ports_status(unsigned);
+
 #endif /* keepalive.h */