vswitchd: Reduce flow idle time when flow table grows large.
authorBen Pfaff <blp@nicira.com>
Fri, 16 Jan 2009 18:37:13 +0000 (10:37 -0800)
committerBen Pfaff <blp@nicira.com>
Fri, 16 Jan 2009 18:37:13 +0000 (10:37 -0800)
This change halves the number of steady-state flows in the flow table
for hping3 --faster --quiet, from over 5000 to less than 2500.  It does
cause some oscillation in flow table size, because there is a harsh step
function in idle time when the flow table goes from 1000 to 1001 flows,
from 2001 to 2002 flows, and from 4003 to 4004 flows, but I doubt that is
a problem.  (If it is, we can introduce some randomness.)

vswitchd/bridge.c

index fd7deb27f3e9a1a29bf21f2587bda4c60354e5f2..9b88fcd487184ec6a71ac74129d6b228c069075b 100644 (file)
@@ -1084,6 +1084,27 @@ sanitize_opp(struct ofp_phy_port *opp)
     }
     opp->name[sizeof opp->name - 1] = '\0';
 }
+
+/* Returns the idle time that the bridge is currently using.  We reduce the
+ * idle time as the flow table grows, so as to act as a brake on further flow
+ * table growth. */
+static int
+bridge_idle_time(const struct bridge *br)
+{
+    int idle_time = br->flow_idle_time;
+    if (idle_time) {
+        size_t n_flows = hmap_count(&br->ft->flows);
+        int step = MAX(1, br->flow_idle_time / 5);
+        while (n_flows > 1000 && idle_time > 0) {
+            idle_time -= step;
+            n_flows /= 2;
+        }
+        if (idle_time < 1) {
+            idle_time = 1;
+        }
+    }
+    return idle_time;
+}
 \f
 /* Bridge packet processing functions. */
 
@@ -1580,7 +1601,7 @@ send_packets(struct bridge *br, const struct flow *flow,
             struct ofp_flow_mod *ofm;
             struct ofpbuf *fbuf;
 
-            fbuf = make_add_flow(flow, pkt->buffer_id, br->flow_idle_time,
+            fbuf = make_add_flow(flow, pkt->buffer_id, bridge_idle_time(br),
                                  actions_len);
             ofm = fbuf->data;
             ofm->command = htons(command);
@@ -1658,7 +1679,7 @@ process_flow(struct bridge *br, const struct flow *flow,
                          "interface %"PRIu16, br->name, in_ifidx); 
 
             queue_tx(br, make_add_flow(flow, pkt->buffer_id,
-                                       br->flow_idle_time, 0));
+                                       bridge_idle_time(br), 0));
             if (f) {
                 ftf_set_dsts(f, NULL, 0);
                 f->tags = tags;