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 */
