I think you're right.  I'll write up a patch.

Ethan

On Wed, Jan 29, 2014 at 4:39 PM, YAMAMOTO Takashi
<yamam...@valinux.co.jp> 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
>
> won't this re-introduce races workarounded by commit bf06c4fe?
>
> YAMAMOTO Takashi
>
>>
>> -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

Reply via email to