From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mx0a-00191d01.pphosted.com (mx0b-00191d01.pphosted.com [67.231.157.136]) by dpdk.org (Postfix) with ESMTP id 4BD341B03D for ; Wed, 3 Jan 2018 15:30:12 +0100 (CET) Received: from pps.filterd (m0049458.ppops.net [127.0.0.1]) by m0049458.ppops.net-00191d01. (8.16.0.21/8.16.0.21) with SMTP id w03ERRo3008571; Wed, 3 Jan 2018 09:30:11 -0500 Received: from alpi155.enaf.aldc.att.com (sbcsmtp7.sbc.com [144.160.229.24]) by m0049458.ppops.net-00191d01. with ESMTP id 2f8wf4bk84-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 03 Jan 2018 09:30:11 -0500 Received: from enaf.aldc.att.com (localhost [127.0.0.1]) by alpi155.enaf.aldc.att.com (8.14.5/8.14.5) with ESMTP id w03EUAk7028150; Wed, 3 Jan 2018 09:30:10 -0500 Received: from mlpi407.sfdc.sbc.com (mlpi407.sfdc.sbc.com [130.9.128.239]) by alpi155.enaf.aldc.att.com (8.14.5/8.14.5) with ESMTP id w03EU5g3027404 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Wed, 3 Jan 2018 09:30:07 -0500 Received: from zlp27128.vci.att.com (zlp27128.vci.att.com [135.66.87.50]) by mlpi407.sfdc.sbc.com (RSA Interceptor); Wed, 3 Jan 2018 14:29:48 GMT Received: from zlp27128.vci.att.com (zlp27128.vci.att.com [127.0.0.1]) by zlp27128.vci.att.com (Service) with ESMTP id 53CFC40006B6; Wed, 3 Jan 2018 14:29:48 +0000 (GMT) Received: from gbcdccas01.intl.att.com (unknown [135.76.180.9]) by zlp27128.vci.att.com (Service) with ESMTPS id DB5284000406; Wed, 3 Jan 2018 14:29:47 +0000 (GMT) Received: from GBCDCMBX03.intl.att.com ([135.76.31.134]) by gbcdccas01.intl.att.com ([135.76.180.9]) with mapi id 14.03.0361.001; Wed, 3 Jan 2018 14:29:45 +0000 From: "Dewar, Alan" To: "'Dumitrescu, Cristian'" , "'alangordondewar@gmail.com'" CC: "'dev@dpdk.org'" , "'Alan Dewar'" Thread-Topic: [PATCH v4] sched: make RED scaling configurable Thread-Index: AQHTPCkh2575WNSGDEy9pEaExW6DkKNhWVeAgAFmFmA= Date: Wed, 3 Jan 2018 14:29:44 +0000 Message-ID: <3F9268EEC0E43747A5FFFC6B48EF0321FBE645@gbcdcmbx03.intl.att.com> References: <1505913120-5521-1-git-send-email-alan.dewar@att.com> <1507022514-21831-1-git-send-email-alan.dewar@att.com> <3EB4FA525960D640B5BDFFD6A3D891267BAF7F2A@IRSMSX108.ger.corp.intel.com> In-Reply-To: <3EB4FA525960D640B5BDFFD6A3D891267BAF7F2A@IRSMSX108.ger.corp.intel.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [135.160.174.41] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-RSA-Inspected: yes X-RSA-Classifications: public X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2018-01-03_10:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_policy_notspam policy=outbound_policy score=0 priorityscore=1501 malwarescore=0 suspectscore=0 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 mlxscore=0 impostorscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1711220000 definitions=main-1801030203 X-Mailman-Approved-At: Thu, 04 Jan 2018 10:34:23 +0100 Subject: Re: [dpdk-dev] [PATCH v4] sched: make RED scaling configurable X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 03 Jan 2018 14:30:13 -0000 Hi Cristian, > -----Original Message----- > From: Dumitrescu, Cristian [mailto:cristian.dumitrescu@intel.com]=20 > Sent: Tuesday, January 02, 2018 4:44 PM > To: alangordondewar@gmail.com > Cc: dev@dpdk.org; Alan Dewar > Subject: RE: [PATCH v4] sched: make RED scaling configurable > > Hi Alan, > > Thanks for your work! Thanks for the review ;^) - my responses are in-line below. Regards Alan > I do have some comments (see below), but generally looks good to me. > > > -----Original Message----- > > From: alangordondewar@gmail.com [mailto:alangordondewar@gmail.com] > > Sent: Tuesday, October 3, 2017 10:22 AM > > To: Dumitrescu, Cristian > > Cc: dev@dpdk.org; Alan Dewar > > Subject: [PATCH v4] sched: make RED scaling configurable > >=20 > > From: Alan Dewar > >=20 > > The RED code stores the weighted moving average in a 32-bit integer as= =20 > > a pseudo fixed-point floating number with 10 fractional bits. Twelve=20 > > other bits are used to encode the filter weight, leaving just 10 bits=20 > > for the queue length. This limits the maximum queue length supported=20 > > by RED queues to 1024 packets. > >=20 > > Introduce a new API to allow the RED scaling factor to be configured=20 > > based upon maximum queue length. If this API is not called, the RED=20 > > scaling factor remains at its default value. > >=20 > > Added some new RED scaling unit-tests to test with RED queue-lengths=20 > > up to 8192 packets long. > >=20 > > Signed-off-by: Alan Dewar > > --- > > lib/librte_sched/rte_red.c | 53 ++++++- > > lib/librte_sched/rte_red.h | 63 ++++++-- > > lib/librte_sched/rte_sched_version.map | 6 + > > test/test/test_red.c | 274 > > ++++++++++++++++++++++++++++++++- > > 4 files changed, 374 insertions(+), 22 deletions(-) > >=20 > > diff --git a/lib/librte_sched/rte_red.c b/lib/librte_sched/rte_red.c=20 > > index ade57d1..0dc8d28 100644 > > --- a/lib/librte_sched/rte_red.c > > +++ b/lib/librte_sched/rte_red.c > > @@ -43,6 +43,8 @@ > > static int rte_red_init_done =3D 0; /**< Flag to indicate that glo= bal > > initialisation is done */ > > uint32_t rte_red_rand_val =3D 0; /**< Random value cache */ > > uint32_t rte_red_rand_seed =3D 0; /**< Seed for random number > > generation */ > > +uint8_t rte_red_scaling =3D RTE_RED_SCALING_DEFAULT; uint16_t=20 > > +rte_red_max_threshold =3D RTE_RED_DEFAULT_QUEUE_LENGTH - > > 1; > >=20 > > /** > > * table[i] =3D log2(1-Wq) * Scale * -1 @@ -66,7 +68,7 @@=20 > > __rte_red_init_tables(void) > > double scale =3D 0.0; > > double table_size =3D 0.0; > >=20 > > - scale =3D (double)(1 << RTE_RED_SCALING); > > + scale =3D (double)(1 << rte_red_scaling); > > table_size =3D (double)(RTE_DIM(rte_red_pow2_frac_inv)); > >=20 > > for (i =3D 0; i < RTE_DIM(rte_red_pow2_frac_inv); i++) { @@ -119,7=20 > > +121,7 @@ rte_red_config_init(struct rte_red_config *red_cfg, > > if (red_cfg =3D=3D NULL) { > > return -1; > > } > > - if (max_th > RTE_RED_MAX_TH_MAX) { > > + if (max_th > rte_red_max_threshold) { > > return -2; > > } > > if (min_th >=3D max_th) { > > @@ -148,11 +150,52 @@ rte_red_config_init(struct rte_red_config=20 > > *red_cfg, > > rte_red_init_done =3D 1; > > } > >=20 > > - red_cfg->min_th =3D ((uint32_t) min_th) << (wq_log2 + > > RTE_RED_SCALING); > > - red_cfg->max_th =3D ((uint32_t) max_th) << (wq_log2 + > > RTE_RED_SCALING); > > - red_cfg->pa_const =3D (2 * (max_th - min_th) * maxp_inv) << > > RTE_RED_SCALING; > > + red_cfg->min_th =3D ((uint32_t) min_th) << (wq_log2 + > > rte_red_scaling); > > + red_cfg->max_th =3D ((uint32_t) max_th) << (wq_log2 + > > rte_red_scaling); > > + red_cfg->pa_const =3D (2 * (max_th - min_th) * maxp_inv) << > > + rte_red_scaling; > > red_cfg->maxp_inv =3D maxp_inv; > > red_cfg->wq_log2 =3D wq_log2; > >=20 > > return 0; > > } > > + > > +int > > +rte_red_set_scaling(uint16_t max_red_queue_length) { > > + int8_t count; > > + > > + if (rte_red_init_done) > > + /** > > + * Can't change the scaling once the red table has been > > + * computed. > > + */ > > + return -1; > > + > > + if (max_red_queue_length < RTE_RED_MIN_QUEUE_LENGTH) > > + return -2; > > + > > + if (max_red_queue_length > RTE_RED_MAX_QUEUE_LENGTH) > > + return -3; > > + > > + if (!rte_is_power_of_2(max_red_queue_length)) > > + return -4; > > + > > + count =3D 0; > > + while (max_red_queue_length !=3D 0) { > > + max_red_queue_length >>=3D 1; > > + count++; > > + } > > + > > + rte_red_scaling -=3D count - RTE_RED_SCALING_DEFAULT; > > + rte_red_max_threshold =3D max_red_queue_length - 1; > > + return 0; > > +} > > + > > +void > > +rte_red_reset_scaling(void) > > +{ > > + rte_red_init_done =3D 0; > > + rte_red_scaling =3D RTE_RED_SCALING_DEFAULT; > > + rte_red_max_threshold =3D RTE_RED_DEFAULT_QUEUE_LENGTH - 1; } > > Why do we need this function? These global variables are already initiali= zed at the top of the file.=20 > > My vote is to remove it.=20 It is needed by the revised unit-test program that has to reinitialize the = RED code for each sub-test. > > diff --git a/lib/librte_sched/rte_red.h b/lib/librte_sched/rte_red.h=20 > > index ca12227..be1fb0f 100644 > > --- a/lib/librte_sched/rte_red.h > > +++ b/lib/librte_sched/rte_red.h > > @@ -52,14 +52,31 @@ extern "C" { > > #include > > #include > >=20 > > -#define RTE_RED_SCALING 10 /**< Fraction s= ize for fixed- > > point */ > > -#define RTE_RED_S (1 << 22) /**< Packet siz= e multiplied > > by number of leaf queues */ > > -#define RTE_RED_MAX_TH_MAX 1023 /**< Max thresh= old > > limit in fixed point format */ > > -#define RTE_RED_WQ_LOG2_MIN 1 /**< Min invers= e filter > > weight value */ > > -#define RTE_RED_WQ_LOG2_MAX 12 /**< Max invers= e > > filter weight value */ > > -#define RTE_RED_MAXP_INV_MIN 1 /**< Min invers= e mark > > probability value */ > > -#define RTE_RED_MAXP_INV_MAX 255 /**< Max invers= e > > mark probability value */ > > -#define RTE_RED_2POW16 (1<<16) /**< 2 power 16= */ > > +/**< Default fraction size for fixed-point */ > > +#define RTE_RED_SCALING_DEFAULT 10 > > Let's keep the name of this macro undchanges, i.e. RTE_RED_SCALING. IMO i= t is ckear enough this is the default value (also > stated in the comment). Okay will do. > > + > > +/**< Packet size multiplied by number of leaf queues */ > > +#define RTE_RED_S (1 << 22) > > + > > +/**< Minimum, default and maximum RED queue length */ > > +#define RTE_RED_MIN_QUEUE_LENGTH 64 > > +#define RTE_RED_DEFAULT_QUEUE_LENGTH 1024 > > +#define RTE_RED_MAX_QUEUE_LENGTH 8192 > > + > > +/**< Min inverse filter weight value */ > > +#define RTE_RED_WQ_LOG2_MIN 1 > > + > > +/**< Max inverse filter weight value */ > > +#define RTE_RED_WQ_LOG2_MAX 12 > > + > > +/**< Min inverse mark probability value */ > > +#define RTE_RED_MAXP_INV_MIN 1 > > + > > +/**< Max inverse mark probability value */ > > +#define RTE_RED_MAXP_INV_MAX 255 > > + > > +/**< 2 power 16 */ > > +#define RTE_RED_2POW16 (1<<16) > > #define RTE_RED_INT16_NBITS (sizeof(uint16_t) * CHAR_B= IT) > > #define RTE_RED_WQ_LOG2_NUM (RTE_RED_WQ_LOG2_MAX - > > RTE_RED_WQ_LOG2_MIN + 1) > >=20 > > All the above Doxygen comments are incorrectly formatted: as you want to = change their behavior to refer to the variable _after_ the comment, they ha= ve to start with /**, not with /**< (which should be used if the comment re= fers to the variable _before_ the comment). Please fix. Will do. > > @@ -71,6 +88,8 @@ extern uint32_t rte_red_rand_val; extern uint32_t=20 > > rte_red_rand_seed; extern uint16_t=20 > > rte_red_log2_1_minus_Wq[RTE_RED_WQ_LOG2_NUM]; > > extern uint16_t rte_red_pow2_frac_inv[16]; > > +extern uint8_t rte_red_scaling; > > +extern uint16_t rte_red_max_threshold; > >=20 > > /** > > * RED configuration parameters passed by user @@ -137,6 +156,26 @@=20 > > rte_red_config_init(struct rte_red_config *red_cfg, > > const uint16_t maxp_inv); > >=20 > > /** > > + * @brief Configures the global setting for the RED scaling factor > > + * > > + * @param max_red_queue_length [in] must be a power of two > > + * > > + * @return Operation status > > + * @retval 0 success > > + * @retval !0 error > > + */ > > +int > > +rte_red_set_scaling(uint16_t max_red_queue_length); > > + > > +/** > > + * @brief Reset the RED scaling factor - only for use by RED=20 > > +unit-tests > > + * > > + * @return Operation status > > + */ > > +void > > +rte_red_reset_scaling(void); > > As stated above, this function is probably not useful and my vote is to r= emove it.=20 > It is needed by the revised unit-test program. This function can't be move= d into the unit-test program because it needs to reset variables that are s= tatically declared within rte_red.c > > + > > +/** > > * @brief Generate random number for RED > > * > > * Implemenetation based on: > > @@ -206,7 +245,7 @@ __rte_red_calc_qempty_factor(uint8_t wq_log2,=20 > > uint16_t m) > > f =3D (n >> 6) & 0xf; > > n >>=3D 10; > >=20 > > - if (n < RTE_RED_SCALING) > > + if (n < rte_red_scaling) > > return (uint16_t) ((rte_red_pow2_frac_inv[f] + (1 << (n - 1))) > > >> n); > >=20 > > return 0; > > @@ -258,7 +297,9 @@ rte_red_enqueue_empty(const struct rte_red_config=20 > > *red_cfg, > > if (m >=3D RTE_RED_2POW16) { > > red->avg =3D 0; > > } else { > > - red->avg =3D (red->avg >> RTE_RED_SCALING) * > > __rte_red_calc_qempty_factor(red_cfg->wq_log2, (uint16_t) m); > > + red->avg =3D (red->avg >> rte_red_scaling) * > > + __rte_red_calc_qempty_factor(red_cfg->wq_log2, > > + (uint16_t) m); > > } > >=20 > > return 0; > > @@ -365,7 +406,7 @@ rte_red_enqueue_nonempty(const struct=20 > > rte_red_config *red_cfg, > > */ > >=20 > > /* avg update */ > > - red->avg +=3D (q << RTE_RED_SCALING) - (red->avg >> red_cfg- > > >wq_log2); > > + red->avg +=3D (q << rte_red_scaling) - (red->avg >> red_cfg- > > >wq_log2); > >=20 > > /* avg < min_th: do not mark the packet */ > > if (red->avg < red_cfg->min_th) { > > diff --git a/lib/librte_sched/rte_sched_version.map > > b/lib/librte_sched/rte_sched_version.map > > index 3aa159a..92e51f8 100644 > > --- a/lib/librte_sched/rte_sched_version.map > > +++ b/lib/librte_sched/rte_sched_version.map > > @@ -29,3 +29,9 @@ DPDK_2.1 { > > rte_sched_port_pkt_read_color; > >=20 > > } DPDK_2.0; > > + > > +DPDK_17.08 { > > + global; > > + > > + rte_red_set_scaling; > > +} DPDK_2.1; > > diff --git a/test/test/test_red.c b/test/test/test_red.c index=20 > > 348075d..f2d50ef 100644 > > --- a/test/test/test_red.c > > +++ b/test/test/test_red.c > > @@ -67,6 +67,7 @@ struct test_rte_red_config { /**< Test structu= re > > for RTE_RED config */ > > uint32_t min_th; /**< Queue minimum threshold */ > > uint32_t max_th; /**< Queue maximum threshold */ > > uint8_t *maxp_inv; /**< Inverse mark probability */ > > + uint16_t max_queue_len; /**< Maximum queue length */ > > }; > >=20 > > struct test_queue { /**< Test structure for RTE_RED Qu= eues */ > > @@ -181,7 +182,7 @@ static uint32_t rte_red_get_avg_int(const struct=20 > > rte_red_config *red_cfg, > > /** > > * scale by 1/n and convert from fixed-point to integer > > */ > > - return red->avg >> (RTE_RED_SCALING + red_cfg->wq_log2); > > + return red->avg >> (rte_red_scaling + red_cfg->wq_log2); > > } > >=20 > > static double rte_red_get_avg_float(const struct rte_red_config=20 > > *red_cfg, @@ -190,7 +191,7 @@ static double=20 > > rte_red_get_avg_float(const struct rte_red_config *red_cfg, > > /** > > * scale by 1/n and convert from fixed-point to floating-point > > */ > > - return ldexp((double)red->avg, -(RTE_RED_SCALING + red_cfg- > > >wq_log2)); > > + return ldexp((double)red->avg, -(rte_red_scaling + red_cfg- > > >wq_log2)); > > } > >=20 > > static void rte_red_set_avg_int(const struct rte_red_config *red_cfg,= =20 > > @@ -200,7 +201,7 @@ static void rte_red_set_avg_int(const struct=20 > > rte_red_config *red_cfg, > > /** > > * scale by n and convert from integer to fixed-point > > */ > > - red->avg =3D avg << (RTE_RED_SCALING + red_cfg->wq_log2); > > + red->avg =3D avg << (rte_red_scaling + red_cfg->wq_log2); > > } > >=20 > > static double calc_exp_avg_on_empty(double avg, uint32_t n, uint32_t > > time_diff) > > @@ -280,10 +281,23 @@ static enum test_result =20 > > test_rte_red_init(struct test_config *tcfg) { > > unsigned i =3D 0; > > + int ret; > >=20 > > tcfg->tvar->clk_freq =3D rte_get_timer_hz(); > > init_port_ts( tcfg->tvar->clk_freq ); > >=20 > > + rte_red_reset_scaling(); > > + ret =3D rte_red_set_scaling(tcfg->tconfig->max_queue_len); > > + if (ret) { > > + printf("rte_red_set_scaling failed: %d\n", ret); > > + return FAIL; > > + } > > + if (rte_red_max_threshold < tcfg->tconfig->max_th) { > > + printf("rte_red_max_th (%u) < tconfig->max_th (%u)\n", > > + rte_red_max_threshold, tcfg->tconfig->max_th); > > + return FAIL; > > + } > > + > > for (i =3D 0; i < tcfg->tconfig->num_cfg; i++) { > > if (rte_red_config_init(&tcfg->tconfig->rconfig[i], > > (uint16_t)tcfg->tconfig->wq_log2[i], > > @@ -385,6 +399,7 @@ static struct test_rte_red_config ft_tconfig =3D { > > .min_th =3D 32, > > .max_th =3D 128, > > .maxp_inv =3D ft_maxp_inv, > > + .max_queue_len =3D RTE_RED_DEFAULT_QUEUE_LENGTH, > > }; > >=20 > > static struct test_queue ft_tqueue =3D { @@ -554,6 +569,7 @@ static=20 > > struct test_rte_red_config ft2_tconfig =3D { > > .min_th =3D 32, > > .max_th =3D 128, > > .maxp_inv =3D ft2_maxp_inv, > > + .max_queue_len =3D RTE_RED_DEFAULT_QUEUE_LENGTH, > > }; > >=20 > > static struct test_config func_test2_config =3D { @@ -576,6 +592,41 @@= =20 > > static struct test_config func_test2_config =3D { > > .tlevel =3D ft2_tlevel, > > }; > >=20 > > +/** > > + * Test F2: functional test 2 - with long queues and smaller=20 > > +red-scaling > > factor > > + */ > > +static uint32_t ft2_tlevel_scaling[] =3D {8190}; > > + > > +static struct test_rte_red_config ft2_tconfig_scaling =3D { > > + .rconfig =3D ft2_rconfig, > > + .num_cfg =3D RTE_DIM(ft2_rconfig), > > + .wq_log2 =3D ft2_wq_log2, > > + .min_th =3D 32, > > + .max_th =3D 8191, > > + .maxp_inv =3D ft2_maxp_inv, > > + .max_queue_len =3D 8192, > > +}; > > + > > +static struct test_config func_test2_config_scaling =3D { > > + .ifname =3D "functional test 2 interface", > > + .msg =3D "functional test 2 : use several RED configurations and long > > queues,\n" > > + " increase average queue size to just below > > maximum threshold,\n" > > + " compare drop rate to drop probability\n\n", > > + .htxt =3D "RED config " > > + "avg queue size " > > + "min threshold " > > + "max threshold " > > + "drop prob % " > > + "drop rate % " > > + "diff % " > > + "tolerance % " > > + "\n", > > + .tconfig =3D &ft2_tconfig_scaling, > > + .tqueue =3D &ft_tqueue, > > + .tvar =3D &ft_tvar, > > + .tlevel =3D ft2_tlevel_scaling, > > +}; > > + > > static enum test_result func_test2(struct test_config *tcfg) { > > enum test_result result =3D PASS; > > @@ -662,6 +713,7 @@ static struct test_rte_red_config ft3_tconfig =3D = { > > .min_th =3D 32, > > .max_th =3D 1023, > > .maxp_inv =3D ft_maxp_inv, > > + .max_queue_len =3D RTE_RED_DEFAULT_QUEUE_LENGTH, > > }; > >=20 > > static struct test_config func_test3_config =3D { @@ -683,6 +735,40 @@= =20 > > static struct test_config func_test3_config =3D { > > .tlevel =3D ft3_tlevel, > > }; > >=20 > > +/** > > + * Test F3: functional test 3 - with large queues and smaller red=20 > > +scaling > > factor > > + */ > > +static uint32_t ft3_tlevel_scaling[] =3D {8190}; > > + > > +static struct test_rte_red_config ft3_tconfig_scaling =3D { > > + .rconfig =3D ft_wrconfig, > > + .num_cfg =3D RTE_DIM(ft_wrconfig), > > + .wq_log2 =3D ft_wq_log2, > > + .min_th =3D 32, > > + .max_th =3D 8191, > > + .maxp_inv =3D ft_maxp_inv, > > + .max_queue_len =3D 8192, > > +}; > > + > > +static struct test_config func_test3_config_scaling =3D { > > + .ifname =3D "functional test 3 interface", > > + .msg =3D "functional test 3 : use one RED configuration and long > > queues,\n" > > + " increase average queue size to target level,\n" > > + " dequeue all packets until queue is empty,\n" > > + " confirm that average queue size is computed > > correctly while queue is empty\n\n", > > + .htxt =3D "q avg before " > > + "q avg after " > > + "expected " > > + "difference % " > > + "tolerance % " > > + "result " > > + "\n", > > + .tconfig =3D &ft3_tconfig_scaling, > > + .tqueue =3D &ft_tqueue, > > + .tvar =3D &ft_tvar, > > + .tlevel =3D ft3_tlevel_scaling, > > +}; > > + > > static enum test_result func_test3(struct test_config *tcfg) { > > enum test_result result =3D PASS; > > @@ -776,6 +862,7 @@ static struct test_rte_red_config ft4_tconfig =3D = { > > .max_th =3D 1023, > > .wq_log2 =3D ft4_wq_log2, > > .maxp_inv =3D ft_maxp_inv, > > + .max_queue_len =3D RTE_RED_DEFAULT_QUEUE_LENGTH, > > }; > >=20 > > static struct test_queue ft4_tqueue =3D { @@ -810,6 +897,42 @@ static= =20 > > struct test_config func_test4_config =3D { > > .tlevel =3D ft4_tlevel, > > }; > >=20 > > +/** > > + * Test F4: functional test 4 > > + */ > > +static uint32_t ft4_tlevel_scaling[] =3D {8190}; > > + > > +static struct test_rte_red_config ft4_tconfig_scaling =3D { > > + .rconfig =3D ft_wrconfig, > > + .num_cfg =3D RTE_DIM(ft_wrconfig), > > + .min_th =3D 32, > > + .max_th =3D 8191, > > + .wq_log2 =3D ft4_wq_log2, > > + .maxp_inv =3D ft_maxp_inv, > > + .max_queue_len =3D 8192, > > +}; > > + > > +static struct test_config func_test4_config_scaling =3D { > > + .ifname =3D "functional test 4 interface", > > + .msg =3D "functional test 4 : use one RED configuration on long > > queue,\n" > > + " increase average queue size to target level,\n" > > + " dequeue all packets until queue is empty,\n" > > + " confirm that average queue size is computed > > correctly while\n" > > + " queue is empty for more than 50 sec,\n" > > + " (this test takes 52 sec to run)\n\n", > > + .htxt =3D "q avg before " > > + "q avg after " > > + "expected " > > + "difference % " > > + "tolerance % " > > + "result " > > + "\n", > > + .tconfig =3D &ft4_tconfig_scaling, > > + .tqueue =3D &ft4_tqueue, > > + .tvar =3D &ft_tvar, > > + .tlevel =3D ft4_tlevel_scaling, > > +}; > > + > > static enum test_result func_test4(struct test_config *tcfg) { > > enum test_result result =3D PASS; > > @@ -924,6 +1047,7 @@ static struct test_rte_red_config ft5_tconfig =3D = { > > .max_th =3D 128, > > .wq_log2 =3D ft5_wq_log2, > > .maxp_inv =3D ft5_maxp_inv, > > + .max_queue_len =3D RTE_RED_DEFAULT_QUEUE_LENGTH, > > }; > >=20 > > static struct test_queue ft5_tqueue =3D { @@ -970,6 +1094,45 @@ static= =20 > > struct test_config func_test5_config =3D { > > .tlevel =3D ft5_tlevel, > > }; > >=20 > > + > > +/** > > + * Test F5: functional test 5 > > + */ > > +static uint32_t ft5_tlevel_scaling[] =3D {8190}; > > + > > +static struct test_rte_red_config ft5_tconfig_scaling =3D { > > + .rconfig =3D ft5_config, > > + .num_cfg =3D RTE_DIM(ft5_config), > > + .min_th =3D 32, > > + .max_th =3D 8191, > > + .wq_log2 =3D ft5_wq_log2, > > + .maxp_inv =3D ft5_maxp_inv, > > + .max_queue_len =3D 8192, > > +}; > > + > > +static struct test_config func_test5_config_scaling =3D { > > + .ifname =3D "functional test 5 interface", > > + .msg =3D "functional test 5 : use several long queues (each with its > > own run-time data),\n" > > + " use several RED configurations (such that each > > configuration is shared by multiple queues),\n" > > + " increase average queue size to just below > > maximum threshold,\n" > > + " compare drop rate to drop probability,\n" > > + " (this is a larger scale version of functional test > > 2)\n\n", > > + .htxt =3D "queue " > > + "config " > > + "avg queue size " > > + "min threshold " > > + "max threshold " > > + "drop prob % " > > + "drop rate % " > > + "diff % " > > + "tolerance % " > > + "\n", > > + .tconfig =3D &ft5_tconfig_scaling, > > + .tqueue =3D &ft5_tqueue, > > + .tvar =3D &ft5_tvar, > > + .tlevel =3D ft5_tlevel_scaling, > > +}; > > + > > static enum test_result func_test5(struct test_config *tcfg) { > > enum test_result result =3D PASS; > > @@ -1062,6 +1225,7 @@ static struct test_rte_red_config ft6_tconfig =3D= { > > .max_th =3D 1023, > > .wq_log2 =3D ft6_wq_log2, > > .maxp_inv =3D ft6_maxp_inv, > > + .max_queue_len =3D RTE_RED_DEFAULT_QUEUE_LENGTH, > > }; > >=20 > > static struct test_queue ft6_tqueue =3D { @@ -1078,7 +1242,7 @@ static= =20 > > struct test_queue ft6_tqueue =3D { static struct test_config=20 > > func_test6_config =3D { > > .ifname =3D "functional test 6 interface", > > .msg =3D "functional test 6 : use several queues (each with its own=20 > > run-time data),\n" > > - " use several RED configurations (such that each > > configuration is sharte_red by multiple queues),\n" > > + " use several RED configurations (such that each > > configuration is shared by multiple queues),\n" > > " increase average queue size to target level,\n" > > " dequeue all packets until queue is empty,\n" > > " confirm that average queue size is computed > > correctly while queue is empty\n" > > @@ -1097,6 +1261,44 @@ static struct test_config func_test6_config =3D = { > > .tlevel =3D ft6_tlevel, > > }; > >=20 > > +/** > > + * Test F6: functional test 6 > > + */ > > +static uint32_t ft6_tlevel_scaling[] =3D {8190}; > > + > > +static struct test_rte_red_config ft6_tconfig_scaling =3D { > > + .rconfig =3D ft6_config, > > + .num_cfg =3D RTE_DIM(ft6_config), > > + .min_th =3D 32, > > + .max_th =3D 8191, > > + .wq_log2 =3D ft6_wq_log2, > > + .maxp_inv =3D ft6_maxp_inv, > > + .max_queue_len =3D 8192, > > +}; > > + > > +static struct test_config func_test6_config_scaling =3D { > > + .ifname =3D "functional test 6 interface", > > + .msg =3D "functional test 6 : use several long queues (each with its > > own run-time data),\n" > > + " use several RED configurations (such that each > > configuration is shared by multiple queues),\n" > > + " increase average queue size to target level,\n" > > + " dequeue all packets until queue is empty,\n" > > + " confirm that average queue size is computed > > correctly while queue is empty\n" > > + " (this is a larger scale version of functional test > > 3)\n\n", > > + .htxt =3D "queue " > > + "config " > > + "q avg before " > > + "q avg after " > > + "expected " > > + "difference % " > > + "tolerance % " > > + "result " > > + "\n", > > + .tconfig =3D &ft6_tconfig_scaling, > > + .tqueue =3D &ft6_tqueue, > > + .tvar =3D &ft_tvar, > > + .tlevel =3D ft6_tlevel_scaling, > > +}; > > + > > static enum test_result func_test6(struct test_config *tcfg) { > > enum test_result result =3D PASS; > > @@ -1195,6 +1397,7 @@ static struct test_rte_red_config pt_tconfig =3D = { > > .min_th =3D 32, > > .max_th =3D 128, > > .maxp_inv =3D pt_maxp_inv, > > + .max_queue_len =3D RTE_RED_DEFAULT_QUEUE_LENGTH, > > }; > >=20 > > static struct test_queue pt_tqueue =3D { @@ -1557,6 +1760,7 @@ static= =20 > > struct test_rte_red_config ovfl_tconfig =3D { > > .min_th =3D 32, > > .max_th =3D 1023, > > .maxp_inv =3D ovfl_maxp_inv, > > + .max_queue_len =3D RTE_RED_DEFAULT_QUEUE_LENGTH, > > }; > >=20 > > static struct test_queue ovfl_tqueue =3D { @@ -1598,7 +1802,7 @@ stati= c=20 > > struct test_config ovfl_test1_config =3D { > > .ifname =3D "queue avergage overflow test interface", > > .msg =3D "overflow test 1 : use one RED configuration,\n" > > " increase average queue size to target level,\n" > > - " check maximum number of bits requirte_red to > > represent avg_s\n\n", > > + " check maximum number of bits required to > > represent avg_s\n\n", > > .htxt =3D "avg queue size " > > "wq_log2 " > > "fraction bits " > > @@ -1615,6 +1819,39 @@ static struct test_config ovfl_test1_config =3D = { > > .tlevel =3D ovfl_tlevel, > > }; > >=20 > > +static uint32_t ovfl_tlevel_scaling[] =3D {8191}; > > + > > +static struct test_rte_red_config ovfl_tconfig_scaling =3D { > > + .rconfig =3D ovfl_wrconfig, > > + .num_cfg =3D RTE_DIM(ovfl_wrconfig), > > + .wq_log2 =3D ovfl_wq_log2, > > + .min_th =3D 32, > > + .max_th =3D 8191, > > + .maxp_inv =3D ovfl_maxp_inv, > > + .max_queue_len =3D 8192, > > +}; > > + > > +static struct test_config ovfl_test1_config_scaling =3D { > > + .ifname =3D "queue average overflow test interface", > > + .msg =3D "overflow test 1 on long queue: use one RED > > configuration,\n" > > + " increase average queue size to target level,\n" > > + " check maximum number of bits required to > > represent avg_s\n\n", > > + .htxt =3D "avg queue size " > > + "wq_log2 " > > + "fraction bits " > > + "max queue avg " > > + "num bits " > > + "enqueued " > > + "dropped " > > + "drop prob % " > > + "drop rate % " > > + "\n", > > + .tconfig =3D &ovfl_tconfig_scaling, > > + .tqueue =3D &ovfl_tqueue, > > + .tvar =3D &ovfl_tvar, > > + .tlevel =3D ovfl_tlevel_scaling, > > +}; > > + > > static enum test_result ovfl_test1(struct test_config *tcfg) { > > enum test_result result =3D PASS; > > @@ -1690,7 +1927,7 @@ static enum test_result ovfl_test1(struct=20 > > test_config *tcfg) > > printf("%s", tcfg->htxt); > >=20 > > printf("%-16u%-9u%-15u0x%08x %-10u%-10u%-10u%-13.2lf%- > > 13.2lf\n", > > - avg, *tcfg->tconfig->wq_log2, RTE_RED_SCALING, > > + avg, *tcfg->tconfig->wq_log2, rte_red_scaling, > > avg_max, avg_max_bits, > > *tcfg->tvar->enqueued, *tcfg->tvar->dropped, > > drop_prob * 100.0, drop_rate * 100.0); @@ -1730,6 +1967,15 @@= =20 > > struct tests perf_tests[] =3D { > > { &perf2_test6_config, perf2_test }, }; > >=20 > > +struct tests scale_tests[] =3D { > > + { &func_test2_config_scaling, func_test2 }, > > + { &func_test3_config_scaling, func_test3 }, > > + { &func_test4_config_scaling, func_test4 }, > > + { &func_test5_config_scaling, func_test5 }, > > + { &func_test6_config_scaling, func_test6 }, > > + { &ovfl_test1_config_scaling, ovfl_test1 }, }; > > + > > /** > > * function to execute the required_red tests > > */ > > @@ -1866,6 +2112,20 @@ test_red_perf(void) } > >=20 > > static int > > +test_red_scaling(void) > > +{ > > + uint32_t num_tests =3D 0; > > + uint32_t num_pass =3D 0; > > + > > + if (test_invalid_parameters() < 0) > > + return -1; > > + > > + run_tests(scale_tests, RTE_DIM(scale_tests), &num_tests, > > &num_pass); > > + show_stats(num_tests, num_pass); > > + return tell_the_result(num_tests, num_pass); } > > + > > +static int > > test_red_all(void) > > { > > uint32_t num_tests =3D 0; > > @@ -1876,10 +2136,12 @@ test_red_all(void) > >=20 > > run_tests(func_tests, RTE_DIM(func_tests), &num_tests, &num_pass); > > run_tests(perf_tests, RTE_DIM(perf_tests), &num_tests, &num_pass); > > + run_tests(scale_tests, RTE_DIM(scale_tests), &num_tests, > > &num_pass); > > show_stats(num_tests, num_pass); > > return tell_the_result(num_tests, num_pass); } > >=20 > > REGISTER_TEST_COMMAND(red_autotest, test_red); =20 > > REGISTER_TEST_COMMAND(red_perf, test_red_perf); > > +REGISTER_TEST_COMMAND(red_scaling, test_red_scaling); > > REGISTER_TEST_COMMAND(red_all, test_red_all); > > -- > > 2.1.4 > > Regards, > Cristian