[ovs-dev] [PATCH] revalidator: Replace ukey->mark with reval_seq.
Joe Stringer
joestringer at nicira.com
Mon May 19 21:12:19 UTC 2014
Rather than setting and resetting the 'mark' field in the ukey, this
patch introduces a seq to track whether a flow has been seen during the
most recent dump. This tidies the code and simplifies the logic for
detecting when flows are duplicated from the datapath.
Signed-off-by: Joe Stringer <joestringer at nicira.com>
---
ofproto/ofproto-dpif-upcall.c | 34 ++++++++++++++++++----------------
1 file changed, 18 insertions(+), 16 deletions(-)
diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c
index 522aa8c..6adc729 100644
--- a/ofproto/ofproto-dpif-upcall.c
+++ b/ofproto/ofproto-dpif-upcall.c
@@ -167,8 +167,7 @@ struct udpif_key {
struct ovs_mutex mutex; /* Guards the following. */
struct dpif_flow_stats stats OVS_GUARDED; /* Last known stats.*/
long long int created OVS_GUARDED; /* Estimate of creation time. */
- bool mark OVS_GUARDED; /* For mark and sweep garbage
- collection. */
+ uint64_t dump_seq OVS_GUARDED; /* Tracks udpif->dump_seq. */
bool flow_exists OVS_GUARDED; /* Ensures flows are only deleted
once. */
@@ -1131,7 +1130,7 @@ ukey_create(const struct nlattr *key, size_t key_len, long long int used)
ukey->key_len = key_len;
ovs_mutex_lock(&ukey->mutex);
- ukey->mark = false;
+ ukey->dump_seq = 0;
ukey->flow_exists = true;
ukey->created = used ? used : time_msec();
memset(&ukey->stats, 0, sizeof ukey->stats);
@@ -1441,6 +1440,7 @@ revalidate(struct revalidator *revalidator)
const struct nlattr *key, *mask, *actions;
size_t key_len, mask_len, actions_len;
const struct dpif_flow_stats *stats;
+ uint64_t dump_seq;
long long int now;
unsigned int flow_limit;
size_t n_ops;
@@ -1448,13 +1448,14 @@ revalidate(struct revalidator *revalidator)
n_ops = 0;
now = time_msec();
+ dump_seq = seq_read(udpif->dump_seq);
atomic_read(&udpif->flow_limit, &flow_limit);
dpif_flow_dump_state_init(udpif->dpif, &state);
while (dpif_flow_dump_next(&udpif->dump, state, &key, &key_len, &mask,
&mask_len, &actions, &actions_len, &stats)) {
struct udpif_key *ukey;
- bool mark, may_destroy;
+ bool keep, may_destroy;
long long int used, max_idle;
uint32_t hash;
size_t n_flows;
@@ -1466,7 +1467,7 @@ revalidate(struct revalidator *revalidator)
if (!used && ukey) {
ovs_mutex_lock(&ukey->mutex);
- if (ukey->mark || !ukey->flow_exists) {
+ if (ukey->dump_seq == dump_seq) {
/* The flow has already been dumped. This can occasionally
* occur if the datapath is changed in the middle of a flow
* dump. Rather than perform the same work twice, skip the
@@ -1480,6 +1481,7 @@ revalidate(struct revalidator *revalidator)
ovs_mutex_unlock(&ukey->mutex);
}
+ /* Delete flows more aggressively if over the limit. */
n_flows = udpif_get_n_flows(udpif);
max_idle = ofproto_max_idle;
if (n_flows > flow_limit) {
@@ -1487,7 +1489,7 @@ revalidate(struct revalidator *revalidator)
}
if ((used && used < now - max_idle) || n_flows > flow_limit * 2) {
- mark = false;
+ keep = false;
} else {
if (!ukey) {
ukey = ukey_create(key, key_len, used);
@@ -1500,17 +1502,18 @@ revalidate(struct revalidator *revalidator)
}
}
- mark = revalidate_ukey(udpif, ukey, mask, mask_len, actions,
+ keep = revalidate_ukey(udpif, ukey, mask, mask_len, actions,
actions_len, stats);
}
if (ukey) {
ovs_mutex_lock(&ukey->mutex);
- ukey->mark = ukey->flow_exists = mark;
+ ukey->dump_seq = dump_seq;
+ ukey->flow_exists = keep;
ovs_mutex_unlock(&ukey->mutex);
}
- if (!mark) {
+ if (!keep) {
dump_op_init(&ops[n_ops++], key, key_len, ukey);
}
@@ -1548,22 +1551,21 @@ revalidator_sweep__(struct revalidator *revalidator, bool purge)
struct dump_op ops[REVALIDATE_MAX_BATCH];
struct udpif_key *ukey, *next;
size_t n_ops;
+ uint64_t dump_seq;
n_ops = 0;
+ dump_seq = seq_read(revalidator->udpif->dump_seq);
/* During garbage collection, this revalidator completely owns its ukeys
* map, and therefore doesn't need to do any locking. */
HMAP_FOR_EACH_SAFE (ukey, next, hmap_node, revalidator->ukeys) {
- if (!purge && ukey->mark) {
- ukey->mark = false;
- } else if (!ukey->flow_exists) {
+ if (!ukey->flow_exists) {
ukey_delete(revalidator, ukey);
- } else {
+ } else if (purge || ukey->dump_seq != dump_seq) {
struct dump_op *op = &ops[n_ops++];
- /* If we have previously seen a flow in the datapath, but didn't
- * see it during the most recent dump, delete it. This allows us
- * to clean up the ukey and keep the statistics consistent. */
+ /* If we have previously seen a flow in the datapath, but it
+ * hasn't been revalidated with the current seq, delete it. */
dump_op_init(op, ukey->key, ukey->key_len, ukey);
if (n_ops == REVALIDATE_MAX_BATCH) {
push_dump_ops(revalidator, ops, n_ops);
--
1.7.10.4
More information about the dev
mailing list