/*
- * Copyright (c) 2009, 2010, 2011, 2012 Nicira Networks.
+ * Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
uint16_t sflow_odp_port; /* Output port for composing sFlow action. */
uint16_t user_cookie_offset;/* Used for user_action_cookie fixup. */
bool exit; /* No further actions should be processed. */
+ struct flow orig_flow; /* Copy of original flow. */
};
static void action_xlate_ctx_init(struct action_xlate_ctx *,
struct hmap bundles; /* Contains "struct ofbundle"s. */
struct mac_learning *ml;
struct ofmirror *mirrors[MAX_MIRRORS];
+ bool has_mirrors;
bool has_bonded_bundles;
/* Expiration. */
ofproto_dpif_unixctl_init();
+ ofproto->has_mirrors = false;
ofproto->has_bundle_action = false;
hmap_init(&ofproto->vlandev_map);
}
ofproto->need_revalidate = true;
+ ofproto->has_mirrors = true;
mac_learning_flush(ofproto->ml, &ofproto->revalidate_set);
mirror_update_dups(ofproto);
struct ofproto_dpif *ofproto;
mirror_mask_t mirror_bit;
struct ofbundle *bundle;
+ int i;
if (!mirror) {
return;
free(mirror);
mirror_update_dups(ofproto);
+
+ ofproto->has_mirrors = false;
+ for (i = 0; i < MAX_MIRRORS; i++) {
+ if (ofproto->mirrors[i]) {
+ ofproto->has_mirrors = true;
+ break;
+ }
+ }
}
static int
const union ofp_action *in, size_t n_in,
struct ofpbuf *odp_actions)
{
- struct flow orig_flow = ctx->flow;
+ /* Normally false. Set to true if we ever hit MAX_RESUBMIT_RECURSION, so
+ * that in the future we always keep a copy of the original flow for
+ * tracing purposes. */
+ static bool hit_resubmit_limit;
COVERAGE_INC(ofproto_dpif_xlate);
ctx->table_id = 0;
ctx->exit = false;
+ if (ctx->ofproto->has_mirrors || hit_resubmit_limit) {
+ /* Do this conditionally because the copy is expensive enough that it
+ * shows up in profiles.
+ *
+ * We keep orig_flow in 'ctx' only because I couldn't make GCC 4.4
+ * believe that I wasn't using it without initializing it if I kept it
+ * in a local variable. */
+ ctx->orig_flow = ctx->flow;
+ }
+
if (ctx->flow.nw_frag & FLOW_NW_FRAG_ANY) {
switch (ctx->ofproto->up.frag_handling) {
case OFPC_FRAG_NORMAL:
ctx->may_set_up_flow = false;
} else {
static struct vlog_rate_limit trace_rl = VLOG_RATE_LIMIT_INIT(1, 1);
- struct flow original_flow = ctx->flow;
ovs_be16 initial_tci = ctx->base_flow.vlan_tci;
add_sflow_action(ctx);
do_xlate_actions(in, n_in, ctx);
- if (ctx->max_resubmit_trigger && !ctx->resubmit_hook
- && !VLOG_DROP_ERR(&trace_rl)) {
- struct ds ds = DS_EMPTY_INITIALIZER;
-
- ofproto_trace(ctx->ofproto, &original_flow, ctx->packet,
- initial_tci, &ds);
- VLOG_ERR("Trace triggered by excessive resubmit recursion:\n%s",
- ds_cstr(&ds));
- ds_destroy(&ds);
+ if (ctx->max_resubmit_trigger && !ctx->resubmit_hook) {
+ if (!hit_resubmit_limit) {
+ /* We didn't record the original flow. Make sure we do from
+ * now on. */
+ hit_resubmit_limit = true;
+ } else if (!VLOG_DROP_ERR(&trace_rl)) {
+ struct ds ds = DS_EMPTY_INITIALIZER;
+
+ ofproto_trace(ctx->ofproto, &ctx->orig_flow, ctx->packet,
+ initial_tci, &ds);
+ VLOG_ERR("Trace triggered by excessive resubmit "
+ "recursion:\n%s", ds_cstr(&ds));
+ ds_destroy(&ds);
+ }
}
if (!connmgr_may_set_up_flow(ctx->ofproto->up.connmgr, &ctx->flow,
compose_output_action(ctx, OFPP_LOCAL);
}
}
- add_mirror_actions(ctx, &orig_flow);
+ if (ctx->ofproto->has_mirrors) {
+ add_mirror_actions(ctx, &ctx->orig_flow);
+ }
fix_sflow_action(ctx);
}
}