diff --git a/src/pae/ieee802_1x_cp.c b/src/pae/ieee802_1x_cp.c
index 360fcd3f5..e6b2767e2 100644
--- a/src/pae/ieee802_1x_cp.c
+++ b/src/pae/ieee802_1x_cp.c
@@ -126,7 +126,6 @@ SM_STATE(CP, INIT)
        sm->otx = FALSE;
        sm->orx = FALSE;

-       sm->port_enabled = TRUE;
        sm->chgd_server = FALSE;
 }

@@ -448,6 +447,7 @@ struct ieee802_1x_cp_sm * ieee802_1x_cp_sm_init(struct ieee802_1x_kay *kay)
        sm->replay_window = kay->macsec_replay_window;

        sm->controlled_port_enabled = FALSE;
+       sm->port_enabled = TRUE;

        sm->lki = NULL;
        sm->lrx = FALSE;
@@ -693,6 +693,17 @@ void ieee802_1x_cp_set_usingtransmitas(void *cp_ctx, Boolean status)


 /**
+ * ieee802_1x_cp_set_portenabled -
+ * @status: indicates MAC_Operational status of the common port
+ */
+void ieee802_1x_cp_set_portenabled(void *cp_ctx, Boolean status)
+{
+       struct ieee802_1x_cp_sm *sm = cp_ctx;
+       sm->port_enabled = status;
+}
+
+
+/**
  * ieee802_1x_cp_sm_step - Advance EAPOL state machines
  * @sm: EAPOL state machine
  *
diff --git a/src/pae/ieee802_1x_cp.h b/src/pae/ieee802_1x_cp.h
index 695629e5c..0d5358666 100644
--- a/src/pae/ieee802_1x_cp.h
+++ b/src/pae/ieee802_1x_cp.h
@@ -36,5 +36,6 @@ void ieee802_1x_cp_set_usingreceivesas(void *cp_ctx, Boolean status);
 void ieee802_1x_cp_set_allreceiving(void *cp_ctx, Boolean status);
 void ieee802_1x_cp_set_servertransmitting(void *cp_ctx, Boolean status);
 void ieee802_1x_cp_set_usingtransmitas(void *cp_ctx, Boolean status);
+void ieee802_1x_cp_set_portenabled(void *cp_ctx, Boolean status);

 #endif /* IEEE802_1X_CP_H */
diff --git a/src/pae/ieee802_1x_kay.c b/src/pae/ieee802_1x_kay.c
index fd329e610..17519ae69 100644
--- a/src/pae/ieee802_1x_kay.c
+++ b/src/pae/ieee802_1x_kay.c
@@ -772,6 +772,11 @@ ieee802_1x_mka_decode_basic_body(struct ieee802_1x_kay *kay, const u8 *mka_msg,
                return NULL;
        }

+       if (!participant->participant) {
+               wpa_printf(MSG_MSGDUMP, "KaY: MKA participation disabled");
+               return NULL;
+       }
+
        /* If the peer's MI is my MI, I will choose new MI */
        if (os_memcmp(body->actor_mi, participant->mi, MI_LEN) == 0) {
                if (!reset_participant_mi(participant))
@@ -1240,7 +1245,6 @@ ieee802_1x_mka_encode_sak_use_body(
        /* set CP's variable */
        if (body->ltx) {
                kay->tx_enable = TRUE;
-               kay->port_enable = TRUE;
        }
        if (body->lrx)
                kay->rx_enable = TRUE;
@@ -2329,6 +2333,28 @@ static void ieee802_1x_delete_transmit_sa(struct ieee802_1x_kay *kay,


 /**
+ * ieee802_1x_kay_recalc_mka_active -
+ */
+static void
+ieee802_1x_kay_recalc_mka_active(struct ieee802_1x_kay *kay)
+{
+       struct ieee802_1x_mka_participant *participant;
+       Boolean active = FALSE;
+
+       /* Recalculate KaY active (ieee8021XKayMkaActive) */
+       dl_list_for_each(participant, &kay->participant_list,
+                        struct ieee802_1x_mka_participant, list) {
+               if (participant->active) {
+                       active = TRUE;
+                       break;
+               }
+       }
+
+       kay->active = active;
+}
+
+
+/**
  * ieee802_1x_participant_timer -
  */
 static void ieee802_1x_participant_timer(void *eloop_ctx, void *timeout_ctx)
@@ -2338,6 +2364,7 @@ static void ieee802_1x_participant_timer(void *eloop_ctx, void *timeout_ctx)
        struct ieee802_1x_kay_peer *peer, *pre_peer;
        time_t now = time(NULL);
        Boolean lp_changed;
+       Boolean participate;
        struct receive_sc *rxsc, *pre_rxsc;
        struct transmit_sa *txsa, *pre_txsa;

@@ -2348,6 +2375,10 @@ static void ieee802_1x_participant_timer(void *eloop_ctx, void *timeout_ctx)
                        goto delete_mka;
        }

+       /* only participate in MKA (i.e., transmit MKPDUs) if port
+        * is enabled and participant has not been disabled */
+       participate = kay->port_enable && participant->participant;
+
        /* should delete MKA instance if there are not live peers
         * when the MKA life elapsed since its creating */
        if (participant->mka_life) {
@@ -2362,7 +2393,7 @@ static void ieee802_1x_participant_timer(void *eloop_ctx, void *timeout_ctx)
        lp_changed = FALSE;
        dl_list_for_each_safe(peer, pre_peer, &participant->live_peers,
                              struct ieee802_1x_kay_peer, list) {
-               if (now > peer->expire) {
+               if (!participate || (now > peer->expire)) {
                        wpa_printf(MSG_DEBUG, "KaY: Live peer removed");
                        wpa_hexdump(MSG_DEBUG, "\tMI: ", peer->mi,
                                    sizeof(peer->mi));
@@ -2420,7 +2451,7 @@ static void ieee802_1x_participant_timer(void *eloop_ctx, void *timeout_ctx)

        dl_list_for_each_safe(peer, pre_peer, &participant->potential_peers,
                              struct ieee802_1x_kay_peer, list) {
-               if (now > peer->expire) {
+               if (!participate || (now > peer->expire)) {
                        wpa_printf(MSG_DEBUG, "KaY: Potential peer removed");
                        wpa_hexdump(MSG_DEBUG, "\tMI: ", peer->mi,
                                    sizeof(peer->mi));
@@ -2430,6 +2461,12 @@ static void ieee802_1x_participant_timer(void *eloop_ctx, void *timeout_ctx)
                }
        }

+       if (!participate) {
+               participant->active = FALSE;
+               ieee802_1x_kay_recalc_mka_active(kay);
+               return;
+       }
+
        if (participant->new_sak) {
                if (!ieee802_1x_kay_generate_new_sak(participant))
                        participant->to_dist_sak = TRUE;
@@ -2836,7 +2873,7 @@ int ieee802_1x_kay_enable_new_info(struct ieee802_1x_kay *kay)
        struct ieee802_1x_mka_participant *principal;

        principal = ieee802_1x_kay_get_principal_participant(kay);
-       if (!principal)
+       if (!principal || !principal->participant)
                return -1;

        if (principal->retry_count < MAX_RETRY_CNT || principal->mode == PSK) {
@@ -3321,7 +3358,7 @@ ieee802_1x_kay_create_mka(struct ieee802_1x_kay *kay, struct mka_key_name *ckn,
        participant->cached = FALSE;

        participant->active = FALSE;
-       participant->participant = FALSE;
+       participant->participant = TRUE;
        participant->retain = FALSE;
        participant->activate = DEFAULT;

@@ -3465,6 +3502,8 @@ ieee802_1x_kay_delete_mka(struct ieee802_1x_kay *kay, struct mka_key_name *ckn)
        os_memset(&participant->kek, 0, sizeof(participant->kek));
        os_memset(&participant->ick, 0, sizeof(participant->ick));
        os_free(participant);
+
+       ieee802_1x_kay_recalc_mka_active(kay);
 }


@@ -3484,7 +3523,57 @@ void ieee802_1x_kay_mka_participate(struct ieee802_1x_kay *kay,
        if (!participant)
                return;

-       participant->active = status;
+       if (participant->participant == status)
+               return;
+
+       participant->participant = status;
+
+       if (status) {
+               /* Restart timer immediately if both port and participant are enabled */
+               if (kay->port_enable) {
+                       eloop_register_timeout(0, 0, ieee802_1x_participant_timer,
+                                              participant, NULL);
+               }
+       } else {
+               participant->active = FALSE;
+               ieee802_1x_kay_recalc_mka_active(kay);
+       }
+}
+
+
+/**
+ * ieee802_1x_kay_notify_port_enabled -
+ */
+void ieee802_1x_kay_notify_port_enabled(struct ieee802_1x_kay *kay,
+                                       Boolean enabled)
+{
+       struct ieee802_1x_mka_participant *participant;
+       unsigned int usecs;
+
+       if (kay->port_enable == enabled)
+               return;
+
+       wpa_printf(MSG_DEBUG, "KaY: External notification - "
+                  "portEnabled=%d", enabled);
+
+       kay->port_enable = enabled;
+
+       ieee802_1x_cp_set_portenabled(kay->cp, enabled);
+
+       if (!enabled) {
+               /* Existing participants will be cleaned up next time their timers expire */
+               kay->active = FALSE;
+       } else {
+               /* Staggered restart of participant timers */
+               dl_list_for_each(participant, &kay->participant_list,
+                                struct ieee802_1x_mka_participant, list) {
+                       if (participant->participant) {
+                               usecs = os_random() % (MKA_HELLO_TIME * 1000);
+                               eloop_register_timeout(0, usecs, ieee802_1x_participant_timer,
+                                                      participant, NULL);
+                       }
+               }
+       }
 }


@@ -3575,6 +3664,7 @@ int ieee802_1x_kay_get_status(struct ieee802_1x_kay *kay, char *buf,
                return 0;

        len = os_snprintf(buf, buflen,
+                         "Port status=%s\n"
                          "PAE KaY status=%s\n"
                          "Authenticated=%s\n"
                          "Secured=%s\n"
@@ -3584,6 +3674,7 @@ int ieee802_1x_kay_get_status(struct ieee802_1x_kay *kay, char *buf,
                          "Is Key Server=%s\n"
                          "Number of Keys Distributed=%u\n"
                          "Number of Keys Received=%u\n",
+                         kay->port_enable ? "Enabled" : "Disabled",
                          kay->active ? "Active" : "Not-Active",
                          kay->authenticated ? "Yes" : "No",
                          kay->secured ? "Yes" : "No",
diff --git a/src/pae/ieee802_1x_kay.h b/src/pae/ieee802_1x_kay.h
index 8f394fd96..8c1a3b2fa 100644
--- a/src/pae/ieee802_1x_kay.h
+++ b/src/pae/ieee802_1x_kay.h
@@ -249,6 +249,8 @@ void ieee802_1x_kay_delete_mka(struct ieee802_1x_kay *kay,
 void ieee802_1x_kay_mka_participate(struct ieee802_1x_kay *kay,
                                    struct mka_key_name *ckn,
                                    Boolean status);
+void ieee802_1x_kay_notify_port_enabled(struct ieee802_1x_kay *kay,
+                                       Boolean enabled);
 int ieee802_1x_kay_new_sak(struct ieee802_1x_kay *kay);
 int ieee802_1x_kay_change_cipher_suite(struct ieee802_1x_kay *kay,
                                       unsigned int cs_index);
diff --git a/src/pae/ieee802_1x_kay_i.h b/src/pae/ieee802_1x_kay_i.h
index bc522d898..c10851d2d 100644
--- a/src/pae/ieee802_1x_kay_i.h
+++ b/src/pae/ieee802_1x_kay_i.h
@@ -90,8 +90,8 @@ struct ieee802_1x_mka_participant {
        Boolean cached;

        /* used by management to monitor and control activation */
-       Boolean active;
-       Boolean participant;
+       Boolean active;      /* used to calculate ieee8021XKayMkaActive (IEEE8021X-PAE-MIB) */
+       Boolean participant; /* MKA.participate, from IEEE802.1X-2010, Clause 12.2 */
        Boolean retain;
        enum mka_created_mode mode;

