If the datapath doesn't dump a flow for some reason, and the current dump is expected to revalidate all flows in the datapath, then perform revalidation for those flows by fetching them during the sweep phase. If revalidation is not required, then leave the flow in the datapath and don't revalidate it.
Signed-off-by: Joe Stringer <joestrin...@nicira.com> --- v4: Minor adjustments to base against master. v3: No change. v2: Make the revalidator_sweep__() logic easier to read. Rebase. RFC: First post. --- ofproto/ofproto-dpif-upcall.c | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c index 2e58d94..df33643 100644 --- a/ofproto/ofproto-dpif-upcall.c +++ b/ofproto/ofproto-dpif-upcall.c @@ -46,6 +46,7 @@ VLOG_DEFINE_THIS_MODULE(ofproto_dpif_upcall); COVERAGE_DEFINE(upcall_duplicate_flow); +COVERAGE_DEFINE(revalidate_missed_dp_flow); /* A thread that reads upcalls from dpif, forwards each upcall's packet, * and possibly sets up a kernel flow as a cache. */ @@ -1440,6 +1441,27 @@ revalidate(struct revalidator *revalidator) dpif_flow_dump_thread_destroy(dump_thread); } +/* Called with exclusive access to 'revalidator' and 'ukey'. */ +static bool +handle_missed_revalidation(struct revalidator *revalidator, + struct udpif_key *ukey) + OVS_NO_THREAD_SAFETY_ANALYSIS +{ + struct udpif *udpif = revalidator->udpif; + struct dpif_flow flow; + struct ofpbuf *buf; + bool keep = false; + + COVERAGE_INC(revalidate_missed_dp_flow); + + if (!dpif_flow_get(udpif->dpif, ukey->key, ukey->key_len, &buf, &flow)) { + keep = revalidate_ukey(udpif, ukey, &flow); + ofpbuf_delete(buf); + } + + return keep; +} + static void revalidator_sweep__(struct revalidator *revalidator, bool purge) OVS_NO_THREAD_SAFETY_ANALYSIS @@ -1455,18 +1477,20 @@ revalidator_sweep__(struct revalidator *revalidator, bool purge) /* 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 (!ukey->flow_exists) { - ukey_delete(revalidator, ukey); - } else if (purge || ukey->dump_seq != dump_seq) { + if (ukey->flow_exists + && (purge + || (ukey->dump_seq != dump_seq + && revalidator->udpif->need_revalidate + && !handle_missed_revalidation(revalidator, ukey)))) { struct dump_op *op = &ops[n_ops++]; - /* If we have previously seen a flow in the datapath, but it - * hasn't been seen in the current dump, 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); n_ops = 0; } + } else if (!ukey->flow_exists) { + ukey_delete(revalidator, ukey); } } -- 1.7.10.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev