diff --git a/include/openvswitch/flow.h b/include/openvswitch/flow.h
index 5d2cf09680f1..18e8b7df0a29 100644
--- a/include/openvswitch/flow.h
+++ b/include/openvswitch/flow.h
@@ -225,6 +225,9 @@ void flow_wildcards_and(struct flow_wildcards *dst,
 void flow_wildcards_or(struct flow_wildcards *dst,
                        const struct flow_wildcards *src1,
                        const struct flow_wildcards *src2);
+void flow_wildcards_xor(struct flow_wildcards *dst,
+                        const struct flow_wildcards *src1,
+                        const struct flow_wildcards *src2);
 bool flow_wildcards_has_extra(const struct flow_wildcards *,
                               const struct flow_wildcards *);
 uint32_t flow_wildcards_hash(const struct flow_wildcards *, uint32_t basis);
diff --git a/lib/flow.c b/lib/flow.c
index bffee70ab55b..398fbf01bd73 100644
--- a/lib/flow.c
+++ b/lib/flow.c
@@ -2015,6 +2015,25 @@ flow_wildcards_or(struct flow_wildcards *dst,
     }
 }
 
+/* Sets 'dst' as the bitwise XOR of wildcards in 'src1' and 'src2'.
+ * That is, a bit or a field is wildcarded in 'dst' if it is wildcarded
+ * in 'src1' or 'src2', but not both. This is primarily useful for
+ * diffing two sets of wildcards. */
+void
+flow_wildcards_xor(struct flow_wildcards *dst,
+                  const struct flow_wildcards *src1,
+                  const struct flow_wildcards *src2)
+{
+    uint64_t *dst_u64 = (uint64_t *) &dst->masks;
+    const uint64_t *src1_u64 = (const uint64_t *) &src1->masks;
+    const uint64_t *src2_u64 = (const uint64_t *) &src2->masks;
+    size_t i;
+
+    for (i = 0; i < FLOW_U64S; i++) {
+        dst_u64[i] = src1_u64[i] ^ src2_u64[i];
+    }
+}
+
 /* Returns a hash of the wildcards in 'wc'. */
 uint32_t
 flow_wildcards_hash(const struct flow_wildcards *wc, uint32_t basis)
diff --git a/ofproto/ofproto-dpif-trace.c b/ofproto/ofproto-dpif-trace.c
index eca61cee250d..f17fabc884e8 100644
--- a/ofproto/ofproto-dpif-trace.c
+++ b/ofproto/ofproto-dpif-trace.c
@@ -652,6 +652,9 @@ ofproto_trace__(struct ofproto_dpif *ofproto, const struct flow *flow,
     struct ofpbuf odp_actions;
     ofpbuf_init(&odp_actions, 0);
 
+    struct flow_wildcards trace_prev_wc;
+    memset(&trace_prev_wc, 0, sizeof trace_prev_wc);
+
     struct xlate_in xin;
     struct flow_wildcards wc;
     struct ovs_list trace = OVS_LIST_INITIALIZER(&trace);
@@ -662,6 +665,7 @@ ofproto_trace__(struct ofproto_dpif *ofproto, const struct flow *flow,
     xin.ofpacts = ofpacts;
     xin.ofpacts_len = ofpacts_len;
     xin.trace = &trace;
+    xin.trace_prev_wc = &trace_prev_wc;
     xin.recirc_queue = recirc_queue;
 
     /* Copy initial flow out of xin.flow.  It differs from '*flow' because
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index 84cce811bd1c..12cb4d0d0fc2 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -34,6 +34,7 @@
 #include "csum.h"
 #include "dp-packet.h"
 #include "dpif.h"
+#include "flow.h"
 #include "in-band.h"
 #include "lacp.h"
 #include "learn.h"
@@ -793,6 +794,22 @@ xlate_report_table(const struct xlate_ctx *ctx, struct rule_dpif *rule,
     }
 
     struct ds s = DS_EMPTY_INITIALIZER;
+
+    if (ctx->wc && ctx->xin->trace_prev_wc) {
+        if (!flow_equal(&ctx->wc->masks, &ctx->xin->trace_prev_wc->masks)) {
+            struct flow_wildcards new_wc;
+            flow_wildcards_xor(&new_wc, ctx->wc, ctx->xin->trace_prev_wc);
+            ds_put_cstr(&s, "    xxx New wildcards: ");
+
+            struct match match;
+            match_init(&match, &ctx->xin->flow, &new_wc);
+            memset(&match.wc.masks.tunnel, '\0', sizeof match.wc.masks.tunnel);
+            match_format(&match, NULL, &s, OFP_DEFAULT_PRIORITY);
+            ds_put_cstr(&s, "\n");
+
+            *ctx->xin->trace_prev_wc = *ctx->wc;
+        }
+    }
     ds_put_format(&s, "%2d. ", table_id);
     if (rule == ctx->xin->ofproto->miss_rule) {
         ds_put_cstr(&s, "No match, and a \"packet-in\" is called for.");
@@ -6808,6 +6825,7 @@ xlate_in_init(struct xlate_in *xin, struct ofproto_dpif *ofproto,
     xin->ofpacts_len = 0;
     xin->tcp_flags = tcp_flags;
     xin->trace = NULL;
+    xin->trace_prev_wc = NULL;
     xin->resubmit_stats = NULL;
     xin->depth = 0;
     xin->resubmits = 0;
diff --git a/ofproto/ofproto-dpif-xlate.h b/ofproto/ofproto-dpif-xlate.h
index 0a5a52887b80..e3f6df713e96 100644
--- a/ofproto/ofproto-dpif-xlate.h
+++ b/ofproto/ofproto-dpif-xlate.h
@@ -107,6 +107,9 @@ struct xlate_in {
      * translation should add tracing information (with oftrace_report()). */
     struct ovs_list *trace;
 
+    /* xxx Explain. */
+    struct flow_wildcards *trace_prev_wc;
+
     /* If nonnull, flow translation credits the specified statistics to each
      * rule reached through a resubmit or OFPP_TABLE action.
      *
