From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wm0-f52.google.com (mail-wm0-f52.google.com [74.125.82.52]) by dpdk.org (Postfix) with ESMTP id 8C6A77D19 for ; Mon, 15 Jan 2018 17:16:18 +0100 (CET) Received: by mail-wm0-f52.google.com with SMTP id 143so2860621wma.5 for ; Mon, 15 Jan 2018 08:16:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=ZPUzix99ATI6FGgn88mGMUUrhAU9RHMR5DDhGjyZa68=; b=ME+BQklMysITyIyLtByO1R9me+nWyHrdnoes2CpfHSUptfmc6i+IIRqT4CwqRv3SXQ Vj5Z4CX361BR7uYaJwLwZLryIMMvIV8O0cbrU6Us4leynCOs9Fi9eNc8+UsiYShFeMmi bxHmIVRcWhQ2fx0/YrlxiLIyXsTFQrADOIr+tKMz9TEvR6hIldz8H/tcbkq50tLZCndb gLQGFaBY10lExuU1o3vkO4MxzqSDuIvNIQdgVT2TvOHCqgIGnAqgFitLsEyzBdT9pkxC 2cSMdbm2Ohguf6gO+jxTm9LGa5dtn6AMv7MwKNVmCwchTju4cimGxOlnVxFcK3fYlCIf c2JA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=ZPUzix99ATI6FGgn88mGMUUrhAU9RHMR5DDhGjyZa68=; b=sI1zNoRTeJmf7IpdjBhxB9mXaqOCwCo5GHJQ49/4yXTmv+6ZeJLHOcvGmM9IOzwJMK 0VU9rXL1sg0yNgX7b1coTeiMfft+6ZObj1hilAZkC3PyG5ZMF3n023bX+dBedrRhb3b/ jkLXUgnyLyqH9azr0EK8XOyCzeV9gDWa1VUOVhcPmkLImQsETi8DAEZ7r0TBR7UFx0EU 2h6FK6mH7QnwiMVe5lhOhJvsAyKpkj11K9Ccq+NBfse5diR+r3V5oefAR+uhGrDMmDFo IDTHKPzlMPf2+EzxnX1FBwhexyR0GFcD1OHbISyJdr2bYoZy/r2ipdlgqpaZDRWDUcIe U35A== X-Gm-Message-State: AKwxyteXHrygbXOOddkfQjIbgn25GuV5c2ZznteagiH0Kr9hGDxFs5sW SBXyoEWnDS/C7CyfOYWA/y7J X-Google-Smtp-Source: ACJfBovL0fj6ZLEiHgDwZVnbuIz7pxNzGBojkXTT3yeca4f7QEiqqk+YtSlIhycsdHjMp8GvJeihBg== X-Received: by 10.28.69.136 with SMTP id l8mr10081519wmi.103.1516032978033; Mon, 15 Jan 2018 08:16:18 -0800 (PST) Received: from localhost.localdomain ([213.251.34.146]) by smtp.gmail.com with ESMTPSA id a6sm432728wma.7.2018.01.15.08.16.17 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 15 Jan 2018 08:16:17 -0800 (PST) From: alangordondewar@gmail.com X-Google-Original-From: alan.dewar@att.com To: cristian.dumitrescu@intel.com Cc: tomasz.kantecki@intel.com, jasvinder.singh@intel.com, dev@dpdk.org, Alan Dewar Date: Mon, 15 Jan 2018 16:16:09 +0000 Message-Id: <1516032969-23894-1-git-send-email-alan.dewar@att.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1515425232-18888-1-git-send-email-alan.dewar@att.com> References: <1515425232-18888-1-git-send-email-alan.dewar@att.com> Subject: [dpdk-dev] [PATCH v6] 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: Mon, 15 Jan 2018 16:16:18 -0000 From: Alan Dewar The RED code stores the weighted moving average in a 32-bit integer as a pseudo fixed-point floating number with 10 fractional bits. Twelve other bits are used to encode the filter weight, leaving just 10 bits for the queue length. This limits the maximum queue length supported by RED queues to 1024 packets. Introduce a new API to allow the RED scaling factor to be configured based upon maximum queue length. If this API is not called, the RED scaling factor remains at its default value. Added some new RED scaling unit-tests to test with RED queue-lengths up to 8192 packets long. Signed-off-by: Alan Dewar --- doc/guides/rel_notes/release_18_02.rst | 2 +- lib/librte_sched/Makefile | 2 +- lib/librte_sched/rte_red.c | 47 +++++- lib/librte_sched/rte_red.h | 63 ++++++-- lib/librte_sched/rte_sched_version.map | 7 + test/test/test_red.c | 274 ++++++++++++++++++++++++++++++++- 6 files changed, 371 insertions(+), 24 deletions(-) diff --git a/doc/guides/rel_notes/release_18_02.rst b/doc/guides/rel_notes/release_18_02.rst index 24b67bb..1bac48f 100644 --- a/doc/guides/rel_notes/release_18_02.rst +++ b/doc/guides/rel_notes/release_18_02.rst @@ -158,7 +158,7 @@ The libraries prepended with a plus sign were incremented in this version. librte_power.so.1 librte_reorder.so.1 librte_ring.so.1 - librte_sched.so.1 + librte_sched.so.2 librte_security.so.1 librte_table.so.3 librte_timer.so.1 diff --git a/lib/librte_sched/Makefile b/lib/librte_sched/Makefile index 04785f7..db12d92 100644 --- a/lib/librte_sched/Makefile +++ b/lib/librte_sched/Makefile @@ -48,7 +48,7 @@ LDLIBS += -lrte_timer EXPORT_MAP := rte_sched_version.map -LIBABIVER := 1 +LIBABIVER := 2 # # all source are stored in SRCS-y diff --git a/lib/librte_sched/rte_red.c b/lib/librte_sched/rte_red.c index ade57d1..a47a2fa 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 = 0; /**< Flag to indicate that global initialisation is done */ uint32_t rte_red_rand_val = 0; /**< Random value cache */ uint32_t rte_red_rand_seed = 0; /**< Seed for random number generation */ +uint32_t rte_red_scaling = RTE_RED_SCALING; +uint32_t rte_red_max_threshold = RTE_RED_DEFAULT_QUEUE_LENGTH - 1; /** * table[i] = log2(1-Wq) * Scale * -1 @@ -66,7 +68,7 @@ __rte_red_init_tables(void) double scale = 0.0; double table_size = 0.0; - scale = (double)(1 << RTE_RED_SCALING); + scale = (double)(1 << rte_red_scaling); table_size = (double)(RTE_DIM(rte_red_pow2_frac_inv)); for (i = 0; i < RTE_DIM(rte_red_pow2_frac_inv); i++) { @@ -119,7 +121,7 @@ rte_red_config_init(struct rte_red_config *red_cfg, if (red_cfg == NULL) { return -1; } - if (max_th > RTE_RED_MAX_TH_MAX) { + if (max_th > rte_red_max_threshold) { return -2; } if (min_th >= max_th) { @@ -148,11 +150,46 @@ rte_red_config_init(struct rte_red_config *red_cfg, rte_red_init_done = 1; } - red_cfg->min_th = ((uint32_t) min_th) << (wq_log2 + RTE_RED_SCALING); - red_cfg->max_th = ((uint32_t) max_th) << (wq_log2 + RTE_RED_SCALING); - red_cfg->pa_const = (2 * (max_th - min_th) * maxp_inv) << RTE_RED_SCALING; + red_cfg->min_th = ((uint32_t) min_th) << (wq_log2 + rte_red_scaling); + red_cfg->max_th = ((uint32_t) max_th) << (wq_log2 + rte_red_scaling); + red_cfg->pa_const = (2 * (max_th - min_th) * maxp_inv) << + rte_red_scaling; red_cfg->maxp_inv = maxp_inv; red_cfg->wq_log2 = wq_log2; return 0; } + +int +rte_red_set_scaling(uint16_t max_red_queue_length) +{ + 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; + + rte_red_scaling = RTE_RED_SCALING - (rte_bsf32(max_red_queue_length) - + RTE_RED_SCALING); + rte_red_max_threshold = max_red_queue_length - 1; + return 0; +} + +void +__rte_red_reset_scaling(void) +{ + rte_red_init_done = 0; + rte_red_scaling = RTE_RED_SCALING; + rte_red_max_threshold = RTE_RED_DEFAULT_QUEUE_LENGTH - 1; +} + diff --git a/lib/librte_sched/rte_red.h b/lib/librte_sched/rte_red.h index 6edf914..5e8c990 100644 --- a/lib/librte_sched/rte_red.h +++ b/lib/librte_sched/rte_red.h @@ -52,14 +52,31 @@ extern "C" { #include #include -#define RTE_RED_SCALING 10 /**< Fraction size for fixed-point */ -#define RTE_RED_S (1 << 22) /**< Packet size multiplied by number of leaf queues */ -#define RTE_RED_MAX_TH_MAX 1023 /**< Max threshold limit in fixed point format */ -#define RTE_RED_WQ_LOG2_MIN 1 /**< Min inverse filter weight value */ -#define RTE_RED_WQ_LOG2_MAX 12 /**< Max inverse filter weight value */ -#define RTE_RED_MAXP_INV_MIN 1 /**< Min inverse mark probability value */ -#define RTE_RED_MAXP_INV_MAX 255 /**< Max inverse mark probability value */ -#define RTE_RED_2POW16 (1<<16) /**< 2 power 16 */ +/** Default fraction size for fixed-point */ +#define RTE_RED_SCALING 10 + +/** 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_BIT) #define RTE_RED_WQ_LOG2_NUM (RTE_RED_WQ_LOG2_MAX - RTE_RED_WQ_LOG2_MIN + 1) @@ -71,6 +88,8 @@ extern uint32_t rte_red_rand_val; extern uint32_t rte_red_rand_seed; extern uint16_t rte_red_log2_1_minus_Wq[RTE_RED_WQ_LOG2_NUM]; extern uint16_t rte_red_pow2_frac_inv[16]; +extern uint32_t rte_red_scaling; +extern uint32_t rte_red_max_threshold; /** * RED configuration parameters passed by user @@ -137,6 +156,26 @@ rte_red_config_init(struct rte_red_config *red_cfg, const uint16_t maxp_inv); /** + * @brief Configures the global setting for the RED scaling factor, this + * function can only be called once and must be called before any + * RED queues are initialised. + * + * @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 all RED global variables - only for use by RED unit-tests + */ +void +__rte_red_reset_scaling(void); + +/** * @brief Generate random number for RED * * Implementation based on: @@ -206,7 +245,7 @@ __rte_red_calc_qempty_factor(uint8_t wq_log2, uint16_t m) f = (n >> 6) & 0xf; n >>= 10; - if (n < RTE_RED_SCALING) + if (n < rte_red_scaling) return (uint16_t) ((rte_red_pow2_frac_inv[f] + (1 << (n - 1))) >> n); return 0; @@ -258,7 +297,9 @@ rte_red_enqueue_empty(const struct rte_red_config *red_cfg, if (m >= RTE_RED_2POW16) { red->avg = 0; } else { - red->avg = (red->avg >> RTE_RED_SCALING) * __rte_red_calc_qempty_factor(red_cfg->wq_log2, (uint16_t) m); + red->avg = (red->avg >> rte_red_scaling) * + __rte_red_calc_qempty_factor(red_cfg->wq_log2, + (uint16_t) m); } return 0; @@ -365,7 +406,7 @@ rte_red_enqueue_nonempty(const struct rte_red_config *red_cfg, */ /* avg update */ - red->avg += (q << RTE_RED_SCALING) - (red->avg >> red_cfg->wq_log2); + red->avg += (q << rte_red_scaling) - (red->avg >> red_cfg->wq_log2); /* 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..56c4a52 100644 --- a/lib/librte_sched/rte_sched_version.map +++ b/lib/librte_sched/rte_sched_version.map @@ -29,3 +29,10 @@ DPDK_2.1 { rte_sched_port_pkt_read_color; } DPDK_2.0; + +DPDK_18.02 { + global; + + rte_red_set_scaling; + __rte_red_reset_scaling; +} DPDK_2.1; diff --git a/test/test/test_red.c b/test/test/test_red.c index 348075d..0c95e84 100644 --- a/test/test/test_red.c +++ b/test/test/test_red.c @@ -67,6 +67,7 @@ struct test_rte_red_config { /**< Test structure 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 */ }; struct test_queue { /**< Test structure for RTE_RED Queues */ @@ -181,7 +182,7 @@ static uint32_t rte_red_get_avg_int(const struct 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); } static double rte_red_get_avg_float(const struct rte_red_config *red_cfg, @@ -190,7 +191,7 @@ static double 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)); } static void rte_red_set_avg_int(const struct rte_red_config *red_cfg, @@ -200,7 +201,7 @@ static void rte_red_set_avg_int(const struct rte_red_config *red_cfg, /** * scale by n and convert from integer to fixed-point */ - red->avg = avg << (RTE_RED_SCALING + red_cfg->wq_log2); + red->avg = avg << (rte_red_scaling + red_cfg->wq_log2); } static double calc_exp_avg_on_empty(double avg, uint32_t n, uint32_t time_diff) @@ -280,10 +281,23 @@ static enum test_result test_rte_red_init(struct test_config *tcfg) { unsigned i = 0; + int ret; tcfg->tvar->clk_freq = rte_get_timer_hz(); init_port_ts( tcfg->tvar->clk_freq ); + __rte_red_reset_scaling(); + ret = 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 = 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 = { .min_th = 32, .max_th = 128, .maxp_inv = ft_maxp_inv, + .max_queue_len = RTE_RED_DEFAULT_QUEUE_LENGTH, }; static struct test_queue ft_tqueue = { @@ -554,6 +569,7 @@ static struct test_rte_red_config ft2_tconfig = { .min_th = 32, .max_th = 128, .maxp_inv = ft2_maxp_inv, + .max_queue_len = RTE_RED_DEFAULT_QUEUE_LENGTH, }; static struct test_config func_test2_config = { @@ -576,6 +592,41 @@ static struct test_config func_test2_config = { .tlevel = ft2_tlevel, }; +/** + * Test F2: functional test 2 - with long queues and smaller red-scaling factor + */ +static uint32_t ft2_tlevel_scaling[] = {8190}; + +static struct test_rte_red_config ft2_tconfig_scaling = { + .rconfig = ft2_rconfig, + .num_cfg = RTE_DIM(ft2_rconfig), + .wq_log2 = ft2_wq_log2, + .min_th = 32, + .max_th = 8191, + .maxp_inv = ft2_maxp_inv, + .max_queue_len = 8192, +}; + +static struct test_config func_test2_config_scaling = { + .ifname = "functional test 2 interface", + .msg = "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 = "RED config " + "avg queue size " + "min threshold " + "max threshold " + "drop prob % " + "drop rate % " + "diff % " + "tolerance % " + "\n", + .tconfig = &ft2_tconfig_scaling, + .tqueue = &ft_tqueue, + .tvar = &ft_tvar, + .tlevel = ft2_tlevel_scaling, +}; + static enum test_result func_test2(struct test_config *tcfg) { enum test_result result = PASS; @@ -662,6 +713,7 @@ static struct test_rte_red_config ft3_tconfig = { .min_th = 32, .max_th = 1023, .maxp_inv = ft_maxp_inv, + .max_queue_len = RTE_RED_DEFAULT_QUEUE_LENGTH, }; static struct test_config func_test3_config = { @@ -683,6 +735,40 @@ static struct test_config func_test3_config = { .tlevel = ft3_tlevel, }; +/** + * Test F3: functional test 3 - with large queues and smaller red scaling factor + */ +static uint32_t ft3_tlevel_scaling[] = {8190}; + +static struct test_rte_red_config ft3_tconfig_scaling = { + .rconfig = ft_wrconfig, + .num_cfg = RTE_DIM(ft_wrconfig), + .wq_log2 = ft_wq_log2, + .min_th = 32, + .max_th = 8191, + .maxp_inv = ft_maxp_inv, + .max_queue_len = 8192, +}; + +static struct test_config func_test3_config_scaling = { + .ifname = "functional test 3 interface", + .msg = "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 = "q avg before " + "q avg after " + "expected " + "difference % " + "tolerance % " + "result " + "\n", + .tconfig = &ft3_tconfig_scaling, + .tqueue = &ft_tqueue, + .tvar = &ft_tvar, + .tlevel = ft3_tlevel_scaling, +}; + static enum test_result func_test3(struct test_config *tcfg) { enum test_result result = PASS; @@ -776,6 +862,7 @@ static struct test_rte_red_config ft4_tconfig = { .max_th = 1023, .wq_log2 = ft4_wq_log2, .maxp_inv = ft_maxp_inv, + .max_queue_len = RTE_RED_DEFAULT_QUEUE_LENGTH, }; static struct test_queue ft4_tqueue = { @@ -810,6 +897,42 @@ static struct test_config func_test4_config = { .tlevel = ft4_tlevel, }; +/** + * Test F4: functional test 4 + */ +static uint32_t ft4_tlevel_scaling[] = {8190}; + +static struct test_rte_red_config ft4_tconfig_scaling = { + .rconfig = ft_wrconfig, + .num_cfg = RTE_DIM(ft_wrconfig), + .min_th = 32, + .max_th = 8191, + .wq_log2 = ft4_wq_log2, + .maxp_inv = ft_maxp_inv, + .max_queue_len = 8192, +}; + +static struct test_config func_test4_config_scaling = { + .ifname = "functional test 4 interface", + .msg = "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 = "q avg before " + "q avg after " + "expected " + "difference % " + "tolerance % " + "result " + "\n", + .tconfig = &ft4_tconfig_scaling, + .tqueue = &ft4_tqueue, + .tvar = &ft_tvar, + .tlevel = ft4_tlevel_scaling, +}; + static enum test_result func_test4(struct test_config *tcfg) { enum test_result result = PASS; @@ -924,6 +1047,7 @@ static struct test_rte_red_config ft5_tconfig = { .max_th = 128, .wq_log2 = ft5_wq_log2, .maxp_inv = ft5_maxp_inv, + .max_queue_len = RTE_RED_DEFAULT_QUEUE_LENGTH, }; static struct test_queue ft5_tqueue = { @@ -970,6 +1094,45 @@ static struct test_config func_test5_config = { .tlevel = ft5_tlevel, }; + +/** + * Test F5: functional test 5 + */ +static uint32_t ft5_tlevel_scaling[] = {8190}; + +static struct test_rte_red_config ft5_tconfig_scaling = { + .rconfig = ft5_config, + .num_cfg = RTE_DIM(ft5_config), + .min_th = 32, + .max_th = 8191, + .wq_log2 = ft5_wq_log2, + .maxp_inv = ft5_maxp_inv, + .max_queue_len = 8192, +}; + +static struct test_config func_test5_config_scaling = { + .ifname = "functional test 5 interface", + .msg = "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 = "queue " + "config " + "avg queue size " + "min threshold " + "max threshold " + "drop prob % " + "drop rate % " + "diff % " + "tolerance % " + "\n", + .tconfig = &ft5_tconfig_scaling, + .tqueue = &ft5_tqueue, + .tvar = &ft5_tvar, + .tlevel = ft5_tlevel_scaling, +}; + static enum test_result func_test5(struct test_config *tcfg) { enum test_result result = PASS; @@ -1062,6 +1225,7 @@ static struct test_rte_red_config ft6_tconfig = { .max_th = 1023, .wq_log2 = ft6_wq_log2, .maxp_inv = ft6_maxp_inv, + .max_queue_len = RTE_RED_DEFAULT_QUEUE_LENGTH, }; static struct test_queue ft6_tqueue = { @@ -1078,7 +1242,7 @@ static struct test_queue ft6_tqueue = { static struct test_config func_test6_config = { .ifname = "functional test 6 interface", .msg = "functional test 6 : use several queues (each with its own 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 = { .tlevel = ft6_tlevel, }; +/** + * Test F6: functional test 6 + */ +static uint32_t ft6_tlevel_scaling[] = {8190}; + +static struct test_rte_red_config ft6_tconfig_scaling = { + .rconfig = ft6_config, + .num_cfg = RTE_DIM(ft6_config), + .min_th = 32, + .max_th = 8191, + .wq_log2 = ft6_wq_log2, + .maxp_inv = ft6_maxp_inv, + .max_queue_len = 8192, +}; + +static struct test_config func_test6_config_scaling = { + .ifname = "functional test 6 interface", + .msg = "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 = "queue " + "config " + "q avg before " + "q avg after " + "expected " + "difference % " + "tolerance % " + "result " + "\n", + .tconfig = &ft6_tconfig_scaling, + .tqueue = &ft6_tqueue, + .tvar = &ft_tvar, + .tlevel = ft6_tlevel_scaling, +}; + static enum test_result func_test6(struct test_config *tcfg) { enum test_result result = PASS; @@ -1195,6 +1397,7 @@ static struct test_rte_red_config pt_tconfig = { .min_th = 32, .max_th = 128, .maxp_inv = pt_maxp_inv, + .max_queue_len = RTE_RED_DEFAULT_QUEUE_LENGTH, }; static struct test_queue pt_tqueue = { @@ -1557,6 +1760,7 @@ static struct test_rte_red_config ovfl_tconfig = { .min_th = 32, .max_th = 1023, .maxp_inv = ovfl_maxp_inv, + .max_queue_len = RTE_RED_DEFAULT_QUEUE_LENGTH, }; static struct test_queue ovfl_tqueue = { @@ -1598,7 +1802,7 @@ static struct test_config ovfl_test1_config = { .ifname = "queue avergage overflow test interface", .msg = "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 = "avg queue size " "wq_log2 " "fraction bits " @@ -1615,6 +1819,39 @@ static struct test_config ovfl_test1_config = { .tlevel = ovfl_tlevel, }; +static uint32_t ovfl_tlevel_scaling[] = {8191}; + +static struct test_rte_red_config ovfl_tconfig_scaling = { + .rconfig = ovfl_wrconfig, + .num_cfg = RTE_DIM(ovfl_wrconfig), + .wq_log2 = ovfl_wq_log2, + .min_th = 32, + .max_th = 8191, + .maxp_inv = ovfl_maxp_inv, + .max_queue_len = 8192, +}; + +static struct test_config ovfl_test1_config_scaling = { + .ifname = "queue average overflow test interface", + .msg = "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 = "avg queue size " + "wq_log2 " + "fraction bits " + "max queue avg " + "num bits " + "enqueued " + "dropped " + "drop prob % " + "drop rate % " + "\n", + .tconfig = &ovfl_tconfig_scaling, + .tqueue = &ovfl_tqueue, + .tvar = &ovfl_tvar, + .tlevel = ovfl_tlevel_scaling, +}; + static enum test_result ovfl_test1(struct test_config *tcfg) { enum test_result result = PASS; @@ -1690,7 +1927,7 @@ static enum test_result ovfl_test1(struct test_config *tcfg) printf("%s", tcfg->htxt); 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 @@ struct tests perf_tests[] = { { &perf2_test6_config, perf2_test }, }; +struct tests scale_tests[] = { + { &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) } static int +test_red_scaling(void) +{ + uint32_t num_tests = 0; + uint32_t num_pass = 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 = 0; @@ -1876,10 +2136,12 @@ test_red_all(void) 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); } REGISTER_TEST_COMMAND(red_autotest, test_red); 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.7.4