Merge branch 'mainstream'
[sliver-openvswitch.git] / ofproto / ofproto-dpif.c
index 81adb0a..b91b3df 100644 (file)
@@ -508,7 +508,6 @@ struct ofproto_dpif {
     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. */
 };
 
@@ -551,16 +550,13 @@ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);
 /* 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.
@@ -1267,7 +1263,6 @@ construct(struct ofproto *ofproto_)
     classifier_init(&ofproto->facets);
     ofproto->consistency_rl = LLONG_MIN;
 
-    guarded_list_init(&ofproto->flow_mods);
     guarded_list_init(&ofproto->pins);
 
     ofproto_dpif_unixctl_init();
@@ -1392,11 +1387,10 @@ destruct(struct ofproto *ofproto_)
     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);
@@ -1419,21 +1413,13 @@ destruct(struct ofproto *ofproto_)
     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) {
@@ -1469,9 +1455,8 @@ run_fast(struct ofproto *ofproto_)
 {
     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. */
@@ -1479,19 +1464,6 @@ run_fast(struct ofproto *ofproto_)
         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);
@@ -3587,7 +3559,7 @@ handle_upcalls(struct dpif_backer *backer)
 
 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
@@ -3907,30 +3879,31 @@ expire_subfacets(struct dpif_backer *backer, int dp_max_idle)
  * 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);
 
+    /* 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.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. */
@@ -4122,17 +4095,21 @@ facet_is_controller_flow(struct facet *facet)
     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;
     }
@@ -4354,7 +4331,10 @@ facet_revalidate(struct facet *facet)
     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);
@@ -4474,6 +4454,7 @@ rule_dpif_fail_open(const struct rule_dpif *rule)
 
 ovs_be64
 rule_dpif_get_flow_cookie(const struct rule_dpif *rule)
+    OVS_REQUIRES(rule->up.mutex)
 {
     return rule->up.flow_cookie;
 }
@@ -4491,14 +4472,7 @@ rule_dpif_reduce_timeouts(struct rule_dpif *rule, uint16_t idle_timeout,
 struct rule_actions *
 rule_dpif_get_actions(const struct rule_dpif *rule)
 {
-    struct rule_actions *actions;
-
-    ovs_mutex_lock(&rule->up.mutex);
-    actions = rule->up.actions;
-    rule_actions_ref(actions);
-    ovs_mutex_unlock(&rule->up.mutex);
-
-    return actions;
+    return rule_get_actions(&rule->up);
 }
 \f
 /* Subfacets. */
@@ -4777,7 +4751,7 @@ rule_dpif_lookup_in_table(struct ofproto_dpif *ofproto,
                           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;
 
@@ -4845,6 +4819,7 @@ rule_dpif_unref(struct rule_dpif *rule)
 
 static void
 complete_operation(struct rule_dpif *rule)
+    OVS_REQUIRES(ofproto_mutex)
 {
     struct ofproto_dpif *ofproto = ofproto_dpif_cast(rule->up.ofproto);
 
@@ -4885,6 +4860,7 @@ rule_construct(struct rule *rule_)
 
 static void
 rule_insert(struct rule *rule_)
+    OVS_REQUIRES(ofproto_mutex)
 {
     struct rule_dpif *rule = rule_dpif_cast(rule_);
     complete_operation(rule);
@@ -4892,6 +4868,7 @@ rule_insert(struct rule *rule_)
 
 static void
 rule_delete(struct rule *rule_)
+    OVS_REQUIRES(ofproto_mutex)
 {
     struct rule_dpif *rule = rule_dpif_cast(rule_);
     complete_operation(rule);
@@ -4956,6 +4933,7 @@ rule_execute(struct rule *rule, const struct flow *flow,
 
 static void
 rule_modify_actions(struct rule *rule_, bool reset_counters)
+    OVS_REQUIRES(ofproto_mutex)
 {
     struct rule_dpif *rule = rule_dpif_cast(rule_);
 
@@ -5270,22 +5248,32 @@ struct trace_ctx {
 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