ofproto-dpif: Don't manage eviction groups from threads.
authorEthan Jackson <ethan@nicira.com>
Tue, 3 Sep 2013 22:37:14 +0000 (15:37 -0700)
committerEthan Jackson <ethan@nicira.com>
Wed, 4 Sep 2013 22:57:07 +0000 (15:57 -0700)
Managing eviction groups from threads was going to be difficult to do
in a performant thread-safe manner, so this patch punts the problem to
the main thread.

Signed-off-by: Ethan Jackson <ethan@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
ofproto/ofproto-dpif.c
ofproto/ofproto-provider.h
ofproto/ofproto.c

index cab7bc3..6125e9b 100644 (file)
@@ -4541,7 +4541,7 @@ rule_dpif_credit_stats(struct rule_dpif *rule,
     ovs_mutex_lock(&rule->stats_mutex);
     rule->packet_count += stats->n_packets;
     rule->byte_count += stats->n_bytes;
-    ofproto_rule_update_used(&rule->up, stats->used);
+    rule->up.used = MAX(rule->up.used, stats->used);
     ovs_mutex_unlock(&rule->stats_mutex);
 }
 
index d6a8a0b..59b9045 100644 (file)
@@ -69,6 +69,7 @@ struct ofproto {
     uint16_t max_ports;         /* Max possible OpenFlow port num, plus one. */
 
     /* Flow tables. */
+    long long int eviction_group_timer; /* For rate limited reheapification. */
     struct oftable *tables;
     int n_tables;
 
@@ -276,7 +277,6 @@ rule_from_cls_rule(const struct cls_rule *cls_rule)
     return cls_rule ? CONTAINER_OF(cls_rule, struct rule, cr) : NULL;
 }
 
-void ofproto_rule_update_used(struct rule *, long long int used);
 void ofproto_rule_expire(struct rule *rule, uint8_t reason);
 void ofproto_rule_delete(struct ofproto *, struct classifier *cls,
                          struct rule *) OVS_REQ_WRLOCK(cls->rwlock);
index bc51aeb..aa295c9 100644 (file)
@@ -439,6 +439,7 @@ ofproto_create(const char *datapath_name, const char *datapath_type,
     shash_init(&ofproto->port_by_name);
     simap_init(&ofproto->ofp_requests);
     ofproto->max_ports = ofp_to_u16(OFPP_MAX);
+    ofproto->eviction_group_timer = LLONG_MIN;
     ofproto->tables = NULL;
     ofproto->n_tables = 0;
     hindex_init(&ofproto->cookies);
@@ -1269,6 +1270,39 @@ ofproto_run(struct ofproto *p)
         VLOG_ERR_RL(&rl, "%s: run failed (%s)", p->name, ovs_strerror(error));
     }
 
+    /* Restore the eviction group heap invariant occasionally. */
+    if (p->eviction_group_timer < time_msec()) {
+        size_t i;
+
+        p->eviction_group_timer = time_msec() + 1000;
+
+        for (i = 0; i < p->n_tables; i++) {
+            struct oftable *table = &p->tables[i];
+            struct eviction_group *evg;
+            struct cls_cursor cursor;
+            struct cls_rule cr;
+            struct rule *rule;
+
+            if (!table->eviction_fields) {
+                continue;
+            }
+
+            HEAP_FOR_EACH (evg, size_node, &table->eviction_groups_by_size) {
+                heap_rebuild(&evg->rules);
+            }
+
+            ovs_rwlock_rdlock(&table->cls.rwlock);
+            cls_cursor_init(&cursor, &table->cls, &cr);
+            CLS_CURSOR_FOR_EACH (rule, cr, &cursor) {
+                if (!rule->eviction_group
+                    && (rule->idle_timeout || rule->hard_timeout)) {
+                    eviction_group_add_rule(rule);
+                }
+            }
+            ovs_rwlock_unlock(&table->cls.rwlock);
+        }
+    }
+
     if (p->ofproto_class->port_poll) {
         char *devname;
 
@@ -3790,20 +3824,6 @@ ofproto_rule_send_removed(struct rule *rule, uint8_t reason)
     connmgr_send_flow_removed(rule->ofproto->connmgr, &fr);
 }
 
-void
-ofproto_rule_update_used(struct rule *rule, long long int used)
-{
-    if (used > rule->used) {
-        struct eviction_group *evg = rule->eviction_group;
-
-        rule->used = used;
-        if (evg) {
-            heap_change(&evg->rules, &rule->evg_node,
-                        rule_eviction_priority(rule));
-        }
-    }
-}
-
 /* Sends an OpenFlow "flow removed" message with the given 'reason' (either
  * OFPRR_HARD_TIMEOUT or OFPRR_IDLE_TIMEOUT), and then removes 'rule' from its
  * ofproto.
@@ -3861,10 +3881,6 @@ ofproto_rule_reduce_timeouts(struct rule *rule,
     reduce_timeout(idle_timeout, &rule->idle_timeout);
     reduce_timeout(hard_timeout, &rule->hard_timeout);
     ovs_mutex_unlock(&rule->timeout_mutex);
-
-    if (!rule->eviction_group) {
-        eviction_group_add_rule(rule);
-    }
 }
 \f
 static enum ofperr