Skip to content

Commit

Permalink
ofproto-dpif-xlate: Correctly decide whether truncating.
Browse files Browse the repository at this point in the history
xlate_output_action() must tell some of the functions it calls whether the
packet is being truncated.  Until now, it has inferred that based on
whether its max_len argument is nonzero.

Unfortunately, max_len conflates two different purposes.  Historically it
was used only to limit the number of bytes of packets sent to an OpenFlow
controller in packet_in messages.  When packet truncation was introduced,
it was then also used to specify the truncation length.  This meant that,
for example, when xlate_output_reg_action() called into
xlate_output_action() passing along for max_len an OpenFlow controller byte
limit (which ovs-ofctl by default sets to 65535), xlate_output_action()
interpreted that as a truncation request and told the functions it called
that the packet was being truncated, which in the worst case led to
assertion failures.

This commit disentangles these two meaning of max_len, separating them into
two separate parameters, and updates the callers.

Reported-by: Kevin Lin <kevin@kelda.io>
Reported-at: https://mail.openvswitch.org/pipermail/ovs-discuss/2017-December/045841.html
Tested-by: Kevin Lin <kevin@kelda.io>
Signed-off-by: Ben Pfaff <blp@ovn.org>
  • Loading branch information
blp committed Dec 8, 2017
1 parent 391ce80 commit 8b496c7
Showing 1 changed file with 27 additions and 11 deletions.
38 changes: 27 additions & 11 deletions ofproto/ofproto-dpif-xlate.c
Expand Up @@ -4825,13 +4825,27 @@ compose_dec_mpls_ttl_action(struct xlate_ctx *ctx)
return true;
}

/* Emits an action that outputs to 'port', within 'ctx'.
*
* 'controller_len' affects only packets sent to an OpenFlow controller. It
* is the maximum number of bytes of the packet to send. UINT16_MAX means to
* send the whole packet (and 0 means to omit the packet entirely).
*
* 'may_packet_in' determines whether the packet may be sent to an OpenFlow
* controller. If it is false, then the packet is never sent to the OpenFlow
* controller.
*
* 'is_last_action' should be true if this output is the last OpenFlow action
* to be processed, which enables certain optimizations.
*
* 'truncate' should be true if the packet to be output is being truncated,
* which suppresses certain optimizations. */
static void
xlate_output_action(struct xlate_ctx *ctx,
ofp_port_t port, uint16_t max_len, bool may_packet_in,
bool is_last_action)
xlate_output_action(struct xlate_ctx *ctx, ofp_port_t port,
uint16_t controller_len, bool may_packet_in,
bool is_last_action, bool truncate)
{
ofp_port_t prev_nf_output_iface = ctx->nf_output_iface;
bool truncate = max_len != 0;

ctx->nf_output_iface = NF_OUT_DROP;

Expand All @@ -4855,7 +4869,7 @@ xlate_output_action(struct xlate_ctx *ctx,
flood_packets(ctx, true, is_last_action);
break;
case OFPP_CONTROLLER:
execute_controller_action(ctx, max_len,
execute_controller_action(ctx, controller_len,
(ctx->in_packet_out ? OFPR_PACKET_OUT
: ctx->in_group ? OFPR_GROUP
: ctx->in_action_set ? OFPR_ACTION_SET
Expand Down Expand Up @@ -4897,8 +4911,8 @@ xlate_output_reg_action(struct xlate_ctx *ctx,

memset(&value, 0xff, sizeof value);
mf_write_subfield_flow(&or->src, &value, &ctx->wc->masks);
xlate_output_action(ctx, u16_to_ofp(port), or->max_len, false,
is_last_action);
xlate_output_action(ctx, u16_to_ofp(port), or->max_len,
false, is_last_action, false);
} else {
xlate_report(ctx, OFT_WARN, "output port %"PRIu64" is out of range",
port);
Expand Down Expand Up @@ -4945,7 +4959,7 @@ xlate_output_trunc_action(struct xlate_ctx *ctx,
OVS_ACTION_ATTR_TRUNC,
sizeof *trunc);
trunc->max_len = max_len;
xlate_output_action(ctx, port, max_len, false, is_last_action);
xlate_output_action(ctx, port, 0, false, is_last_action, true);
if (!support_trunc) {
ctx->xout->slow |= SLOW_ACTION;
}
Expand All @@ -4970,7 +4984,8 @@ xlate_enqueue_action(struct xlate_ctx *ctx,
error = dpif_queue_to_priority(ctx->xbridge->dpif, queue_id, &priority);
if (error) {
/* Fall back to ordinary output action. */
xlate_output_action(ctx, enqueue->port, 0, false, is_last_action);
xlate_output_action(ctx, enqueue->port, 0, false,
is_last_action, false);
return;
}

Expand Down Expand Up @@ -5043,7 +5058,7 @@ xlate_bundle_action(struct xlate_ctx *ctx,
nxm_reg_load(&bundle->dst, ofp_to_u16(port), &ctx->xin->flow, ctx->wc);
xlate_report_subfield(ctx, &bundle->dst);
} else {
xlate_output_action(ctx, port, 0, false, is_last_action);
xlate_output_action(ctx, port, 0, false, is_last_action, false);
}
}

Expand Down Expand Up @@ -6202,7 +6217,8 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
switch (a->type) {
case OFPACT_OUTPUT:
xlate_output_action(ctx, ofpact_get_OUTPUT(a)->port,
ofpact_get_OUTPUT(a)->max_len, true, last);
ofpact_get_OUTPUT(a)->max_len, true, last,
false);
break;

case OFPACT_GROUP:
Expand Down

0 comments on commit 8b496c7

Please sign in to comment.