I get a bunch of thread-safety warnings with the latest Clang without this
patch, because Clang is smart enough to see locking and unlocking but not
smart enough to figure out the relationships. This refactoring avoids the
warnings.
I first noticed these warnings with Clang 1:3.4~svn188890-1~exp1.
I previously used version 1:3.4~svn187484-1~exp1.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Jarno Rajahalme <jrajahalme@nicira.com>
compose_output_action__(ctx, ofp_port, true);
}
compose_output_action__(ctx, ofp_port, true);
}
+static void
+xlate_recursively(struct xlate_ctx *ctx, struct rule_dpif *rule)
+ OVS_RELEASES(rule->up.evict)
+{
+ struct rule_dpif *old_rule = ctx->rule;
+
+ if (ctx->xin->resubmit_stats) {
+ rule_credit_stats(rule, ctx->xin->resubmit_stats);
+ }
+
+ ctx->recurse++;
+ ctx->rule = rule;
+ do_xlate_actions(rule->up.ofpacts, rule->up.ofpacts_len, ctx);
+ ctx->rule = old_rule;
+ ctx->recurse--;
+
+ rule_release(rule);
+}
+
static void
xlate_table_action(struct xlate_ctx *ctx,
ofp_port_t in_port, uint8_t table_id, bool may_packet_in)
static void
xlate_table_action(struct xlate_ctx *ctx,
ofp_port_t in_port, uint8_t table_id, bool may_packet_in)
struct rule_dpif *rule;
ofp_port_t old_in_port = ctx->xin->flow.in_port.ofp_port;
uint8_t old_table_id = ctx->table_id;
struct rule_dpif *rule;
ofp_port_t old_in_port = ctx->xin->flow.in_port.ofp_port;
uint8_t old_table_id = ctx->table_id;
ctx->table_id = table_id;
ctx->table_id = table_id;
- /* Look up a flow with 'in_port' as the input port. */
+ /* 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;
ctx->xin->flow.in_port.ofp_port = in_port;
- rule_dpif_lookup_in_table(ctx->xbridge->ofproto, &ctx->xin->flow,
- &ctx->xout->wc, table_id, &rule);
-
- /* Restore the original input port. Otherwise OFPP_NORMAL and
- * OFPP_IN_PORT will have surprising behavior. */
+ got_rule = rule_dpif_lookup_in_table(ctx->xbridge->ofproto,
+ &ctx->xin->flow, &ctx->xout->wc,
+ table_id, &rule);
ctx->xin->flow.in_port.ofp_port = old_in_port;
if (ctx->xin->resubmit_hook) {
ctx->xin->resubmit_hook(ctx->xin, rule, ctx->recurse);
}
ctx->xin->flow.in_port.ofp_port = old_in_port;
if (ctx->xin->resubmit_hook) {
ctx->xin->resubmit_hook(ctx->xin, rule, ctx->recurse);
}
- if (rule == NULL && may_packet_in) {
+ if (got_rule) {
+ xlate_recursively(ctx, rule);
+ } else if (may_packet_in) {
- /* Makes clang's thread safety analysis happy. */
- rule_release(rule);
-
/* XXX
* check if table configuration flags
* OFPTC_TABLE_MISS_CONTROLLER, default.
/* XXX
* check if table configuration flags
* OFPTC_TABLE_MISS_CONTROLLER, default.
ctx->xbridge->miss_rule,
ctx->xbridge->no_packet_in_rule);
ovs_rwlock_rdlock(&rule->up.evict);
ctx->xbridge->miss_rule,
ctx->xbridge->no_packet_in_rule);
ovs_rwlock_rdlock(&rule->up.evict);
+ xlate_recursively(ctx, rule);
- if (rule && ctx->xin->resubmit_stats) {
- rule_credit_stats(rule, ctx->xin->resubmit_stats);
- }
-
- if (rule) {
- struct rule_dpif *old_rule = ctx->rule;
-
- ctx->recurse++;
- ctx->rule = rule;
- do_xlate_actions(rule->up.ofpacts, rule->up.ofpacts_len, ctx);
- ctx->rule = old_rule;
- ctx->recurse--;
- }
- rule_release(rule);
-
ctx->table_id = old_table_id;
} else {
static struct vlog_rate_limit recurse_rl = VLOG_RATE_LIMIT_INIT(1, 1);
ctx->table_id = old_table_id;
} else {
static struct vlog_rate_limit recurse_rl = VLOG_RATE_LIMIT_INIT(1, 1);