ofproto-dpif-xlate: Account mirrored packets only if the VLAN matches.
Until now, OVS has accounted packets to mirrors even if the VLAN selection
criteria did not match.  This fixes the problem.
Acked-by: Justin Pettit
Tested-by: Shweta Seth
Reported-by: Shweta Seth
Reported-at:
@@ -2058,21 +2058,10 @@ mirror_packet(struct xlate_ctx *ctx, struct xbundle *xbundle,
return;
}
- if (ctx->xin->resubmit_stats) {
- mirror_update_stats(xbridge->mbridge, mirrors,
- ctx->xin->resubmit_stats->n_packets,
- ctx->xin->resubmit_stats->n_bytes);
- }
- if (ctx->xin->xcache) {
- struct xc_entry *entry;
-
- entry = xlate_cache_add_entry(ctx->xin->xcache, XC_MIRROR);
- entry->mirror.mbridge = mbridge_ref(xbridge->mbridge);
- entry->mirror.mirrors = mirrors;
- }
-
- /* 'mirrors' is a bit-mask of candidates for mirroring. Iterate as long as
- * some candidates remain. */
+ /* 'mirrors' is a bit-mask of candidates for mirroring. Iterate through
+ * the candidates, adding the ones that really should be mirrored to
+ * 'used_mirrors', as long as some candidates remain. */
+ mirror_mask_t used_mirrors = 0;
while (mirrors) {
const unsigned long *vlans;
mirror_mask_t dup_mirrors;
@@ -2096,6 +2085,9 @@ mirror_packet(struct xlate_ctx *ctx, struct xbundle *xbundle,
continue;
}
+ /* We sent a packet to this mirror. */
+ used_mirrors |= rightmost_1bit(mirrors);
+
/* Record the mirror, and the mirrors that output to the same
* destination, so that we don't mirror to them again. This must be
* done now to ensure that output_normal(), below, doesn't recursively
@@ -2129,6 +2121,21 @@ mirror_packet(struct xlate_ctx *ctx, struct xbundle *xbundle,
mirrors &= ~ctx->mirrors;
ctx->mirror_snaplen = 0;
}
+
+ if (used_mirrors) {
+ if (ctx->xin->resubmit_stats) {
+ mirror_update_stats(xbridge->mbridge, used_mirrors,
+ ctx->xin->resubmit_stats->n_packets,
+ ctx->xin->resubmit_stats->n_bytes);
+ }
+ if (ctx->xin->xcache) {
+ struct xc_entry *entry;
+
+ entry = xlate_cache_add_entry(ctx->xin->xcache, XC_MIRROR);
+ entry->mirror.mbridge = mbridge_ref(xbridge->mbridge);
+ entry->mirror.mirrors = used_mirrors;
+ }
+ }
}
static void
