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.
Signed-off-by: Joe Stringer <joestrin...@nicira.com> --- This relies on the mask dumping from the previous patch, but doesn't make use of batched flow_get. --- ofproto/ofproto-dpif-upcall.c | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c index df929d6..3fab2ec 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. */ @@ -1447,6 +1448,30 @@ 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 buffer; + uint64_t stub[1024 / 8]; + bool keep = false; + + COVERAGE_INC(revalidate_missed_dp_flow); + + ofpbuf_use_stub(&buffer, stub, sizeof stub); + if (!dpif_flow_get(udpif->dpif, ukey->key, ukey->key_len, &buffer, + &flow)) { + keep = revalidate_ukey(udpif, ukey, &flow); + } + ofpbuf_uninit(&buffer); + + return keep; +} + static void revalidator_sweep__(struct revalidator *revalidator, bool purge) OVS_NO_THREAD_SAFETY_ANALYSIS @@ -1462,18 +1487,21 @@ 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) { - bool missed_reval; + bool missed_reval, delete_flow; missed_reval = ukey->last_seen && need_revalidate; ukey->last_seen++; + delete_flow = purge || ukey->last_seen == MAX_UKEY_AGE; if (!ukey->flow_exists) { ukey_delete(revalidator, ukey); - } else if (purge || missed_reval || ukey->last_seen == MAX_UKEY_AGE) { + continue; + } else if (!delete_flow && missed_reval) { + delete_flow = handle_missed_revalidation(revalidator, ukey); + } + + if (delete_flow) { 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. */ 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 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev