Looks good to me. This certainly makes it easier to get reproducible performance results.
Acked-by: Joe Stringer <joestrin...@nicira.com> On 27 January 2014 16:50, Ethan Jackson <et...@nicira.com> wrote: > Before this patch, OVS tried to guess an optimal max idle time for > datapath flows based on the number of datapath flows relative to the > limit. This caused instability because the limit was based on the > dump duration which was affected by the max idle time. This patch > chooses instead to hardcode the max idle time to 1.5s except in > extreme case where the datapath flow limit is exceeded. 1.5s was > chosen to ensure pings occurring at once per second stay cached in the > datapath. > > Signed-off-by: Ethan Jackson <et...@nicira.com> > --- > ofproto/ofproto-dpif-upcall.c | 25 ++++--------------------- > tests/ofproto-dpif.at | 10 ++-------- > 2 files changed, 6 insertions(+), 29 deletions(-) > > diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c > index 24919db..9f761b8 100644 > --- a/ofproto/ofproto-dpif-upcall.c > +++ b/ofproto/ofproto-dpif-upcall.c > @@ -41,6 +41,7 @@ > #define MAX_QUEUE_LENGTH 512 > #define FLOW_MISS_MAX_BATCH 50 > #define REVALIDATE_MAX_BATCH 50 > +#define MAX_IDLE 1500 > > VLOG_DEFINE_THIS_MODULE(ofproto_dpif_upcall); > > @@ -125,7 +126,6 @@ struct udpif { > unsigned int avg_n_flows; > > /* Following fields are accessed and modified by different threads. */ > - atomic_llong max_idle; /* Maximum datapath flow idle > time. */ > atomic_uint flow_limit; /* Datapath flow hard limit. */ > > /* n_flows_mutex prevents multiple threads updating these > concurrently. */ > @@ -259,7 +259,6 @@ udpif_create(struct dpif_backer *backer, struct dpif > *dpif) > > udpif->dpif = dpif; > udpif->backer = backer; > - atomic_init(&udpif->max_idle, 5000); > atomic_init(&udpif->flow_limit, MIN(ofproto_flow_limit, 10000)); > udpif->secret = random_uint32(); > udpif->reval_seq = seq_create(); > @@ -283,7 +282,6 @@ udpif_destroy(struct udpif *udpif) > latch_destroy(&udpif->exit_latch); > seq_destroy(udpif->reval_seq); > seq_destroy(udpif->dump_seq); > - atomic_destroy(&udpif->max_idle); > atomic_destroy(&udpif->flow_limit); > atomic_destroy(&udpif->n_flows); > atomic_destroy(&udpif->n_flows_timestamp); > @@ -533,7 +531,6 @@ udpif_flow_dumper(void *arg) > struct dpif_flow_dump dump; > size_t key_len, mask_len; > unsigned int flow_limit; > - long long int max_idle; > bool need_revalidate; > uint64_t reval_seq; > size_t n_flows, i; > @@ -546,18 +543,6 @@ udpif_flow_dumper(void *arg) > udpif->max_n_flows = MAX(n_flows, udpif->max_n_flows); > udpif->avg_n_flows = (udpif->avg_n_flows + n_flows) / 2; > > - atomic_read(&udpif->flow_limit, &flow_limit); > - if (n_flows < flow_limit / 8) { > - max_idle = 5000; > - } else if (n_flows < flow_limit / 4) { > - max_idle = 2000; > - } else if (n_flows < flow_limit / 2) { > - max_idle = 1000; > - } else { > - max_idle = 500; > - } > - atomic_store(&udpif->max_idle, max_idle); > - > start_time = time_msec(); > dpif_flow_dump_start(&dump, udpif->dpif); > while (dpif_flow_dump_next(&dump, &key, &key_len, &mask, > &mask_len, > @@ -617,6 +602,7 @@ udpif_flow_dumper(void *arg) > > duration = time_msec() - start_time; > udpif->dump_duration = duration; > + atomic_read(&udpif->flow_limit, &flow_limit); > if (duration > 2000) { > flow_limit /= duration / 1000; > } else if (duration > 1300) { > @@ -633,7 +619,7 @@ udpif_flow_dumper(void *arg) > duration); > } > > - poll_timer_wait_until(start_time + MIN(max_idle, 500)); > + poll_timer_wait_until(start_time + MIN(MAX_IDLE, 500)); > seq_wait(udpif->reval_seq, udpif->last_reval_seq); > latch_wait(&udpif->exit_latch); > poll_block(); > @@ -1386,12 +1372,12 @@ revalidate_udumps(struct revalidator *revalidator, > struct list *udumps) > long long int max_idle; > bool must_del; > > - atomic_read(&udpif->max_idle, &max_idle); > atomic_read(&udpif->flow_limit, &flow_limit); > > n_flows = udpif_get_n_flows(udpif); > > must_del = false; > + max_idle = MAX_IDLE; > if (n_flows > flow_limit) { > must_del = n_flows > 2 * flow_limit; > max_idle = 100; > @@ -1526,17 +1512,14 @@ upcall_unixctl_show(struct unixctl_conn *conn, int > argc OVS_UNUSED, > > LIST_FOR_EACH (udpif, list_node, &all_udpifs) { > unsigned int flow_limit; > - long long int max_idle; > size_t i; > > atomic_read(&udpif->flow_limit, &flow_limit); > - atomic_read(&udpif->max_idle, &max_idle); > > ds_put_format(&ds, "%s:\n", dpif_name(udpif->dpif)); > ds_put_format(&ds, "\tflows : (current %"PRIu64")" > " (avg %u) (max %u) (limit %u)\n", udpif_get_n_flows(udpif), > udpif->avg_n_flows, udpif->max_n_flows, flow_limit); > - ds_put_format(&ds, "\tmax idle : %lldms\n", max_idle); > ds_put_format(&ds, "\tdump duration : %lldms\n", > udpif->dump_duration); > > ds_put_char(&ds, '\n'); > diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at > index 23a1f14..1348790 100644 > --- a/tests/ofproto-dpif.at > +++ b/tests/ofproto-dpif.at > @@ -2442,20 +2442,14 @@ AT_CHECK([ovs-ofctl add-flow br1 > actions=LOCAL,output:1,output:3]) > > for i in $(seq 1 10); do > ovs-appctl netdev-dummy/receive br0 > 'in_port(100),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' > - if [[ $i -eq 1 ]]; then > - sleep 1 > - fi > done > > for i in $(seq 1 5); do > ovs-appctl netdev-dummy/receive br1 > 'in_port(101),eth(src=50:54:00:00:00:07,dst=50:54:00:00:00:05),eth_type(0x0800),ipv4(src=192.168.0.2,dst=192.168.0.1,proto=1,tos=0,ttl=64,frag=no),icmp(type=8,code=0)' > - if [[ $i -eq 1 ]]; then > - sleep 1 > - fi > done > > -AT_CHECK([ovs-appctl time/warp 1000 && ovs-appctl time/warp 1000], [0], > [warped > -warped > +AT_CHECK([ovs-appctl time/warp 500], [0], > +[warped > ]) > > AT_CHECK([ovs-appctl dpif/show], [0], [dnl > -- > 1.8.1.2 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > http://openvswitch.org/mailman/listinfo/dev >
_______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev