diff options
| -rw-r--r-- | ofproto/ofproto-dpif.c | 16 | ||||
| -rw-r--r-- | ofproto/ofproto-provider.h | 3 | ||||
| -rw-r--r-- | ofproto/ofproto.c | 14 | ||||
| -rw-r--r-- | ofproto/ofproto.h | 4 | ||||
| -rw-r--r-- | vswitchd/bridge.c | 18 | ||||
| -rw-r--r-- | vswitchd/vswitch.xml | 15 |
6 files changed, 63 insertions, 7 deletions
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 8bd6f7529..cdc21bca6 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -1871,11 +1871,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 @@ -1890,7 +1891,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; } @@ -1908,7 +1909,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 62fb03534..be1e4de6c 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 affects 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 201488de4..f40f99590 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 53ed69128..4975a8d3b 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 35ee3e737..6a4ebe58d 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 e72401fdc..b3029eb26 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> |
