diff --git a/datapath-windows/include/OvsDpInterfaceCtExt.h b/datapath-windows/include/OvsDpInterfaceCtExt.h
index 3b94778..45e7ff8 100644
--- a/datapath-windows/include/OvsDpInterfaceCtExt.h
+++ b/datapath-windows/include/OvsDpInterfaceCtExt.h
@@ -154,6 +154,7 @@ enum cntl_msg_types {
     IPCTNL_MSG_CT_GET_STATS,
     IPCTNL_MSG_CT_GET_DYING,
     IPCTNL_MSG_CT_GET_UNCONFIRMED,
+    IPCTNL_MSG_CT_UPDATE,
     IPCTNL_MSG_MAX
 };
 
diff --git a/datapath-windows/ovsext/Conntrack.c b/datapath-windows/ovsext/Conntrack.c
index 68ed395..ab53993 100644
--- a/datapath-windows/ovsext/Conntrack.c
+++ b/datapath-windows/ovsext/Conntrack.c
@@ -698,9 +698,11 @@ OvsCtExecute_(OvsForwardingContext *fwdCtx,
               MD_MARK *mark,
               MD_LABELS *labels,
               PCHAR helper,
-              PNAT_ACTION_INFO natInfo)
+              PNAT_ACTION_INFO natInfo,
+              BOOLEAN postUpdateEvent)
 {
     NDIS_STATUS status = NDIS_STATUS_SUCCESS;
+    BOOLEAN sendUpdateEvent = FALSE;
     POVS_CT_ENTRY entry = NULL;
     PNET_BUFFER_LIST curNbl = fwdCtx->curNbl;
     OvsConntrackKeyLookupCtx ctx = { 0 };
@@ -752,10 +754,16 @@ OvsCtExecute_(OvsForwardingContext *fwdCtx,
     }
 
     if (entry && mark) {
+        if (!entryCreated) {
+            sendUpdateEvent = TRUE;
+        }
         OvsConntrackSetMark(key, entry, mark->value, mark->mask);
     }
 
     if (entry && labels) {
+        if (!entryCreated) {
+            sendUpdateEvent = TRUE;
+        }
         OvsConntrackSetLabels(key, entry, &labels->value, &labels->mask);
     }
 
@@ -790,6 +798,9 @@ OvsCtExecute_(OvsForwardingContext *fwdCtx,
     if (entryCreated && entry) {
         OvsPostCtEventEntry(entry, OVS_EVENT_CT_NEW);
     }
+    if (postUpdateEvent && sendUpdateEvent) {
+        OvsPostCtEventEntry(entry, OVS_EVENT_CT_UPDATE);
+    }
 
     NdisReleaseRWLock(ovsConntrackLockObj, &lockState);
 
@@ -811,7 +822,9 @@ OvsExecuteConntrackAction(OvsForwardingContext *fwdCtx,
     PNL_ATTR ctAttr;
     BOOLEAN commit = FALSE;
     BOOLEAN force = FALSE;
+    BOOLEAN postUpdateEvent = FALSE;
     UINT16 zone = 0;
+    UINT32 eventmask = 0;
     MD_MARK *mark = NULL;
     MD_LABELS *labels = NULL;
     PCHAR helper = NULL;
@@ -932,9 +945,17 @@ OvsExecuteConntrackAction(OvsForwardingContext *fwdCtx,
         /* Force implicitly means commit */
         commit = TRUE;
     }
+    ctAttr = NlAttrFindNested(a, OVS_CT_ATTR_EVENTMASK);
+    if (ctAttr) {
+        eventmask = NlAttrGetU32(ctAttr);
+        /* Only mark and label updates are supported. */
+        if (eventmask & (1 << IPCT_MARK | 1 << IPCT_LABEL))
+            postUpdateEvent = TRUE;
+    }
     /* If newNbl is not allocated, use the current Nbl*/
     status = OvsCtExecute_(fwdCtx, key, layers,
-                           commit, force, zone, mark, labels, helper, &natActionInfo);
+                           commit, force, zone, mark, labels, helper, &natActionInfo,
+                           postUpdateEvent);
     return status;
 }
 
@@ -1290,6 +1311,8 @@ OvsCreateNlMsgFromCtEntry(POVS_CT_ENTRY entry,
         nlmsgType = (UINT16) (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_CT_NEW);
     } else if (eventType == OVS_EVENT_CT_DELETE) {
         nlmsgType = (UINT16) (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_CT_DELETE);
+    } else if (eventType == OVS_EVENT_CT_UPDATE) {
+        nlmsgType = (UINT16) (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_CT_UPDATE);
     } else {
         return STATUS_INVALID_PARAMETER;
     }
diff --git a/datapath-windows/ovsext/Datapath.c b/datapath-windows/ovsext/Datapath.c
index 83d996e..10412a1 100644
--- a/datapath-windows/ovsext/Datapath.c
+++ b/datapath-windows/ovsext/Datapath.c
@@ -1312,6 +1312,9 @@ OvsSubscribeEventCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
         if (mcastGrp == NFNLGRP_CONNTRACK_DESTROY) {
             request.mask = OVS_EVENT_CT_DELETE;
         }
+        if (mcastGrp == NFNLGRP_CONNTRACK_UPDATE) {
+            request.mask = OVS_EVENT_CT_UPDATE;
+        }
     }
 
     status = OvsSubscribeEventIoctl(instance->fileObject, &request,
diff --git a/datapath-windows/ovsext/DpInternal.h b/datapath-windows/ovsext/DpInternal.h
index 743891c..3e351b7 100644
--- a/datapath-windows/ovsext/DpInternal.h
+++ b/datapath-windows/ovsext/DpInternal.h
@@ -336,7 +336,8 @@ enum {
 enum {
     OVS_EVENT_CT_NEW        = (1 << 0),
     OVS_EVENT_CT_DELETE     = (1 << 1),
-    OVS_EVENT_CT_MASK_ALL   = 0x3
+    OVS_EVENT_CT_UPDATE     = (1 << 2),
+    OVS_EVENT_CT_MASK_ALL   = 0x7
 };
 
 /* Supported mcast event groups */
diff --git a/datapath-windows/ovsext/Event.c b/datapath-windows/ovsext/Event.c
index cb0dc92..2b54692 100644
--- a/datapath-windows/ovsext/Event.c
+++ b/datapath-windows/ovsext/Event.c
@@ -71,7 +71,8 @@ OvsGetMcastEventId(UINT32 protocol, UINT32 mcastMask, UINT32 *eventId)
         return NDIS_STATUS_SUCCESS;
     case NETLINK_NETFILTER:
         if ((mcastMask & OVS_EVENT_CT_NEW)
-            || (mcastMask & OVS_EVENT_CT_DELETE)) {
+            || (mcastMask & OVS_EVENT_CT_DELETE)
+            || (mcastMask & OVS_EVENT_CT_UPDATE)) {
             *eventId =  OVS_MCAST_CT_EVENT;
             return NDIS_STATUS_SUCCESS;
         }
diff --git a/lib/netlink-conntrack.c b/lib/netlink-conntrack.c
index f0e2aea..e976fb3 100644
--- a/lib/netlink-conntrack.c
+++ b/lib/netlink-conntrack.c
@@ -728,6 +728,9 @@ nl_ct_parse_header_policy(struct ofpbuf *buf,
     case IPCTNL_MSG_CT_DELETE:
         *event_type = NL_CT_EVENT_DELETE;
         break;
+    case IPCTNL_MSG_CT_UPDATE:
+        *event_type = NL_CT_EVENT_UPDATE;
+        break;
     default:
         VLOG_ERR_RL(&rl, "Can't parse conntrack event type.");
         return false;
