Skip to content

Commit 4c30b24

Browse files
cloftusgg17
authored andcommitted
dpif-netdev: Conditional EMC insert
Unconditional insertion of EMC entries results in EMC thrashing at high numbers of parallel flows. When this occurs, the performance of the EMC often falls below that of the dpcls classifier, rendering the EMC practically useless. Instead of unconditionally inserting entries into the EMC when a miss occurs, use a 1% probability of insertion. This ensures that the most frequent flows have the highest chance of creating an entry in the EMC, and the probability of thrashing the EMC is also greatly reduced. The probability of insertion is configurable, via the other_config:emc-insert-inv-prob option. This value sets the average probability of insertion to 1/emc-insert-inv-prob. For example the following command changes the insertion probability to (on average) 1 in every 20 packets ie. 1/20 ie. 5%. ovs-vsctl set Open_vSwitch . other_config:emc-insert-inv-prob=20 Signed-off-by: Ciara Loftus <ciara.loftus@intel.com> Signed-off-by: Georg Schmuecking <georg.schmuecking@ericsson.com> Co-authored-by: Georg Schmuecking <georg.schmuecking@ericsson.com> Acked-by: Kevin Traynor <ktraynor@redhat.com> Signed-off-by: Daniele Di Proietto <diproiettod@vmware.com>
1 parent 878b54d commit 4c30b24

6 files changed

Lines changed: 96 additions & 4 deletions

File tree

AUTHORS.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,7 @@ Eric Lopez elopez@nicira.com
385385
Frido Roose fr.roose@gmail.com
386386
Gaetano Catalli gaetano.catalli@gmail.com
387387
Gavin Remaley gavin_remaley@selinc.com
388+
Georg Schmuecking georg.schmuecking@ericsson.com
388389
George Shuklin amarao@desunote.ru
389390
Gerald Rogers gerald.rogers@intel.com
390391
Ghanem Bahri bahri.ghanem@gmail.com

Documentation/howto/dpdk.rst

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,26 @@ the `DPDK documentation
354354

355355
Note: Not all DPDK virtual PMD drivers have been tested and verified to work.
356356

357+
EMC Insertion Probability
358+
-------------------------
359+
By default 1 in every 100 flows are inserted into the Exact Match Cache (EMC).
360+
It is possible to change this insertion probability by setting the
361+
``emc-insert-inv-prob`` option::
362+
363+
$ ovs-vsctl --no-wait set Open_vSwitch . other_config:emc-insert-inv-prob=N
364+
365+
where:
366+
367+
``N``
368+
is a positive integer representing the inverse probability of insertion ie.
369+
on average 1 in every N packets with a unique flow will generate an EMC
370+
insertion.
371+
372+
If ``N`` is set to 1, an insertion will be performed for every flow. If set to
373+
0, no insertions will be performed and the EMC will effectively be disabled.
374+
375+
For more information on the EMC refer to :doc:`/intro/install/dpdk` .
376+
357377
.. _dpdk-ovs-in-guest:
358378

359379
OVS with DPDK Inside VMs

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ Post-v2.7.0
33
- Tunnels:
44
* Added support to set packet mark for tunnel endpoint using
55
`egress_pkt_mark` OVSDB option.
6+
- EMC insertion probability is reduced to 1% and is configurable via
7+
the new 'other_config:emc-insert-inv-prob' option.
68

79
v2.7.0 - xx xxx xxxx
810
---------------------

lib/dpif-netdev.c

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,11 @@ struct netdev_flow_key {
144144
#define EM_FLOW_HASH_MASK (EM_FLOW_HASH_ENTRIES - 1)
145145
#define EM_FLOW_HASH_SEGS 2
146146

147+
/* Default EMC insert probability is 1 / DEFAULT_EM_FLOW_INSERT_INV_PROB */
148+
#define DEFAULT_EM_FLOW_INSERT_INV_PROB 100
149+
#define DEFAULT_EM_FLOW_INSERT_MIN (UINT32_MAX / \
150+
DEFAULT_EM_FLOW_INSERT_INV_PROB)
151+
147152
struct emc_entry {
148153
struct dp_netdev_flow *flow;
149154
struct netdev_flow_key key; /* key.hash used for emc hash value. */
@@ -254,6 +259,9 @@ struct dp_netdev {
254259
uint64_t last_tnl_conf_seq;
255260

256261
struct conntrack conntrack;
262+
263+
/* Probability of EMC insertions is a factor of 'emc_insert_min'.*/
264+
OVS_ALIGNED_VAR(CACHE_LINE_SIZE) atomic_uint32_t emc_insert_min;
257265
};
258266

259267
static struct dp_netdev_port *dp_netdev_lookup_port(const struct dp_netdev *dp,
@@ -1066,6 +1074,8 @@ create_dp_netdev(const char *name, const struct dpif_class *class,
10661074

10671075
conntrack_init(&dp->conntrack);
10681076

1077+
atomic_init(&dp->emc_insert_min, DEFAULT_EM_FLOW_INSERT_MIN);
1078+
10691079
cmap_init(&dp->poll_threads);
10701080
ovs_mutex_init_recursive(&dp->non_pmd_mutex);
10711081
ovsthread_key_create(&dp->per_pmd_key, NULL);
@@ -1943,6 +1953,27 @@ emc_insert(struct emc_cache *cache, const struct netdev_flow_key *key,
19431953
emc_change_entry(to_be_replaced, flow, key);
19441954
}
19451955

1956+
static inline void
1957+
emc_probabilistic_insert(struct dp_netdev_pmd_thread *pmd,
1958+
const struct netdev_flow_key *key,
1959+
struct dp_netdev_flow *flow)
1960+
{
1961+
/* Insert an entry into the EMC based on probability value 'min'. By
1962+
* default the value is UINT32_MAX / 100 which yields an insertion
1963+
* probability of 1/100 ie. 1% */
1964+
1965+
uint32_t min;
1966+
atomic_read_relaxed(&pmd->dp->emc_insert_min, &min);
1967+
1968+
#ifdef DPDK_NETDEV
1969+
if (min && (key->hash ^ (uint32_t) pmd->last_cycles) <= min) {
1970+
#else
1971+
if (min && (key->hash ^ random_uint32()) <= min) {
1972+
#endif
1973+
emc_insert(&pmd->flow_cache, key, flow);
1974+
}
1975+
}
1976+
19461977
static inline struct dp_netdev_flow *
19471978
emc_lookup(struct emc_cache *cache, const struct netdev_flow_key *key)
19481979
{
@@ -2731,13 +2762,35 @@ dpif_netdev_set_config(struct dpif *dpif, const struct smap *other_config)
27312762
{
27322763
struct dp_netdev *dp = get_dp_netdev(dpif);
27332764
const char *cmask = smap_get(other_config, "pmd-cpu-mask");
2765+
unsigned long long insert_prob =
2766+
smap_get_ullong(other_config, "emc-insert-inv-prob",
2767+
DEFAULT_EM_FLOW_INSERT_INV_PROB);
2768+
uint32_t insert_min, cur_min;
27342769

27352770
if (!nullable_string_is_equal(dp->pmd_cmask, cmask)) {
27362771
free(dp->pmd_cmask);
27372772
dp->pmd_cmask = nullable_xstrdup(cmask);
27382773
dp_netdev_request_reconfigure(dp);
27392774
}
27402775

2776+
atomic_read_relaxed(&dp->emc_insert_min, &cur_min);
2777+
if (insert_prob <= UINT32_MAX) {
2778+
insert_min = insert_prob == 0 ? 0 : UINT32_MAX / insert_prob;
2779+
} else {
2780+
insert_min = DEFAULT_EM_FLOW_INSERT_MIN;
2781+
insert_prob = DEFAULT_EM_FLOW_INSERT_INV_PROB;
2782+
}
2783+
2784+
if (insert_min != cur_min) {
2785+
atomic_store_relaxed(&dp->emc_insert_min, insert_min);
2786+
if (insert_min == 0) {
2787+
VLOG_INFO("EMC has been disabled");
2788+
} else {
2789+
VLOG_INFO("EMC insertion probability changed to 1/%llu (~%.2f%%)",
2790+
insert_prob, (100 / (float)insert_prob));
2791+
}
2792+
}
2793+
27412794
return 0;
27422795
}
27432796

@@ -4193,8 +4246,7 @@ handle_packet_upcall(struct dp_netdev_pmd_thread *pmd, struct dp_packet *packet,
41934246
add_actions->size);
41944247
}
41954248
ovs_mutex_unlock(&pmd->flow_mutex);
4196-
4197-
emc_insert(&pmd->flow_cache, key, netdev_flow);
4249+
emc_probabilistic_insert(pmd, key, netdev_flow);
41984250
}
41994251
}
42004252

@@ -4217,7 +4269,6 @@ fast_path_processing(struct dp_netdev_pmd_thread *pmd,
42174269
struct dpcls *cls;
42184270
struct dpcls_rule *rules[PKT_ARRAY_SIZE];
42194271
struct dp_netdev *dp = pmd->dp;
4220-
struct emc_cache *flow_cache = &pmd->flow_cache;
42214272
int miss_cnt = 0, lost_cnt = 0;
42224273
int lookup_cnt = 0, add_lookup_cnt;
42234274
bool any_miss;
@@ -4288,7 +4339,7 @@ fast_path_processing(struct dp_netdev_pmd_thread *pmd,
42884339

42894340
flow = dp_netdev_flow_cast(rules[i]);
42904341

4291-
emc_insert(flow_cache, &keys[i], flow);
4342+
emc_probabilistic_insert(pmd, &keys[i], flow);
42924343
dp_netdev_queue_batches(packet, flow, &keys[i].mf, batches, n_batches);
42934344
}
42944345

tests/pmd.at

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ CHECK_PMD_THREADS_CREATED()
158158

159159
AT_CHECK([ovs-appctl vlog/set dpif_netdev:dbg])
160160
AT_CHECK([ovs-ofctl add-flow br0 action=normal])
161+
AT_CHECK([ovs-vsctl set Open_vSwitch . other_config:emc-insert-inv-prob=1])
161162

162163
sleep 1
163164

vswitchd/vswitch.xml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,23 @@
335335
datapaths.
336336
</p>
337337
</column>
338+
339+
<column name="other_config" key="emc-insert-inv-prob"
340+
type='{"type": "integer", "minInteger": 0, "maxInteger": 4294967295}'>
341+
<p>
342+
Specifies the inverse probability (1/emc-insert-inv-prob) of a flow
343+
being inserted into the Exact Match Cache (EMC). On average one in
344+
every <code>emc-insert-inv-prob</code> packets that generate a unique
345+
flow will cause an insertion into the EMC.
346+
347+
A value of 1 will result in an insertion for every flow (1/1 = 100%)
348+
whereas a value of zero will result in no insertions and essentially
349+
disable the EMC.
350+
</p>
351+
<p>
352+
Defaults to 100 ie. there is (1/100 =) 1% chance of EMC insertion.
353+
</p>
354+
</column>
338355
</group>
339356

340357
<group title="Status">

0 commit comments

Comments
 (0)