[ovs-dev] [RFC PATCH 16/21] keepalive: Check the link status as part of PMD health checks.

Bhanuprakash Bodireddy bhanuprakash.bodireddy at intel.com
Wed Jun 7 16:15:12 UTC 2017


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 at intel.com>
---
 lib/dpif-netdev.c | 41 ++++++++++++++++++++++++++++--
 lib/keepalive.c   | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/keepalive.h   | 33 ++++++++++++++++++++++++
 3 files changed, 148 insertions(+), 2 deletions(-)

diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
index b2f0611..b7689e3 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,45 @@ 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);
+
+    if (port_link_status == ACTIVE_RUN_STATE) {
+        ka_set_pmd_state(pmd->core_id, KA_STATE_ALIVE);
+    } else {
+        ka_set_pmd_state(pmd->core_id, KA_STATE_CHECK);
+    }
 }
 
 static void
diff --git a/lib/keepalive.c b/lib/keepalive.c
index 9fa9ad9..d1858ac 100644
--- a/lib/keepalive.c
+++ b/lib/keepalive.c
@@ -148,6 +148,17 @@ ka_is_pmdhealth_check_needed(unsigned core_id)
     return ka_pmd_core_health[core_id];
 }
 
+void
+ka_set_pmd_state(unsigned core_id, enum keepalive_state state)
+{
+    struct keepalive_shm *ka_shm = get_ka_shm();
+    if (!ka_shm) {
+        VLOG_ERR_RL(&rl, "KeepAlive: Invalid shared memory block.");
+    }
+
+    ka_shm->core_state[core_id] = state;
+}
+
 /* Retrieve and return the keepalive timer interval from OVSDB. */
 static uint32_t
 get_ka_timer_interval(const struct smap *ovs_other_config OVS_UNUSED)
@@ -310,6 +321,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 32ea729..2de50f3 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 {
@@ -53,8 +77,14 @@ enum keepalive_status {
    ka_init_success
 };
 
+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(unsigned, enum keepalive_state);
 
 void ka_register_pmd_thread(unsigned);
 void ka_unregister_pmd_thread(unsigned);
@@ -71,4 +101,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 */
-- 
2.4.11



More information about the dev mailing list