* nothing if the connection is already committed will check that the current
  * packet is in conntrack entry's original direction.  If directionality does
  * not match, will delete the existing conntrack entry and commit a new one.
+ * @OVS_CT_ATTR_EVENTMASK: Mask of bits indicating which conntrack event types
+ * (enum ip_conntrack_events IPCT_*) should be reported.  For any bit set to
+ * zero, the corresponding event type is not generated.  Default behavior
+ * depends on system configuration, but typically all event types are
+ * generated, hence listening on NFNLGRP_CONNTRACK_UPDATE events may get a lot
+ * of events.  Explicitly passing this attribute allows limiting the updates
+ * received to the events of interest.  The bit 1 << IPCT_NEW, 1 <<
+ * IPCT_RELATED, and 1 << IPCT_DESTROY must be set to ones for those events to
+ * be received on NFNLGRP_CONNTRACK_NEW and NFNLGRP_CONNTRACK_DESTROY groups,
+ * respectively.  Remaining bits control the changes for which an event is
+ * delivered on the NFNLGRP_CONNTRACK_UPDATE group.
  */
 enum ovs_ct_attr {
        OVS_CT_ATTR_UNSPEC,
                                   related connections. */
        OVS_CT_ATTR_NAT,        /* Nested OVS_NAT_ATTR_* */
        OVS_CT_ATTR_FORCE_COMMIT,  /* No argument */
+       OVS_CT_ATTR_EVENTMASK,  /* u32 mask of IPCT_* events. */
        __OVS_CT_ATTR_MAX
 };
 
 
        u8 commit : 1;
        u8 nat : 3;                 /* enum ovs_ct_nat */
        u8 force : 1;
+       u8 have_eventmask : 1;
        u16 family;
+       u32 eventmask;              /* Mask of 1 << IPCT_*. */
        struct md_mark mark;
        struct md_labels labels;
 #ifdef CONFIG_NF_NAT_NEEDED
        if (!ct)
                return 0;
 
+       /* Set the conntrack event mask if given.  NEW and DELETE events have
+        * their own groups, but the NFNLGRP_CONNTRACK_UPDATE group listener
+        * typically would receive many kinds of updates.  Setting the event
+        * mask allows those events to be filtered.  The set event mask will
+        * remain in effect for the lifetime of the connection unless changed
+        * by a further CT action with both the commit flag and the eventmask
+        * option. */
+       if (info->have_eventmask) {
+               struct nf_conntrack_ecache *cache = nf_ct_ecache_find(ct);
+
+               if (cache)
+                       cache->ctmask = info->eventmask;
+       }
+
        /* Apply changes before confirming the connection so that the initial
         * conntrack NEW netlink event carries the values given in the CT
         * action.
        /* NAT length is checked when parsing the nested attributes. */
        [OVS_CT_ATTR_NAT]       = { .minlen = 0, .maxlen = INT_MAX },
 #endif
+       [OVS_CT_ATTR_EVENTMASK] = { .minlen = sizeof(u32),
+                                   .maxlen = sizeof(u32) },
 };
 
 static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info,
                        break;
                }
 #endif
+               case OVS_CT_ATTR_EVENTMASK:
+                       info->have_eventmask = true;
+                       info->eventmask = nla_get_u32(a);
+                       break;
+
                default:
                        OVS_NLERR(log, "Unknown conntrack attr (%d)",
                                  type);
                                   ct_info->helper->name))
                        return -EMSGSIZE;
        }
+       if (ct_info->have_eventmask &&
+           nla_put_u32(skb, OVS_CT_ATTR_EVENTMASK, ct_info->eventmask))
+               return -EMSGSIZE;
+
 #ifdef CONFIG_NF_NAT_NEEDED
        if (ct_info->nat && !ovs_ct_nat_to_attr(ct_info, skb))
                return -EMSGSIZE;