uint64_t n_missed;
/* Work queues. */
- struct guarded_list flow_mods; /* Contains "struct flow_mod"s. */
struct guarded_list pins; /* Contains "struct ofputil_packet_in"s. */
};
/* Initial mappings of port to bridge mappings. */
static struct shash init_ofp_ports = SHASH_INITIALIZER(&init_ofp_ports);
-/* Executes and takes ownership of 'fm'. */
+/* Executes 'fm'. The caller retains ownership of 'fm' and everything in
+ * it. */
void
ofproto_dpif_flow_mod(struct ofproto_dpif *ofproto,
struct ofputil_flow_mod *fm)
{
- if (!guarded_list_push_back(&ofproto->flow_mods, &fm->list_node, 1024)) {
- COVERAGE_INC(flow_mod_overflow);
- free(fm->ofpacts);
- free(fm);
- }
+ ofproto_flow_mod(&ofproto->up, fm);
}
/* Appends 'pin' to the queue of "packet ins" to be sent to the controller.
classifier_init(&ofproto->facets);
ofproto->consistency_rl = LLONG_MIN;
- guarded_list_init(&ofproto->flow_mods);
guarded_list_init(&ofproto->pins);
ofproto_dpif_unixctl_init();
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
struct rule_dpif *rule, *next_rule;
struct ofputil_packet_in *pin, *next_pin;
- struct ofputil_flow_mod *fm, *next_fm;
struct facet *facet, *next_facet;
- struct list flow_mods, pins;
struct cls_cursor cursor;
struct oftable *table;
+ struct list pins;
ovs_rwlock_rdlock(&ofproto->facets.rwlock);
cls_cursor_init(&cursor, &ofproto->facets, NULL);
OFPROTO_FOR_EACH_TABLE (table, &ofproto->up) {
struct cls_cursor cursor;
- ovs_rwlock_wrlock(&table->cls.rwlock);
+ ovs_rwlock_rdlock(&table->cls.rwlock);
cls_cursor_init(&cursor, &table->cls, NULL);
+ ovs_rwlock_unlock(&table->cls.rwlock);
CLS_CURSOR_FOR_EACH_SAFE (rule, next_rule, up.cr, &cursor) {
- ofproto_rule_delete(&ofproto->up, &table->cls, &rule->up);
+ ofproto_rule_delete(&ofproto->up, &rule->up);
}
- ovs_rwlock_unlock(&table->cls.rwlock);
- }
-
- guarded_list_pop_all(&ofproto->flow_mods, &flow_mods);
- LIST_FOR_EACH_SAFE (fm, next_fm, list_node, &flow_mods) {
- list_remove(&fm->list_node);
- free(fm->ofpacts);
- free(fm);
}
- guarded_list_destroy(&ofproto->flow_mods);
guarded_list_pop_all(&ofproto->pins, &pins);
LIST_FOR_EACH_SAFE (pin, next_pin, list_node, &pins) {
{
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
struct ofputil_packet_in *pin, *next_pin;
- struct ofputil_flow_mod *fm, *next_fm;
- struct list flow_mods, pins;
struct ofport_dpif *ofport;
+ struct list pins;
/* Do not perform any periodic activity required by 'ofproto' while
* waiting for flow restore to complete. */
return 0;
}
- guarded_list_pop_all(&ofproto->flow_mods, &flow_mods);
- LIST_FOR_EACH_SAFE (fm, next_fm, list_node, &flow_mods) {
- int error = ofproto_flow_mod(&ofproto->up, fm);
- if (error && !VLOG_DROP_WARN(&rl)) {
- VLOG_WARN("learning action failed to modify flow table (%s)",
- ofperr_get_name(error));
- }
-
- list_remove(&fm->list_node);
- free(fm->ofpacts);
- free(fm);
- }
-
guarded_list_pop_all(&ofproto->pins, &pins);
LIST_FOR_EACH_SAFE (pin, next_pin, list_node, &pins) {
connmgr_send_packet_in(ofproto->up.connmgr, pin);
static int subfacet_max_idle(const struct dpif_backer *);
static void update_stats(struct dpif_backer *);
-static void rule_expire(struct rule_dpif *);
+static void rule_expire(struct rule_dpif *) OVS_REQUIRES(ofproto_mutex);
static void expire_subfacets(struct dpif_backer *, int dp_max_idle);
/* This function is called periodically by run(). Its job is to collect
/* Expire OpenFlow flows whose idle_timeout or hard_timeout
* has passed. */
- ovs_mutex_lock(&ofproto->up.expirable_mutex);
+ ovs_mutex_lock(&ofproto_mutex);
LIST_FOR_EACH_SAFE (rule, next_rule, expirable,
&ofproto->up.expirable) {
rule_expire(rule_dpif_cast(rule));
}
- ovs_mutex_unlock(&ofproto->up.expirable_mutex);
+ ovs_mutex_unlock(&ofproto_mutex);
/* All outstanding data in existing flows has been accounted, so it's a
* good time to do bond rebalancing. */
* then delete it entirely. */
static void
rule_expire(struct rule_dpif *rule)
+ OVS_REQUIRES(ofproto_mutex)
{
uint16_t idle_timeout, hard_timeout;
- long long int now;
- uint8_t reason;
+ long long int now = time_msec();
+ int reason;
ovs_assert(!rule->up.pending);
- ovs_mutex_lock(&rule->up.timeout_mutex);
+ /* Has 'rule' expired? */
+ ovs_mutex_lock(&rule->up.mutex);
hard_timeout = rule->up.hard_timeout;
idle_timeout = rule->up.idle_timeout;
- ovs_mutex_unlock(&rule->up.timeout_mutex);
-
- /* Has 'rule' expired? */
- now = time_msec();
if (hard_timeout && now > rule->up.modified + hard_timeout * 1000) {
reason = OFPRR_HARD_TIMEOUT;
} else if (idle_timeout && now > rule->up.used + idle_timeout * 1000) {
reason = OFPRR_IDLE_TIMEOUT;
} else {
- return;
+ reason = -1;
}
+ ovs_mutex_unlock(&rule->up.mutex);
- COVERAGE_INC(ofproto_dpif_expired);
- ofproto_rule_expire(&rule->up, reason);
+ if (reason >= 0) {
+ COVERAGE_INC(ofproto_dpif_expired);
+ ofproto_rule_expire(&rule->up, reason);
+ }
}
\f
/* Facets. */
if (facet) {
struct ofproto_dpif *ofproto = facet->ofproto;
const struct ofpact *ofpacts;
+ struct rule_actions *actions;
struct rule_dpif *rule;
size_t ofpacts_len;
bool is_controller;
rule_dpif_lookup(ofproto, &facet->flow, NULL, &rule);
- ofpacts_len = rule->up.actions->ofpacts_len;
- ofpacts = rule->up.actions->ofpacts;
+ actions = rule_dpif_get_actions(rule);
+ rule_dpif_unref(rule);
+
+ ofpacts_len = actions->ofpacts_len;
+ ofpacts = actions->ofpacts;
is_controller = ofpacts_len > 0
&& ofpacts->type == OFPACT_CONTROLLER
&& ofpact_next(ofpacts) >= ofpact_end(ofpacts, ofpacts_len);
- rule_dpif_unref(rule);
+ rule_actions_unref(actions);
return is_controller;
}
facet->xout.nf_output_iface = xout.nf_output_iface;
facet->xout.mirrors = xout.mirrors;
facet->nf_flow.output_iface = facet->xout.nf_output_iface;
+
+ ovs_mutex_lock(&new_rule->up.mutex);
facet->used = MAX(facet->used, new_rule->up.created);
+ ovs_mutex_unlock(&new_rule->up.mutex);
xlate_out_uninit(&xout);
rule_dpif_unref(new_rule);
ovs_be64
rule_dpif_get_flow_cookie(const struct rule_dpif *rule)
+ OVS_REQUIRES(rule->up.mutex)
{
return rule->up.flow_cookie;
}
struct rule_actions *
rule_dpif_get_actions(const struct rule_dpif *rule)
{
- struct rule_actions *actions;
-
- ovs_rwlock_rdlock(&rule->up.rwlock);
- actions = rule->up.actions;
- rule_actions_ref(actions);
- ovs_rwlock_unlock(&rule->up.rwlock);
-
- return actions;
+ return rule_get_actions(&rule->up);
}
\f
/* Subfacets. */
const struct flow *flow, struct flow_wildcards *wc,
uint8_t table_id, struct rule_dpif **rule)
{
- struct cls_rule *cls_rule;
+ const struct cls_rule *cls_rule;
struct classifier *cls;
bool frag;
static void
complete_operation(struct rule_dpif *rule)
+ OVS_REQUIRES(ofproto_mutex)
{
struct ofproto_dpif *ofproto = ofproto_dpif_cast(rule->up.ofproto);
static void
rule_insert(struct rule *rule_)
+ OVS_REQUIRES(ofproto_mutex)
{
struct rule_dpif *rule = rule_dpif_cast(rule_);
complete_operation(rule);
static void
rule_delete(struct rule *rule_)
+ OVS_REQUIRES(ofproto_mutex)
{
struct rule_dpif *rule = rule_dpif_cast(rule_);
complete_operation(rule);
static void
rule_modify_actions(struct rule *rule_, bool reset_counters)
+ OVS_REQUIRES(ofproto_mutex)
{
struct rule_dpif *rule = rule_dpif_cast(rule_);
static void
trace_format_rule(struct ds *result, int level, const struct rule_dpif *rule)
{
+ struct rule_actions *actions;
+ ovs_be64 cookie;
+
ds_put_char_multiple(result, '\t', level);
if (!rule) {
ds_put_cstr(result, "No match\n");
return;
}
+ ovs_mutex_lock(&rule->up.mutex);
+ cookie = rule->up.flow_cookie;
+ ovs_mutex_unlock(&rule->up.mutex);
+
ds_put_format(result, "Rule: table=%"PRIu8" cookie=%#"PRIx64" ",
- rule ? rule->up.table_id : 0, ntohll(rule->up.flow_cookie));
+ rule ? rule->up.table_id : 0, ntohll(cookie));
cls_rule_format(&rule->up.cr, result);
ds_put_char(result, '\n');
+ actions = rule_dpif_get_actions(rule);
+
ds_put_char_multiple(result, '\t', level);
ds_put_cstr(result, "OpenFlow ");
- ofpacts_format(rule->up.actions->ofpacts, rule->up.actions->ofpacts_len,
- result);
+ ofpacts_format(actions->ofpacts, actions->ofpacts_len, result);
ds_put_char(result, '\n');
+
+ rule_actions_unref(actions);
}
static void