}
ovs_rwlock_unlock(&xlate_rwlock);
+ /* Only ofproto-dpif cares about the facet classifier so we just
+ * lock cls_cursor_init() to appease the thread safety analysis. */
+ ovs_rwlock_rdlock(&ofproto->facets.rwlock);
cls_cursor_init(&cursor, &ofproto->facets, NULL);
+ ovs_rwlock_unlock(&ofproto->facets.rwlock);
CLS_CURSOR_FOR_EACH_SAFE (facet, next, cr, &cursor) {
facet_revalidate(facet);
run_fast_rl();
OFPROTO_FOR_EACH_TABLE (table, &ofproto->up) {
struct cls_cursor cursor;
+ ovs_rwlock_wrlock(&table->cls.rwlock);
cls_cursor_init(&cursor, &table->cls, NULL);
CLS_CURSOR_FOR_EACH_SAFE (rule, next_rule, up.cr, &cursor) {
- ofproto_rule_destroy(&rule->up);
+ ofproto_rule_destroy(&ofproto->up, &table->cls, &rule->up);
}
+ ovs_rwlock_unlock(&table->cls.rwlock);
}
ovs_mutex_lock(&ofproto->flow_mod_mutex);
ovs_rwlock_unlock(&ofproto->ml->rwlock);
/* Check the consistency of a random facet, to aid debugging. */
+ ovs_rwlock_rdlock(&ofproto->facets.rwlock);
if (time_msec() >= ofproto->consistency_rl
&& !classifier_is_empty(&ofproto->facets)
&& !ofproto->backer->need_revalidate) {
ofproto->backer->need_revalidate = REV_INCONSISTENCY;
}
}
+ ovs_rwlock_unlock(&ofproto->facets.rwlock);
return 0;
}
size_t n_subfacets = 0;
struct facet *facet;
+ ovs_rwlock_rdlock(&ofproto->facets.rwlock);
simap_increase(usage, "facets", classifier_count(&ofproto->facets));
+ ovs_rwlock_unlock(&ofproto->facets.rwlock);
+ ovs_rwlock_rdlock(&ofproto->facets.rwlock);
cls_cursor_init(&cursor, &ofproto->facets, NULL);
CLS_CURSOR_FOR_EACH (facet, cr, &cursor) {
n_subfacets += list_size(&facet->subfacets);
}
+ ovs_rwlock_unlock(&ofproto->facets.rwlock);
simap_increase(usage, "subfacets", n_subfacets);
}
match_init(&match, &facet->flow, &facet->xout.wc);
cls_rule_init(&facet->cr, &match, OFP_DEFAULT_PRIORITY);
+ ovs_rwlock_wrlock(&ofproto->facets.rwlock);
classifier_insert(&ofproto->facets, &facet->cr);
+ ovs_rwlock_unlock(&ofproto->facets.rwlock);
facet->nf_flow.output_iface = facet->xout.nf_output_iface;
facet->fail_open = rule->up.cr.priority == FAIL_OPEN_PRIORITY;
&facet->subfacets) {
subfacet_destroy__(subfacet);
}
+ ovs_rwlock_wrlock(&facet->ofproto->facets.rwlock);
classifier_remove(&facet->ofproto->facets, &facet->cr);
+ ovs_rwlock_unlock(&facet->ofproto->facets.rwlock);
cls_rule_destroy(&facet->cr);
facet_free(facet);
}
static struct facet *
facet_find(struct ofproto_dpif *ofproto, const struct flow *flow)
{
- struct cls_rule *cr = classifier_lookup(&ofproto->facets, flow, NULL);
+ struct cls_rule *cr;
+
+ ovs_rwlock_rdlock(&ofproto->facets.rwlock);
+ cr = classifier_lookup(&ofproto->facets, flow, NULL);
+ ovs_rwlock_unlock(&ofproto->facets.rwlock);
return cr ? CONTAINER_OF(cr, struct facet, cr) : NULL;
}
struct cls_cursor cursor;
struct facet *facet;
+ ovs_rwlock_rdlock(&ofproto->facets.rwlock);
cls_cursor_init(&cursor, &ofproto->facets, NULL);
CLS_CURSOR_FOR_EACH (facet, cr, &cursor) {
facet_push_stats(facet, false);
run_fast_rl();
}
}
+ ovs_rwlock_unlock(&ofproto->facets.rwlock);
}
rl = time_msec() + 100;
struct flow ofpc_normal_flow = *flow;
ofpc_normal_flow.tp_src = htons(0);
ofpc_normal_flow.tp_dst = htons(0);
+ ovs_rwlock_rdlock(&cls->rwlock);
cls_rule = classifier_lookup(cls, &ofpc_normal_flow, wc);
+ ovs_rwlock_unlock(&cls->rwlock);
} else if (frag && ofproto->up.frag_handling == OFPC_FRAG_DROP) {
cls_rule = &ofproto->drop_frags_rule->up.cr;
if (wc) {
flow_wildcards_init_exact(wc);
}
} else {
+ ovs_rwlock_rdlock(&cls->rwlock);
cls_rule = classifier_lookup(cls, flow, wc);
+ ovs_rwlock_unlock(&cls->rwlock);
}
return rule_dpif_cast(rule_from_cls_rule(cls_rule));
}
struct cls_cursor cursor;
struct facet *facet;
+ ovs_rwlock_rdlock(&ofproto->facets.rwlock);
cls_cursor_init(&cursor, &ofproto->facets, NULL);
CLS_CURSOR_FOR_EACH (facet, cr, &cursor) {
send_active_timeout(ofproto, facet);
}
+ ovs_rwlock_unlock(&ofproto->facets.rwlock);
}
\f
static struct ofproto_dpif *
int errors;
errors = 0;
+ ovs_rwlock_rdlock(&ofproto->facets.rwlock);
cls_cursor_init(&cursor, &ofproto->facets, NULL);
CLS_CURSOR_FOR_EACH (facet, cr, &cursor) {
if (!facet_check_consistency(facet)) {
errors++;
}
}
+ ovs_rwlock_unlock(&ofproto->facets.rwlock);
if (errors) {
ofproto->backer->need_revalidate = REV_INCONSISTENCY;
}
return;
}
+ ovs_rwlock_rdlock(&ofproto->facets.rwlock);
cls_cursor_init(&cursor, &ofproto->facets, NULL);
CLS_CURSOR_FOR_EACH (facet, cr, &cursor) {
cls_rule_format(&facet->cr, &ds);
}
ds_put_cstr(&ds, "\n");
}
+ ovs_rwlock_unlock(&ofproto->facets.rwlock);
ds_chomp(&ds, '\n');
unixctl_command_reply(conn, ds_cstr(&ds));