[ovs-dev] [PATCH] [patch v3] ofproto-dpif: Allow setting of flow eviction threshold

Simon Horman horms at verge.net.au
Thu Jul 28 23:10:57 UTC 2011


Allow setting the number of flows present in the flow hash
at which point eviction of entries from the kernel flow hash
will begin to occur.

The value may be set using a bridge's other-config column.

e.g.

ovs-vsctl set bridge br3 other-config:flow-eviction-threshold=10000

default is 1000, reflecting constant value previously used.

Increasing this value can result in reduced CPU usage and
packet loss in situations where the number of active flows
is significantly larger than 1000.

---

v3
As suggested by Ben Pfaff
* Coding Style: Use {} around statements inside "if".
* Style: End sentences with a full-stop in vswitch.xml

v2
As suggested by Ben Pfaff
* Ensure that the flow_eviction_threshold element of struct ofproto
  is always initialised by calling ofproto_set_flow_eviction_threshold()
  from ofproto_create()
* Limit the minimum value for threshold to 100
* Note that the flow_eviction_threshold element of struct ofproto
  only affects the ofproto-dpif implementation.
* Flesh out description in vswitch.xml to include motivation and,
  minimum and default values.
---
 ofproto/ofproto-dpif.c     |   16 +++++++++-------
 ofproto/ofproto-provider.h |    3 +++
 ofproto/ofproto.c          |   14 ++++++++++++++
 ofproto/ofproto.h          |    4 ++++
 vswitchd/bridge.c          |   18 ++++++++++++++++++
 vswitchd/vswitch.xml       |   15 +++++++++++++++
 6 files changed, 63 insertions(+), 7 deletions(-)

diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index a700d5e..0972298 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -1870,11 +1870,12 @@ facet_max_idle(const struct ofproto_dpif *ofproto)
      * N_BUCKETS buckets whose width is BUCKET_WIDTH msecs each.  Each facet
      * that is installed in the kernel gets dropped in the appropriate bucket.
      * After the histogram has been built, we compute the cutoff so that only
-     * the most-recently-used 1% of facets (but at least 1000 flows) are kept
-     * cached.  At least the most-recently-used bucket of facets is kept, so
-     * actually an arbitrary number of facets can be kept in any given
-     * expiration run (though the next run will delete most of those unless
-     * they receive additional data).
+     * the most-recently-used 1% of facets (but at least
+     * ofproto->up.flow_eviction_threshold flows) are kept cached.  At least
+     * the most-recently-used bucket of facets is kept, so actually an
+     * arbitrary number of facets can be kept in any given expiration run
+     * (though the next run will delete most of those unless they receive
+     * additional data).
      *
      * This requires a second pass through the facets, in addition to the pass
      * made by update_stats(), because the former function never looks
@@ -1889,7 +1890,7 @@ facet_max_idle(const struct ofproto_dpif *ofproto)
     int i;
 
     total = hmap_count(&ofproto->facets);
-    if (total <= 1000) {
+    if (total <= ofproto->up.flow_eviction_threshold) {
         return N_BUCKETS * BUCKET_WIDTH;
     }
 
@@ -1907,7 +1908,8 @@ facet_max_idle(const struct ofproto_dpif *ofproto)
     subtotal = bucket = 0;
     do {
         subtotal += buckets[bucket++];
-    } while (bucket < N_BUCKETS && subtotal < MAX(1000, total / 100));
+    } while (bucket < N_BUCKETS &&
+             subtotal < MAX(ofproto->up.flow_eviction_threshold, total / 100));
 
     if (VLOG_IS_DBG_ENABLED()) {
         struct ds s;
diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h
index 62fb035..fe0a616 100644
--- a/ofproto/ofproto-provider.h
+++ b/ofproto/ofproto-provider.h
@@ -38,6 +38,9 @@ struct ofproto {
     /* Settings. */
     uint64_t fallback_dpid;     /* Datapath ID if no better choice found. */
     uint64_t datapath_id;       /* Datapath ID. */
+    unsigned flow_eviction_threshold; /* Threshold at which to begin flow
+    				       * table eviction. Only effects the
+				       * ofproto-dpif implementation */
     char *mfr_desc;             /* Manufacturer. */
     char *hw_desc;              /* Hardware. */
     char *sw_desc;              /* Software version. */
diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
index 201488d..f40f995 100644
--- a/ofproto/ofproto.c
+++ b/ofproto/ofproto.c
@@ -320,6 +320,8 @@ ofproto_create(const char *datapath_name, const char *datapath_type,
     hmap_insert(&all_ofprotos, &ofproto->hmap_node,
                 hash_string(ofproto->name, 0));
     ofproto->datapath_id = 0;
+    ofproto_set_flow_eviction_threshold(ofproto,
+                                        OFPROTO_FLOW_EVICTON_THRESHOLD_DEFAULT);
     ofproto->fallback_dpid = pick_fallback_dpid();
     ofproto->mfr_desc = xstrdup(DEFAULT_MFR_DESC);
     ofproto->hw_desc = xstrdup(DEFAULT_HW_DESC);
@@ -407,6 +409,18 @@ ofproto_set_in_band_queue(struct ofproto *ofproto, int queue_id)
     connmgr_set_in_band_queue(ofproto->connmgr, queue_id);
 }
 
+/* Sets the number of flows at which eviction from the kernel flow table
+ * will occur. */
+void
+ofproto_set_flow_eviction_threshold(struct ofproto *ofproto, unsigned threshold)
+{
+    if (threshold < OFPROTO_FLOW_EVICTION_THRESHOLD_MIN) {
+        ofproto->flow_eviction_threshold = OFPROTO_FLOW_EVICTION_THRESHOLD_MIN;
+    } else {
+        ofproto->flow_eviction_threshold = threshold;
+    }
+}
+
 void
 ofproto_set_desc(struct ofproto *p,
                  const char *mfr_desc, const char *hw_desc,
diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h
index 53ed691..4975a8d 100644
--- a/ofproto/ofproto.h
+++ b/ofproto/ofproto.h
@@ -141,6 +141,9 @@ int ofproto_port_dump_done(struct ofproto_port_dump *);
           : (ofproto_port_dump_done(DUMP), false));         \
         )
 
+#define OFPROTO_FLOW_EVICTON_THRESHOLD_DEFAULT	1000
+#define OFPROTO_FLOW_EVICTION_THRESHOLD_MIN	100
+
 int ofproto_port_add(struct ofproto *, struct netdev *, uint16_t *ofp_portp);
 int ofproto_port_del(struct ofproto *, uint16_t ofp_port);
 
@@ -156,6 +159,7 @@ void ofproto_reconnect_controllers(struct ofproto *);
 void ofproto_set_extra_in_band_remotes(struct ofproto *,
                                        const struct sockaddr_in *, size_t n);
 void ofproto_set_in_band_queue(struct ofproto *, int queue_id);
+void ofproto_set_flow_eviction_threshold(struct ofproto *, unsigned threshold);
 void ofproto_set_desc(struct ofproto *,
                       const char *mfr_desc, const char *hw_desc,
                       const char *sw_desc, const char *serial_desc,
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c
index c331f1d..5056e48 100644
--- a/vswitchd/bridge.c
+++ b/vswitchd/bridge.c
@@ -148,6 +148,7 @@ static void bridge_add_ofproto_ports(struct bridge *);
 static void bridge_del_ofproto_ports(struct bridge *);
 static void bridge_refresh_ofp_port(struct bridge *);
 static void bridge_configure_datapath_id(struct bridge *);
+static void bridge_configure_flow_eviction_threshold(struct bridge *);
 static void bridge_configure_netflow(struct bridge *);
 static void bridge_configure_sflow(struct bridge *, int *sflow_bridge_number);
 static void bridge_configure_remotes(struct bridge *,
@@ -412,6 +413,7 @@ bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg)
         }
         bridge_configure_mirrors(br);
         bridge_configure_datapath_id(br);
+        bridge_configure_flow_eviction_threshold(br);
         bridge_configure_remotes(br, managers, n_managers);
         bridge_configure_netflow(br);
         bridge_configure_sflow(br, &sflow_bridge_number);
@@ -962,6 +964,22 @@ bridge_get_other_config(const struct ovsrec_bridge *br_cfg, const char *key)
                                 &ovsrec_bridge_col_other_config, key);
 }
 
+/* Set Flow eviction threshold */
+static void
+bridge_configure_flow_eviction_threshold(struct bridge *br)
+{
+    const char *threshold_str;
+    unsigned threshold;
+
+    threshold_str = bridge_get_other_config(br->cfg, "flow-eviction-threshold");
+    if (threshold_str) {
+        threshold = strtoul(threshold_str, NULL, 10);
+    } else {
+        threshold = OFPROTO_FLOW_EVICTON_THRESHOLD_DEFAULT;
+    }
+    ofproto_set_flow_eviction_threshold(br->ofproto, threshold);
+}
+
 static void
 bridge_pick_local_hw_addr(struct bridge *br, uint8_t ea[ETH_ADDR_LEN],
                           struct iface **hw_addr_iface)
diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml
index e72401f..b3029eb 100644
--- a/vswitchd/vswitch.xml
+++ b/vswitchd/vswitch.xml
@@ -438,6 +438,21 @@
             does not have QoS configured, or if the port does not have a queue
             with the specified ID, the default queue is used instead.
           </dd>
+          <dt><code>flow-eviction-threshold</code></dt>
+          <dd>
+            A number of flows as a nonnegative integer.  This sets number
+            of flows at which eviction from the kernel flow table will
+            be triggered.
+            If there are a large number of flows then increasing this
+            value to around the number of flows present
+            can result in reduced CPU usage and packet loss.
+	  </dd>
+	  <dd>
+            The default is 1000.
+	  </dd>
+	  <dd>
+            Values below 100 will be rounded up to 100.
+          </dd>
         </dl>
       </column>
     </group>
-- 
1.7.5.4




More information about the dev mailing list