I couldn't measure a difference in TCP_CRR. I dropped that part of the message from the patch that I sent for master:
http://openvswitch.org/pipermail/dev/2014-May/040863.html On 28 May 2014 14:33, Joe Stringer <joestrin...@nicira.com> wrote: > Yeah, I'd like to get a gauge of this as well. I'll follow up on this. > > > On 28 May 2014 14:28, Ethan Jackson <et...@nicira.com> wrote: > >> Could we measure if this actually causes a performance degradation? >> I'd honestly be surprised if it does . . . My guess is our bottlenecks >> are elsewhere, but perhaps they aren't. >> >> Ethan >> >> On Tue, May 27, 2014 at 7:13 PM, Joe Stringer <joestrin...@nicira.com> >> wrote: >> > Thanks for the Ack, I pushed this to branch-2.3. >> > >> > I'd like to send a patch for master anyway, in part so that we ensure to >> > address this (fix the bug, and make the code more readable), and in part >> > because it still matters if newer userspace is used with an older >> kernel. >> > >> > >> > On 28 May 2014 13:52, Alex Wang <al...@nicira.com> wrote: >> >> >> >> Acked-by: Alex Wang <al...@nicira.com> >> >> >> >> >> >> For master, I'm about to refactor the datapath so that we never dump >> >> duplicated flows. So, I think we should consider refactoring master >> after >> >> that. >> >> >> >> >> >> Thanks, >> >> Alex Wang, >> >> >> >> >> >> On Tue, May 27, 2014 at 6:19 PM, Joe Stringer <joestrin...@nicira.com> >> >> wrote: >> >>> >> >>> A series of bugs have been identified recently that are caused by a >> >>> combination of the awkward flow dump API, possibility of duplicate >> flows >> >>> in a flow dump, and premature optimisation of the revalidator logic. >> >>> This patch attempts to simplify the revalidator logic by combining >> >>> multiple critical sections into one, which should make the state more >> >>> consistent. >> >>> >> >>> The new flow of logic is: >> >>> + Lookup the ukey. >> >>> + If the ukey doesn't exist, create it. >> >>> + Insert the ukey into the udpif. If we can't insert it, skip this >> flow. >> >>> + Lock the ukey. If we can't lock it, skip it. >> >>> + Determine if the ukey was already handled. If it has, skip it. >> >>> + Revalidate. >> >>> + Update ukey's fields (mark, flow_exists). >> >>> + Unlock the ukey. >> >>> >> >>> Previously, we would attempt process a flow without creating a ukey if >> >>> it hadn't been dumped before and it was due to be deleted. This patch >> >>> changes this to always create a ukey, allowing the ukey's >> >>> mutex to be used as the basis for preventing a flow from being handled >> >>> twice. This is expected to cause some minor performance regression for >> >>> cases like TCP_CRR, in favour of correctness and readability. >> >>> >> >>> Bug #1252997. >> >>> >> >>> Signed-off-by: Joe Stringer <joestrin...@nicira.com> >> >>> --- >> >>> ofproto/ofproto-dpif-upcall.c | 64 >> >>> ++++++++++++++++++----------------------- >> >>> 1 file changed, 28 insertions(+), 36 deletions(-) >> >>> >> >>> diff --git a/ofproto/ofproto-dpif-upcall.c >> >>> b/ofproto/ofproto-dpif-upcall.c >> >>> index 64444d9..906ccb4 100644 >> >>> --- a/ofproto/ofproto-dpif-upcall.c >> >>> +++ b/ofproto/ofproto-dpif-upcall.c >> >>> @@ -1205,6 +1205,7 @@ revalidate_ukey(struct udpif *udpif, struct >> >>> udpif_key *ukey, >> >>> const struct nlattr *mask, size_t mask_len, >> >>> const struct nlattr *actions, size_t actions_len, >> >>> const struct dpif_flow_stats *stats) >> >>> + OVS_REQUIRES(ukey->mutex) >> >>> { >> >>> uint64_t slow_path_buf[128 / 8]; >> >>> struct xlate_out xout, *xoutp; >> >>> @@ -1225,7 +1226,6 @@ revalidate_ukey(struct udpif *udpif, struct >> >>> udpif_key *ukey, >> >>> xoutp = NULL; >> >>> netflow = NULL; >> >>> >> >>> - ovs_mutex_lock(&ukey->mutex); >> >>> last_used = ukey->stats.used; >> >>> push.used = stats->used; >> >>> push.tcp_flags = stats->tcp_flags; >> >>> @@ -1236,11 +1236,6 @@ revalidate_ukey(struct udpif *udpif, struct >> >>> udpif_key *ukey, >> >>> ? stats->n_bytes - ukey->stats.n_bytes >> >>> : 0; >> >>> >> >>> - if (!ukey->flow_exists) { >> >>> - /* Don't bother revalidating if the flow was already >> deleted. */ >> >>> - goto exit; >> >>> - } >> >>> - >> >>> if (udpif->need_revalidate && last_used >> >>> && !should_revalidate(push.n_packets, last_used)) { >> >>> ok = false; >> >>> @@ -1320,7 +1315,6 @@ revalidate_ukey(struct udpif *udpif, struct >> >>> udpif_key *ukey, >> >>> ok = true; >> >>> >> >>> exit: >> >>> - ovs_mutex_unlock(&ukey->mutex); >> >>> if (netflow) { >> >>> if (!ok) { >> >>> netflow_expire(netflow, &flow); >> >>> @@ -1460,25 +1454,38 @@ revalidate(struct revalidator *revalidator) >> >>> ukey = ukey_lookup(udpif, key, key_len, hash); >> >>> >> >>> used = stats->used; >> >>> - if (ukey) { >> >>> - ovs_mutex_lock(&ukey->mutex); >> >>> - >> >>> - if (ukey->mark || !ukey->flow_exists) { >> >>> - /* 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 >> >>> - * flow this time. */ >> >>> - ovs_mutex_unlock(&ukey->mutex); >> >>> + if (!ukey) { >> >>> + ukey = ukey_create(key, key_len, used); >> >>> + if (!udpif_insert_ukey(udpif, ukey, hash)) { >> >>> + /* The same ukey has already been created. This means >> >>> that >> >>> + * another revalidator is processing this flow >> >>> + * concurrently, so don't bother processing it. */ >> >>> COVERAGE_INC(upcall_duplicate_flow); >> >>> + ukey_delete(NULL, ukey); >> >>> goto next; >> >>> } >> >>> + } >> >>> >> >>> - if (!used) { >> >>> - used = ukey->created; >> >>> - } >> >>> + if (ovs_mutex_trylock(&ukey->mutex)) { >> >>> + /* The flow has been dumped, and is being handled by >> another >> >>> + * revalidator concurrently. 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 flow this time. >> */ >> >>> + COVERAGE_INC(upcall_duplicate_flow); >> >>> + goto next; >> >>> + } >> >>> + >> >>> + if (ukey->mark || !ukey->flow_exists) { >> >>> + /* The flow has already been dumped and handled by >> another >> >>> + * revalidator during this flow dump operation. Skip it. >> */ >> >>> + COVERAGE_INC(upcall_duplicate_flow); >> >>> ovs_mutex_unlock(&ukey->mutex); >> >>> + goto next; >> >>> } >> >>> >> >>> + if (!used) { >> >>> + used = ukey->created; >> >>> + } >> >>> n_flows = udpif_get_n_flows(udpif); >> >>> max_idle = ofproto_max_idle; >> >>> if (n_flows > flow_limit) { >> >>> @@ -1488,30 +1495,15 @@ revalidate(struct revalidator *revalidator) >> >>> if ((used && used < now - max_idle) || n_flows > flow_limit >> * 2) >> >>> { >> >>> mark = false; >> >>> } else { >> >>> - if (!ukey) { >> >>> - ukey = ukey_create(key, key_len, used); >> >>> - if (!udpif_insert_ukey(udpif, ukey, hash)) { >> >>> - /* The same ukey has already been created. This >> >>> means that >> >>> - * another revalidator is processing this flow >> >>> - * concurrently, so don't bother processing it. >> */ >> >>> - ukey_delete(NULL, ukey); >> >>> - goto next; >> >>> - } >> >>> - } >> >>> - >> >>> mark = revalidate_ukey(udpif, ukey, mask, mask_len, >> actions, >> >>> actions_len, stats); >> >>> } >> >>> - >> >>> - if (ukey) { >> >>> - ovs_mutex_lock(&ukey->mutex); >> >>> - ukey->mark = ukey->flow_exists = mark; >> >>> - ovs_mutex_unlock(&ukey->mutex); >> >>> - } >> >>> + ukey->mark = ukey->flow_exists = mark; >> >>> >> >>> if (!mark) { >> >>> dump_op_init(&ops[n_ops++], key, key_len, ukey); >> >>> } >> >>> + ovs_mutex_unlock(&ukey->mutex); >> >>> >> >>> next: >> >>> may_destroy = >> dpif_flow_dump_next_may_destroy_keys(&udpif->dump, >> >>> -- >> >>> 1.7.10.4 >> >>> >> >> >> > >> > >> > _______________________________________________ >> > dev mailing list >> > dev@openvswitch.org >> > http://openvswitch.org/mailman/listinfo/dev >> > >> > >
_______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev