aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJarno Rajahalme <jrajahalme@nicira.com>2014-11-10 13:14:29 -0800
committerJarno Rajahalme <jrajahalme@nicira.com>2014-11-10 13:33:38 -0800
commit34dd0d78d9b30b745c5011020701bf228a63810d (patch)
treedade318bdcd7b97388d7c5085b21a898415f4838
parent2f47cdf48336debf20488790dfa2b176122fbe1e (diff)
ofproto-dpif: Clean up table lookup code.
Keep knowledge about ofproto-dpif internal rules within ofproto-dpif. This removes duplication of code (accross multiple files), and allows making the ofproto-dpif-xlate interface a bit smaller. 'may_packet_in' was previously not honored for the 'LOOKUP_VERDICT_DEFAULT' case. Now it is, but this change did not break any unit tests. Also, previously in the 'LOOKUP_VERDICT_CONTROLLER' case packet-in messages would have been generated when the in_port could not be found ('config' was set to zero in this case, causing 'OFPUTIL_PC_NO_PACKET_IN' flag to be zero as well). This patch changes this behavior and never issues packet-in messages when the in_port cannot be found. This did not break any unit tests either. Signed-off-by: Jarno Rajahalme <jrajahalme@nicira.com> Acked-by: Ben Pfaff <blp@nicira.com>
-rw-r--r--ofproto/ofproto-dpif-xlate.c120
-rw-r--r--ofproto/ofproto-dpif-xlate.h5
-rw-r--r--ofproto/ofproto-dpif.c222
-rw-r--r--ofproto/ofproto-dpif.h39
4 files changed, 139 insertions, 247 deletions
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index c9f71445a..ba002ba1a 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -89,11 +89,6 @@ struct xbridge {
struct stp *stp; /* STP or null if disabled. */
struct rstp *rstp; /* RSTP or null if disabled. */
- /* Special rules installed by ofproto-dpif. */
- struct rule_dpif *miss_rule;
- struct rule_dpif *no_packet_in_rule;
- struct rule_dpif *drop_frags_rule;
-
bool has_in_band; /* Bridge has in band control? */
bool forward_bpdu; /* Bridge forwards STP BPDUs? */
@@ -333,7 +328,7 @@ static bool may_receive(const struct xport *, struct xlate_ctx *);
static void do_xlate_actions(const struct ofpact *, size_t ofpacts_len,
struct xlate_ctx *);
static void xlate_normal(struct xlate_ctx *);
-static void xlate_report(struct xlate_ctx *, const char *);
+static inline void xlate_report(struct xlate_ctx *, const char *);
static void xlate_table_action(struct xlate_ctx *, ofp_port_t in_port,
uint8_t table_id, bool may_packet_in,
bool honor_table_miss);
@@ -363,9 +358,6 @@ static void xlate_xbridge_init(struct xlate_cfg *, struct xbridge *);
static void xlate_xbundle_init(struct xlate_cfg *, struct xbundle *);
static void xlate_xport_init(struct xlate_cfg *, struct xport *);
static void xlate_xbridge_set(struct xbridge *, struct dpif *,
- struct rule_dpif *miss_rule,
- struct rule_dpif *no_packet_in_rule,
- struct rule_dpif *drop_frags_rule,
const struct mac_learning *, struct stp *,
struct rstp *, const struct mcast_snooping *,
const struct mbridge *,
@@ -398,6 +390,13 @@ static void xlate_xport_copy(struct xbridge *, struct xbundle *,
struct xport *);
static void xlate_xcfg_free(struct xlate_cfg *);
+static inline void
+xlate_report(struct xlate_ctx *ctx, const char *s)
+{
+ if (OVS_UNLIKELY(ctx->xin->report_hook)) {
+ ctx->xin->report_hook(ctx->xin, s, ctx->recurse);
+ }
+}
static void
xlate_xbridge_init(struct xlate_cfg *xcfg, struct xbridge *xbridge)
@@ -430,9 +429,6 @@ xlate_xport_init(struct xlate_cfg *xcfg, struct xport *xport)
static void
xlate_xbridge_set(struct xbridge *xbridge,
struct dpif *dpif,
- struct rule_dpif *miss_rule,
- struct rule_dpif *no_packet_in_rule,
- struct rule_dpif *drop_frags_rule,
const struct mac_learning *ml, struct stp *stp,
struct rstp *rstp, const struct mcast_snooping *ms,
const struct mbridge *mbridge,
@@ -488,9 +484,6 @@ xlate_xbridge_set(struct xbridge *xbridge,
xbridge->dpif = dpif;
xbridge->forward_bpdu = forward_bpdu;
xbridge->has_in_band = has_in_band;
- xbridge->miss_rule = miss_rule;
- xbridge->no_packet_in_rule = no_packet_in_rule;
- xbridge->drop_frags_rule = drop_frags_rule;
xbridge->enable_recirc = enable_recirc;
xbridge->variable_length_userdata = variable_length_userdata;
xbridge->max_mpls_depth = max_mpls_depth;
@@ -570,9 +563,7 @@ xlate_xbridge_copy(struct xbridge *xbridge)
xlate_xbridge_init(new_xcfg, new_xbridge);
xlate_xbridge_set(new_xbridge,
- xbridge->dpif, xbridge->miss_rule,
- xbridge->no_packet_in_rule, xbridge->drop_frags_rule,
- xbridge->ml, xbridge->stp,
+ xbridge->dpif, xbridge->ml, xbridge->stp,
xbridge->rstp, xbridge->ms, xbridge->mbridge,
xbridge->sflow, xbridge->ipfix, xbridge->netflow,
xbridge->forward_bpdu,
@@ -722,9 +713,7 @@ xlate_xcfg_free(struct xlate_cfg *xcfg)
void
xlate_ofproto_set(struct ofproto_dpif *ofproto, const char *name,
- struct dpif *dpif, struct rule_dpif *miss_rule,
- struct rule_dpif *no_packet_in_rule,
- struct rule_dpif *drop_frags_rule,
+ struct dpif *dpif,
const struct mac_learning *ml, struct stp *stp,
struct rstp *rstp, const struct mcast_snooping *ms,
const struct mbridge *mbridge,
@@ -750,10 +739,8 @@ xlate_ofproto_set(struct ofproto_dpif *ofproto, const char *name,
free(xbridge->name);
xbridge->name = xstrdup(name);
- xlate_xbridge_set(xbridge, dpif, miss_rule, no_packet_in_rule,
- drop_frags_rule, ml, stp,
- rstp, ms, mbridge, sflow, ipfix, netflow,
- forward_bpdu, has_in_band, enable_recirc,
+ xlate_xbridge_set(xbridge, dpif, ml, stp, rstp, ms, mbridge, sflow, ipfix,
+ netflow, forward_bpdu, has_in_band, enable_recirc,
variable_length_userdata, max_mpls_depth,
masked_set_action);
}
@@ -2721,63 +2708,24 @@ xlate_table_action(struct xlate_ctx *ctx, ofp_port_t in_port, uint8_t table_id,
bool may_packet_in, bool honor_table_miss)
{
if (xlate_resubmit_resource_check(ctx)) {
- ofp_port_t old_in_port = ctx->xin->flow.in_port.ofp_port;
- bool skip_wildcards = ctx->xin->skip_wildcards;
+ struct flow_wildcards *wc;
uint8_t old_table_id = ctx->table_id;
struct rule_dpif *rule;
- enum rule_dpif_lookup_verdict verdict;
- enum ofputil_port_config config = 0;
ctx->table_id = table_id;
+ wc = (ctx->xin->skip_wildcards) ? NULL : &ctx->xout->wc;
- /* Look up a flow with 'in_port' as the input port. Then restore the
- * original input port (otherwise OFPP_NORMAL and OFPP_IN_PORT will
- * have surprising behavior). */
- ctx->xin->flow.in_port.ofp_port = in_port;
- verdict = rule_dpif_lookup_from_table(ctx->xbridge->ofproto,
- &ctx->xin->flow,
- !skip_wildcards
- ? &ctx->xout->wc : NULL,
- honor_table_miss,
- &ctx->table_id, &rule,
- ctx->xin->xcache != NULL,
- ctx->xin->resubmit_stats);
- ctx->xin->flow.in_port.ofp_port = old_in_port;
+ rule = rule_dpif_lookup_from_table(ctx->xbridge->ofproto,
+ &ctx->xin->flow, wc,
+ ctx->xin->xcache != NULL,
+ ctx->xin->resubmit_stats,
+ &ctx->table_id, in_port,
+ may_packet_in, honor_table_miss);
if (OVS_UNLIKELY(ctx->xin->resubmit_hook)) {
ctx->xin->resubmit_hook(ctx->xin, rule, ctx->recurse + 1);
}
- switch (verdict) {
- case RULE_DPIF_LOOKUP_VERDICT_MATCH:
- goto match;
- case RULE_DPIF_LOOKUP_VERDICT_CONTROLLER:
- if (may_packet_in) {
- struct xport *xport;
-
- xport = get_ofp_port(ctx->xbridge,
- ctx->xin->flow.in_port.ofp_port);
- config = xport ? xport->config : 0;
- break;
- }
- /* Fall through to drop */
- case RULE_DPIF_LOOKUP_VERDICT_DROP:
- config = OFPUTIL_PC_NO_PACKET_IN;
- break;
- case RULE_DPIF_LOOKUP_VERDICT_DEFAULT:
- if (!ofproto_dpif_wants_packet_in_on_miss(ctx->xbridge->ofproto)) {
- config = OFPUTIL_PC_NO_PACKET_IN;
- }
- break;
- default:
- OVS_NOT_REACHED();
- }
-
- choose_miss_rule(config, ctx->xbridge->miss_rule,
- ctx->xbridge->no_packet_in_rule, &rule,
- ctx->xin->xcache != NULL);
-
-match:
if (rule) {
/* Fill in the cache entry here instead of xlate_recursively
* to make the reference counting more explicit. We take a
@@ -3996,14 +3944,6 @@ xlate_actions_for_side_effects(struct xlate_in *xin)
xlate_out_uninit(&xout);
}
-static void
-xlate_report(struct xlate_ctx *ctx, const char *s)
-{
- if (ctx->xin->report_hook) {
- ctx->xin->report_hook(ctx->xin, s, ctx->recurse);
- }
-}
-
void
xlate_out_copy(struct xlate_out *dst, const struct xlate_out *src)
{
@@ -4249,22 +4189,10 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout)
ctx.was_mpls = false;
if (!xin->ofpacts && !ctx.rule) {
- ctx.table_id = rule_dpif_lookup(ctx.xbridge->ofproto, flow,
- !xin->skip_wildcards ? wc : NULL,
- &rule, ctx.xin->xcache != NULL,
- ctx.xin->resubmit_stats);
- if (OVS_UNLIKELY(ctx.xin->report_hook)) {
- if (rule == ctx.xbridge->miss_rule) {
- xlate_report(&ctx, "No match, flow generates \"packet in\"s.");
- } else if (rule == ctx.xbridge->no_packet_in_rule) {
- xlate_report(&ctx, "No match, packets dropped because "
- "OFPPC_NO_PACKET_IN is set on in_port.");
- } else if (rule == ctx.xbridge->drop_frags_rule) {
- xlate_report(&ctx, "Packets dropped because they are IP "
- "fragments and the fragment handling mode is "
- "\"drop\".");
- }
- }
+ rule = rule_dpif_lookup(ctx.xbridge->ofproto, flow,
+ xin->skip_wildcards ? NULL : wc,
+ ctx.xin->xcache != NULL,
+ ctx.xin->resubmit_stats, &ctx.table_id);
if (ctx.xin->resubmit_stats) {
rule_dpif_credit_stats(rule, ctx.xin->resubmit_stats);
}
diff --git a/ofproto/ofproto-dpif-xlate.h b/ofproto/ofproto-dpif-xlate.h
index 8fa41f17e..9a0378241 100644
--- a/ofproto/ofproto-dpif-xlate.h
+++ b/ofproto/ofproto-dpif-xlate.h
@@ -143,10 +143,7 @@ struct xlate_in {
struct ofpbuf *odp_actions;
};
-void xlate_ofproto_set(struct ofproto_dpif *, const char *name,
- struct dpif *, struct rule_dpif *miss_rule,
- struct rule_dpif *no_packet_in_rule,
- struct rule_dpif *drop_frags_rule,
+void xlate_ofproto_set(struct ofproto_dpif *, const char *name, struct dpif *,
const struct mac_learning *, struct stp *,
struct rstp *, const struct mcast_snooping *,
const struct mbridge *, const struct dpif_sflow *,
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index abfe7f24b..40401ef36 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -618,9 +618,7 @@ type_run(const char *type)
xlate_txn_start();
xlate_ofproto_set(ofproto, ofproto->up.name,
- ofproto->backer->dpif, ofproto->miss_rule,
- ofproto->no_packet_in_rule,
- ofproto->drop_frags_rule, ofproto->ml,
+ ofproto->backer->dpif, ofproto->ml,
ofproto->stp, ofproto->rstp, ofproto->ms,
ofproto->mbridge, ofproto->sflow, ofproto->ipfix,
ofproto->netflow,
@@ -3576,24 +3574,24 @@ rule_set_recirc_id(struct rule *rule_, uint32_t id)
/* Lookup 'flow' in table 0 of 'ofproto''s classifier.
* If 'wc' is non-null, sets the fields that were relevant as part of
- * the lookup. Returns the table_id where a match or miss occurred.
- *
- * The return value will be zero unless there was a miss and
+ * the lookup. Returns the table id where a match or miss occurred via
+ * 'table_id'. This will be zero unless there was a miss and
* OFPTC11_TABLE_MISS_CONTINUE is in effect for the sequence of tables
- * where misses occur.
+ * where misses occur, or TBL_INTERNAL if the rule has a non-zero
+ * recirculation ID, and a match was found in the internal table, or if
+ * there was no match and one of the special rules (drop_frags_rule,
+ * miss_rule, or no_packet_in_rule) was returned.
*
- * The rule is returned in '*rule', which is valid at least until the next
- * RCU quiescent period. If the '*rule' needs to stay around longer,
+ * The return value is the found rule, which is valid at least until the next
+ * RCU quiescent period. If the rule needs to stay around longer,
* a non-zero 'take_ref' must be passed in to cause a reference to be taken
* on it before this returns. */
-uint8_t
+struct rule_dpif *
rule_dpif_lookup(struct ofproto_dpif *ofproto, struct flow *flow,
- struct flow_wildcards *wc, struct rule_dpif **rule,
- bool take_ref, const struct dpif_flow_stats *stats)
+ struct flow_wildcards *wc, bool take_ref,
+ const struct dpif_flow_stats *stats, uint8_t *table_id)
{
- enum rule_dpif_lookup_verdict verdict;
- enum ofputil_port_config config = 0;
- uint8_t table_id = 0;
+ *table_id = 0;
if (ofproto_dpif_get_enable_recirc(ofproto)) {
/* Always exactly match recirc_id since datapath supports
@@ -3604,47 +3602,18 @@ rule_dpif_lookup(struct ofproto_dpif *ofproto, struct flow *flow,
if (flow->recirc_id) {
/* Start looking up from internal table for post recirculation
* flows or packets. */
- table_id = TBL_INTERNAL;
- }
- }
-
- verdict = rule_dpif_lookup_from_table(ofproto, flow, wc, true,
- &table_id, rule, take_ref, stats);
-
- switch (verdict) {
- case RULE_DPIF_LOOKUP_VERDICT_MATCH:
- return table_id;
- case RULE_DPIF_LOOKUP_VERDICT_CONTROLLER: {
- struct ofport_dpif *port;
-
- port = get_ofp_port(ofproto, flow->in_port.ofp_port);
- if (!port) {
- VLOG_WARN_RL(&rl, "packet-in on unknown OpenFlow port %"PRIu16,
- flow->in_port.ofp_port);
+ *table_id = TBL_INTERNAL;
}
- config = port ? port->up.pp.config : 0;
- break;
- }
- case RULE_DPIF_LOOKUP_VERDICT_DROP:
- config = OFPUTIL_PC_NO_PACKET_IN;
- break;
- case RULE_DPIF_LOOKUP_VERDICT_DEFAULT:
- if (!connmgr_wants_packet_in_on_miss(ofproto->up.connmgr)) {
- config = OFPUTIL_PC_NO_PACKET_IN;
- }
- break;
- default:
- OVS_NOT_REACHED();
}
- choose_miss_rule(config, ofproto->miss_rule,
- ofproto->no_packet_in_rule, rule, take_ref);
- return table_id;
+ return rule_dpif_lookup_from_table(ofproto, flow, wc, take_ref, stats,
+ table_id, flow->in_port.ofp_port, true,
+ true);
}
-/* The returned rule is valid at least until the next RCU quiescent period.
- * If the '*rule' needs to stay around longer, a non-zero 'take_ref' must be
- * passed in to cause a reference to be taken on it before this returns. */
+/* The returned rule (if any) is valid at least until the next RCU quiescent
+ * period. If the rule needs to stay around longer, a non-zero 'take_ref'
+ * must be passed in to cause a reference to be taken on it. */
static struct rule_dpif *
rule_dpif_lookup_in_table(struct ofproto_dpif *ofproto, uint8_t table_id,
const struct flow *flow, struct flow_wildcards *wc,
@@ -3666,7 +3635,9 @@ rule_dpif_lookup_in_table(struct ofproto_dpif *ofproto, uint8_t table_id,
}
/* Look up 'flow' in 'ofproto''s classifier starting from table '*table_id'.
- * Stores the rule that was found in '*rule', or NULL if none was found.
+ * Returns the rule that was found, which may be one of the special rules
+ * according to packet miss hadling. If 'may_packet_in' is false, returning of
+ * the miss_rule (which issues packet ins for the controller) is avoided.
* Updates 'wc', if nonnull, to reflect the fields that were used during the
* lookup.
*
@@ -3679,35 +3650,24 @@ rule_dpif_lookup_in_table(struct ofproto_dpif *ofproto, uint8_t table_id,
* If 'honor_table_miss' is false, then only one table lookup occurs, in
* '*table_id'.
*
- * Returns:
- *
- * - RULE_DPIF_LOOKUP_VERDICT_MATCH if a rule (in '*rule') was found.
- *
- * - RULE_OFPTC_TABLE_MISS_CONTROLLER if no rule was found and either:
- * + 'honor_table_miss' is false
- * + a table miss configuration specified that the packet should be
- * sent to the controller in this case.
- *
- * - RULE_DPIF_LOOKUP_VERDICT_DROP if no rule was found, 'honor_table_miss'
- * is true and a table miss configuration specified that the packet
- * should be dropped in this case.
- *
- * - RULE_DPIF_LOOKUP_VERDICT_DEFAULT if no rule was found,
- * 'honor_table_miss' is true and a table miss configuration has
- * not been specified in this case.
- *
* The rule is returned in '*rule', which is valid at least until the next
* RCU quiescent period. If the '*rule' needs to stay around longer,
* a non-zero 'take_ref' must be passed in to cause a reference to be taken
- * on it before this returns. */
-enum rule_dpif_lookup_verdict
+ * on it before this returns.
+ *
+ * 'in_port' allows the lookup to take place as if the in port had the value
+ * 'in_port'. This is needed for resubmit action support. */
+struct rule_dpif *
rule_dpif_lookup_from_table(struct ofproto_dpif *ofproto, struct flow *flow,
- struct flow_wildcards *wc, bool honor_table_miss,
- uint8_t *table_id, struct rule_dpif **rule,
- bool take_ref, const struct dpif_flow_stats *stats)
+ struct flow_wildcards *wc, bool take_ref,
+ const struct dpif_flow_stats *stats,
+ uint8_t *table_id, ofp_port_t in_port,
+ bool may_packet_in, bool honor_table_miss)
{
ovs_be16 old_tp_src = flow->tp_src, old_tp_dst = flow->tp_dst;
- enum rule_dpif_lookup_verdict verdict;
+ ofp_port_t old_in_port = flow->in_port.ofp_port;
+ enum ofputil_table_miss miss_config;
+ struct rule_dpif *rule;
uint8_t next_id;
/* We always unwildcard nw_frag (for IP), so they
@@ -3721,9 +3681,9 @@ rule_dpif_lookup_from_table(struct ofproto_dpif *ofproto, struct flow *flow,
} else {
/* Must be OFPC_FRAG_DROP (we don't have OFPC_FRAG_REASM).
* Use the drop_frags_rule (which cannot disappear). */
- *rule = ofproto->drop_frags_rule;
+ rule = ofproto->drop_frags_rule;
if (take_ref) {
- rule_dpif_ref(*rule);
+ rule_dpif_ref(rule);
}
if (stats) {
struct oftable *tbl = &ofproto->up.tables[*table_id];
@@ -3731,74 +3691,76 @@ rule_dpif_lookup_from_table(struct ofproto_dpif *ofproto, struct flow *flow,
atomic_add_relaxed(&tbl->n_matched, stats->n_packets, &orig);
}
- return RULE_DPIF_LOOKUP_VERDICT_MATCH;
+ return rule;
}
}
- verdict = RULE_DPIF_LOOKUP_VERDICT_CONTROLLER;
+ /* Look up a flow with 'in_port' as the input port. Then restore the
+ * original input port (otherwise OFPP_NORMAL and OFPP_IN_PORT will
+ * have surprising behavior). */
+ flow->in_port.ofp_port = in_port;
+
+ /* Our current implementation depends on n_tables == N_TABLES, and
+ * TBL_INTERNAL being the last table. */
+ BUILD_ASSERT_DECL(N_TABLES == TBL_INTERNAL + 1);
+
+ miss_config = OFPUTIL_TABLE_MISS_CONTINUE;
for (next_id = *table_id;
next_id < ofproto->up.n_tables;
next_id++, next_id += (next_id == TBL_INTERNAL))
{
*table_id = next_id;
- *rule = rule_dpif_lookup_in_table(ofproto, *table_id, flow, wc,
- take_ref);
+ rule = rule_dpif_lookup_in_table(ofproto, next_id, flow, wc, take_ref);
if (stats) {
struct oftable *tbl = &ofproto->up.tables[next_id];
unsigned long orig;
- atomic_add_relaxed(*rule ? &tbl->n_matched : &tbl->n_missed,
+ atomic_add_relaxed(rule ? &tbl->n_matched : &tbl->n_missed,
stats->n_packets, &orig);
}
- if (*rule) {
- verdict = RULE_DPIF_LOOKUP_VERDICT_MATCH;
- goto out;
- } else if (!honor_table_miss) {
- goto out;
- } else {
- switch (ofproto_table_get_miss_config(&ofproto->up, *table_id)) {
- case OFPUTIL_TABLE_MISS_CONTINUE:
- break;
-
- case OFPUTIL_TABLE_MISS_CONTROLLER:
- goto out;
-
- case OFPUTIL_TABLE_MISS_DROP:
- verdict = RULE_DPIF_LOOKUP_VERDICT_DROP;
- goto out;
-
- case OFPUTIL_TABLE_MISS_DEFAULT:
- verdict = RULE_DPIF_LOOKUP_VERDICT_DEFAULT;
- goto out;
+ if (rule) {
+ goto out; /* Match. */
+ }
+ if (honor_table_miss) {
+ miss_config = ofproto_table_get_miss_config(&ofproto->up,
+ *table_id);
+ if (miss_config == OFPUTIL_TABLE_MISS_CONTINUE) {
+ continue;
+ }
+ }
+ break;
+ }
+ /* Miss. */
+ rule = ofproto->no_packet_in_rule;
+ if (may_packet_in) {
+ if (miss_config == OFPUTIL_TABLE_MISS_CONTINUE
+ || miss_config == OFPUTIL_TABLE_MISS_CONTROLLER) {
+ struct ofport_dpif *port;
+
+ port = get_ofp_port(ofproto, old_in_port);
+ if (!port) {
+ VLOG_WARN_RL(&rl, "packet-in on unknown OpenFlow port %"PRIu16,
+ old_in_port);
+ } else if (!(port->up.pp.config & OFPUTIL_PC_NO_PACKET_IN)) {
+ rule = ofproto->miss_rule;
}
+ } else if (miss_config == OFPUTIL_TABLE_MISS_DEFAULT &&
+ connmgr_wants_packet_in_on_miss(ofproto->up.connmgr)) {
+ rule = ofproto->miss_rule;
}
}
+ if (take_ref) {
+ rule_dpif_ref(rule);
+ }
out:
/* Restore port numbers, as they may have been modified above. */
flow->tp_src = old_tp_src;
flow->tp_dst = old_tp_dst;
+ /* Restore the old in port. */
+ flow->in_port.ofp_port = old_in_port;
- return verdict;
-}
-
-/* Given a port configuration (specified as zero if there's no port), chooses
- * which of 'miss_rule' and 'no_packet_in_rule' should be used in case of a
- * flow table miss.
- *
- * The rule is returned in '*rule', which is valid at least until the next
- * RCU quiescent period. If the '*rule' needs to stay around longer,
- * a reference must be taken on it (rule_dpif_ref()).
- */
-void
-choose_miss_rule(enum ofputil_port_config config, struct rule_dpif *miss_rule,
- struct rule_dpif *no_packet_in_rule, struct rule_dpif **rule,
- bool take_ref)
-{
- *rule = config & OFPUTIL_PC_NO_PACKET_IN ? no_packet_in_rule : miss_rule;
- if (take_ref) {
- rule_dpif_ref(*rule);
- }
+ return rule;
}
static void
@@ -4420,12 +4382,28 @@ trace_format_megaflow(struct ds *result, int level, const char *title,
ds_put_char(result, '\n');
}
+static void trace_report(struct xlate_in *xin, const char *s, int recurse);
+
static void
trace_resubmit(struct xlate_in *xin, struct rule_dpif *rule, int recurse)
{
struct trace_ctx *trace = CONTAINER_OF(xin, struct trace_ctx, xin);
struct ds *result = trace->result;
+ if (!recurse) {
+ if (rule == xin->ofproto->miss_rule) {
+ trace_report(xin, "No match, flow generates \"packet in\"s.",
+ recurse);
+ } else if (rule == xin->ofproto->no_packet_in_rule) {
+ trace_report(xin, "No match, packets dropped because "
+ "OFPPC_NO_PACKET_IN is set on in_port.", recurse);
+ } else if (rule == xin->ofproto->drop_frags_rule) {
+ trace_report(xin, "Packets dropped because they are IP "
+ "fragments and the fragment handling mode is "
+ "\"drop\".", recurse);
+ }
+ }
+
ds_put_char(result, '\n');
if (recurse) {
trace_format_flow(result, recurse, "Resubmitted flow", trace);
diff --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h
index 24d509d67..77ae8f08f 100644
--- a/ofproto/ofproto-dpif.h
+++ b/ofproto/ofproto-dpif.h
@@ -40,23 +40,6 @@ struct dpif_backer;
struct OVS_LOCKABLE rule_dpif;
struct OVS_LOCKABLE group_dpif;
-enum rule_dpif_lookup_verdict {
- RULE_DPIF_LOOKUP_VERDICT_MATCH, /* A match occurred. */
- RULE_DPIF_LOOKUP_VERDICT_CONTROLLER, /* A miss occurred and the packet
- * should be passed to
- * the controller. */
- RULE_DPIF_LOOKUP_VERDICT_DROP, /* A miss occurred and the packet
- * should be dropped. */
- RULE_DPIF_LOOKUP_VERDICT_DEFAULT, /* A miss occurred and the packet
- * should handled by the default
- * miss behaviour.
- * For pre-OF1.3 it should be
- * forwarded to the controller.
- * For OF1.3+ it should be
- * dropped. */
-};
-
-
/* Ofproto-dpif -- DPIF based ofproto implementation.
*
* Ofproto-dpif provides an ofproto implementation for those platforms which
@@ -88,14 +71,20 @@ enum rule_dpif_lookup_verdict {
size_t ofproto_dpif_get_max_mpls_depth(const struct ofproto_dpif *);
bool ofproto_dpif_get_enable_recirc(const struct ofproto_dpif *);
-uint8_t rule_dpif_lookup(struct ofproto_dpif *, struct flow *,
- struct flow_wildcards *, struct rule_dpif **rule,
- bool take_ref, const struct dpif_flow_stats *);
-
-enum rule_dpif_lookup_verdict rule_dpif_lookup_from_table(
- struct ofproto_dpif *, struct flow *, struct flow_wildcards *,
- bool force_controller_on_miss, uint8_t *table_id, struct rule_dpif **rule,
- bool take_ref, const struct dpif_flow_stats *);
+struct rule_dpif *rule_dpif_lookup(struct ofproto_dpif *, struct flow *,
+ struct flow_wildcards *, bool take_ref,
+ const struct dpif_flow_stats *,
+ uint8_t *table_id);
+
+struct rule_dpif *rule_dpif_lookup_from_table(struct ofproto_dpif *,
+ struct flow *,
+ struct flow_wildcards *,
+ bool take_ref,
+ const struct dpif_flow_stats *,
+ uint8_t *table_id,
+ ofp_port_t in_port,
+ bool may_packet_in,
+ bool honor_table_miss);
static inline void rule_dpif_ref(struct rule_dpif *);
static inline void rule_dpif_unref(struct rule_dpif *);