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.
* 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
* 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
*
* This requires a second pass through the facets, in addition to the pass
* made by update_stats(), because the former function never looks
int i;
total = hmap_count(&ofproto->facets);
int i;
total = hmap_count(&ofproto->facets);
+ if (total <= ofproto->up.flow_eviction_threshold) {
return N_BUCKETS * BUCKET_WIDTH;
}
return N_BUCKETS * BUCKET_WIDTH;
}
subtotal = bucket = 0;
do {
subtotal += buckets[bucket++];
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;
if (VLOG_IS_DBG_ENABLED()) {
struct ds s;
/* Settings. */
uint64_t fallback_dpid; /* Datapath ID if no better choice found. */
uint64_t datapath_id; /* Datapath ID. */
/* 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 affects the
+ * ofproto-dpif implementation */
char *mfr_desc; /* Manufacturer. */
char *hw_desc; /* Hardware. */
char *sw_desc; /* Software version. */
char *mfr_desc; /* Manufacturer. */
char *hw_desc; /* Hardware. */
char *sw_desc; /* Software version. */
hmap_insert(&all_ofprotos, &ofproto->hmap_node,
hash_string(ofproto->name, 0));
ofproto->datapath_id = 0;
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);
ofproto->fallback_dpid = pick_fallback_dpid();
ofproto->mfr_desc = xstrdup(DEFAULT_MFR_DESC);
ofproto->hw_desc = xstrdup(DEFAULT_HW_DESC);
connmgr_set_in_band_queue(ofproto->connmgr, 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,
void
ofproto_set_desc(struct ofproto *p,
const char *mfr_desc, const char *hw_desc,
: (ofproto_port_dump_done(DUMP), false)); \
)
: (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);
int ofproto_port_add(struct ofproto *, struct netdev *, uint16_t *ofp_portp);
int ofproto_port_del(struct ofproto *, uint16_t ofp_port);
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_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,
void ofproto_set_desc(struct ofproto *,
const char *mfr_desc, const char *hw_desc,
const char *sw_desc, const char *serial_desc,
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_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 *,
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 *,
}
bridge_configure_mirrors(br);
bridge_configure_datapath_id(br);
}
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);
bridge_configure_remotes(br, managers, n_managers);
bridge_configure_netflow(br);
bridge_configure_sflow(br, &sflow_bridge_number);
&ovsrec_bridge_col_other_config, 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)
static void
bridge_pick_local_hw_addr(struct bridge *br, uint8_t ea[ETH_ADDR_LEN],
struct iface **hw_addr_iface)
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>
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>