Skip to content

Commit

Permalink
ofproto-dpif-xlate: Fix treatment of mirrors across patch port.
Browse files Browse the repository at this point in the history
When the bridges on both sides of a patch port included mirrors, the
translation code incorrectly conflated them instead of treating them as
independent.

Reported-by: Zoltán Balogh <[email protected]>
Reported-by: Sugesh Chandran <[email protected]>
Reported-at: http://openvswitch.org/pipermail/discuss/2016-September/022689.html
Signed-off-by: Ben Pfaff <[email protected]>
Tested-by: Zoltán Balogh <[email protected]>
Signed-off-by: Ben Pfaff <[email protected]>
  • Loading branch information
blp committed Sep 16, 2016
1 parent 53cc166 commit 76f3c26
Showing 1 changed file with 25 additions and 3 deletions.
28 changes: 25 additions & 3 deletions ofproto/ofproto-dpif-xlate.c
Original file line number Diff line number Diff line change
Expand Up @@ -2911,7 +2911,6 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,

ofpbuf_use_stub(&ctx->stack, new_stack, sizeof new_stack);
ofpbuf_use_stub(&ctx->action_set, actset_stub, sizeof actset_stub);
ctx->xbridge = peer->xbridge;
flow->in_port.ofp_port = peer->ofp_port;
flow->metadata = htonll(0);
memset(&flow->tunnel, 0, sizeof flow->tunnel);
Expand All @@ -2920,6 +2919,26 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
ctx->conntracked = false;
clear_conntrack(flow);

/* When the patch port points to a different bridge, then the mirrors
* for that bridge clearly apply independently to the packet, so we
* reset the mirror bitmap to zero and then restore it after the packet
* returns.
*
* When the patch port points to the same bridge, this is more of a
* design decision: can mirrors be re-applied to the packet after it
* re-enters the bridge, or should we treat that as doubly mirroring a
* single packet? The former may be cleaner, since it respects the
* model in which a patch port is like a physical cable plugged from
* one switch port to another, but the latter may be less surprising to
* users. We take the latter choice, for now at least. (To use the
* former choice, hard-code 'independent_mirrors' to "true".) */
mirror_mask_t old_mirrors = ctx->mirrors;
bool independent_mirrors = peer->xbridge != ctx->xbridge;
if (independent_mirrors) {
ctx->mirrors = 0;
}
ctx->xbridge = peer->xbridge;

/* The bridge is now known so obtain its table version. */
ctx->xin->tables_version
= ofproto_dpif_get_tables_version(ctx->xbridge->ofproto);
Expand All @@ -2938,10 +2957,10 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
* the learning action look at the packet, then drop it. */
struct flow old_base_flow = ctx->base_flow;
size_t old_size = ctx->odp_actions->size;
mirror_mask_t old_mirrors = ctx->mirrors;
mirror_mask_t old_mirrors2 = ctx->mirrors;

xlate_table_action(ctx, flow->in_port.ofp_port, 0, true, true);
ctx->mirrors = old_mirrors;
ctx->mirrors = old_mirrors2;
ctx->base_flow = old_base_flow;
ctx->odp_actions->size = old_size;

Expand All @@ -2950,6 +2969,9 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
}
}

if (independent_mirrors) {
ctx->mirrors = old_mirrors;
}
ctx->xin->flow = old_flow;
ctx->xbridge = xport->xbridge;
ofpbuf_uninit(&ctx->action_set);
Expand Down

0 comments on commit 76f3c26

Please sign in to comment.