From patchwork Thu Nov 16 17:18:51 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Dewar X-Patchwork-Id: 31447 Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id D1EB51B1A0; Thu, 16 Nov 2017 18:20:06 +0100 (CET) Received: from mail-wm0-f42.google.com (mail-wm0-f42.google.com [74.125.82.42]) by dpdk.org (Postfix) with ESMTP id 9AEE6325C for ; Thu, 16 Nov 2017 18:20:05 +0100 (CET) Received: by mail-wm0-f42.google.com with SMTP id l8so1655558wmg.4 for ; Thu, 16 Nov 2017 09:20:05 -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; bh=ZFosB0+QWC8B/bxNLfCpG/qCsde1qbWOMSR0rELf0NU=; b=aYM8IaeCOYWi6sVHcBgeinvHNCb8nfKTuTyta0KbuPJpn0XhVMG/9VdAUjjWQcWSvG 5kY0FahXxbpR1sPRkEecnwjPlJ4CF8ISS5jIlQ+344Lm/jmy537nYlEPzba8J+5fe+k6 83/ydKPLlN9LwIprKQKBKXk6pFXw5xgv99ViGcYyUA6yDysd78NdcNpq2UII3M9/I7lz rtqxOWV07y2bbNY47/fmZdfwn9G7zFateEPwBoLMeoK2utPHhDVF9ercr2OMzjl+OCDt 3LhZUzGzBrq6ahkRqWsAwLvmHxQnKxm+7OdQZtQ+z16+YsmP+5HQPCCbRZGrvdGSzsYP u4Cw== 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; bh=ZFosB0+QWC8B/bxNLfCpG/qCsde1qbWOMSR0rELf0NU=; b=dNlXN2bkcMCKt7wJsTOOO+YVi90h5Tsq1vua/UIU5GwqbeJKtUaN1hT14GzKW1WK0v qVX/RP3f8yOh/LeEhFhASQN+ZWkCXHvOaar/N+3xOkXU8d9oAUia0To1d8JgRa5q+MH0 XjfGF7RyjLq0p2eiYIzNswZj2gJ/m2gQqTZ3tCrEpTgiSQVk2d3axvUv8WEZIr2JSLOm gzFoK6yJhBIA/6aKCBGS4e4lLm2kV82JnbAEKt1VYCxTKW/VMuCBszqbtIlz65lELLrx h1a4Go4+5rAgk/aaUZGQNvNX//Ksjrm32Gs0Hf4qGCK4/VHf3fkQIDm2KJ3MhD+RJCxB 8oGw== X-Gm-Message-State: AJaThX4pDF00gnqqaC6ujbOsseyca+goQZHVfeNU6Kq7btHc6T6cGi+1 kuTFyXTh/9bqH2glxtBSwA== X-Google-Smtp-Source: AGs4zMbtaF3eiQTreOYviHFAJ6/NE6YYk0hy25pcxKc60G2+gaaZ6zS98SjmF746SO+n/KWm+ErF0g== X-Received: by 10.80.150.196 with SMTP id z4mr3883389eda.110.1510852804897; Thu, 16 Nov 2017 09:20:04 -0800 (PST) Received: from bra-l27t7p12.brocade.com ([144.49.71.22]) by smtp.gmail.com with ESMTPSA id p37sm1472144eda.96.2017.11.16.09.20.02 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 16 Nov 2017 09:20:03 -0800 (PST) From: alangordondewar@gmail.com X-Google-Original-From: alan.dewar@att.com To: cristian.dumitrescu@intel.com Cc: dev@dpdk.org, chas3@att.com, luca.boccassi@att.com, alan.robertson@att.com, Alan Dewar Date: Thu, 16 Nov 2017 17:18:51 +0000 Message-Id: <1510852731-27555-1-git-send-email-alan.dewar@att.com> X-Mailer: git-send-email 2.1.4 Subject: [dpdk-dev] [PATCH] test: new sched WRR unit-test 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: , Errors-To: dev-bounces@dpdk.org Sender: "dev" From: Alan Dewar New unit-test for the librte_sched WRR weighting code. With the standard 17.11 code, the first three sub-tests pass, but the last two fail due to bugs in the WRR weighting code. With the "sched: fix overflow errors in WRR weighting code" patch all five sub-tests pass. Signed-off-by: Alan Dewar Reviewed-by: Luca Boccassi --- test/test/Makefile | 1 + test/test/test_sched_wrr.c | 434 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 435 insertions(+) create mode 100644 test/test/test_sched_wrr.c diff --git a/test/test/Makefile b/test/test/Makefile index bb54c98..0ab0ed3 100644 --- a/test/test/Makefile +++ b/test/test/Makefile @@ -173,6 +173,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_NET) += test_crc.c ifeq ($(CONFIG_RTE_LIBRTE_SCHED),y) SRCS-y += test_red.c SRCS-y += test_sched.c +SRCS-y += test_sched_wrr.c endif SRCS-$(CONFIG_RTE_LIBRTE_METER) += test_meter.c diff --git a/test/test/test_sched_wrr.c b/test/test/test_sched_wrr.c new file mode 100644 index 0000000..3214091 --- /dev/null +++ b/test/test/test_sched_wrr.c @@ -0,0 +1,434 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2010-2014 Intel Corporation. All rights reserved. + * Copyright(c) 2017 ATT Intellectual Property. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include +#include + +#include "test.h" + +#include +#include +#include +#include +#include + + +#define SUBPORT 0 +#define PIPE 1 +#define TC 0 // 2 +#define QUEUE 3 + +static struct rte_sched_subport_params subport_param[] = { + { + .tb_rate = 1250000000, + .tb_size = 1000000, + + .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000}, + .tc_period = 10, + }, +}; + +static struct rte_sched_pipe_params pipe_profile[] = { + { /* Profile #0 */ + .tb_rate = 305175, + .tb_size = 1000000, + + .tc_rate = {305175, 305175, 305175, 305175}, + .tc_period = 160, + + .wrr_weights = {1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1}, + }, +}; + +static struct rte_sched_port_params port_param = { + .socket = 0, /* computed */ + .rate = 0, /* computed */ + .mtu = 1522, + .frame_overhead = RTE_SCHED_FRAME_OVERHEAD_DEFAULT, + .n_subports_per_port = 1, + .n_pipes_per_subport = 1024, + .qsize = {32, 32, 32, 32}, + .pipe_profiles = pipe_profile, + .n_pipe_profiles = 1, +}; + +#define NB_MBUF (4 * 32) +#define MBUF_DATA_SZ (2048 + RTE_PKTMBUF_HEADROOM) +#define MEMPOOL_CACHE_SZ 0 +#define SOCKET 0 + + +static struct rte_mempool * +create_mempool(uint32_t total_packets) +{ + struct rte_mempool *mp; + + mp = rte_mempool_lookup("test_sched wrr"); + if (!mp) + mp = rte_pktmbuf_pool_create("test_sched wrr", total_packets, + MEMPOOL_CACHE_SZ, 0, MBUF_DATA_SZ, SOCKET); + + return mp; +} + +static void +delete_mempool(struct rte_mempool *mp) +{ + rte_mempool_free(mp); +} + +static void +prepare_pkt(struct rte_mbuf *mbuf, uint32_t tc, uint32_t queue) +{ + struct ether_hdr *eth_hdr; + struct vlan_hdr *vlan1, *vlan2; + struct ipv4_hdr *ip_hdr; + + /* Simulate a classifier */ + eth_hdr = rte_pktmbuf_mtod(mbuf, struct ether_hdr *); + vlan1 = (struct vlan_hdr *)(ð_hdr->ether_type); + vlan2 = (struct vlan_hdr *)((uintptr_t)ð_hdr->ether_type + + sizeof(struct vlan_hdr)); + eth_hdr = (struct ether_hdr *)((uintptr_t)ð_hdr->ether_type + + 2 * sizeof(struct vlan_hdr)); + ip_hdr = (struct ipv4_hdr *)((uintptr_t)eth_hdr + + sizeof(eth_hdr->ether_type)); + + vlan1->vlan_tci = rte_cpu_to_be_16(SUBPORT); + vlan2->vlan_tci = rte_cpu_to_be_16(PIPE); + eth_hdr->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); + ip_hdr->dst_addr = IPv4(0, 0, TC, QUEUE); + + + rte_sched_port_pkt_write(mbuf, SUBPORT, PIPE, tc, queue, + e_RTE_METER_YELLOW); + + /* 64 byte packet */ + mbuf->pkt_len = 60; + mbuf->data_len = 60; +} + +/* + * This function carries out the core of the enqueue/dequeue testing. + * This is where we should detect failures if the WRR code is broken. + */ +static int +test_sched_wrr_enqueue_dequeue(const char *subtest_name, + struct rte_mempool *mp, + struct rte_sched_port *port, + struct rte_mbuf **in_mbufs, + struct rte_mbuf **out_mbufs, + int32_t enqueue_packets, + int32_t dequeue_packets, + uint32_t *expected_counts) +{ + uint32_t wrr_counts[RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS] = { 0 }; + uint32_t pipe; + int32_t i; + int err; + + /* + * Create the packets to be enqueued, spread them evenly across + * each of the four WRR queues of the test-TC + */ + for (i = 0; i < enqueue_packets; i++) { + in_mbufs[i] = rte_pktmbuf_alloc(mp); + TEST_ASSERT_NOT_NULL(in_mbufs[i], + "%s: Packet allocation failed on packet " + "%d\n", subtest_name, i); + prepare_pkt(in_mbufs[i], TC, (i & 0x3)); + } + + /* + * Queue all the enqueue packets, none should be dropped as the + * four queues should be long enough. + */ + err = rte_sched_port_enqueue(port, in_mbufs, enqueue_packets); + TEST_ASSERT_EQUAL(err, enqueue_packets, + "%s: Enqueue failed, err: %d != %d\n", + subtest_name, err, enqueue_packets); + + /* + * Dequeue the required number of packets. + */ + err = rte_sched_port_dequeue(port, out_mbufs, dequeue_packets); + TEST_ASSERT_EQUAL(err, dequeue_packets, + "%s: Dequeue failed, err: %d != %d\n", + subtest_name, err, dequeue_packets); + + /* + * Check each packet and count which WRR queue it came from. + */ + for (i = 0; i < dequeue_packets; i++) { + enum rte_meter_color color; + uint32_t subport, traffic_class, queue; + + color = rte_sched_port_pkt_read_color(out_mbufs[i]); + TEST_ASSERT_EQUAL(color, e_RTE_METER_YELLOW, + "%s: Wrong color\n", subtest_name); + + rte_sched_port_pkt_read_tree_path(out_mbufs[i], + &subport, &pipe, &traffic_class, &queue); + + TEST_ASSERT_EQUAL(subport, SUBPORT, "%s: Wrong subport\n", + subtest_name); + TEST_ASSERT_EQUAL(pipe, PIPE, "%s: Wrong pipe\n", subtest_name); + TEST_ASSERT_EQUAL(traffic_class, TC, + "%s: Wrong traffic-class\n", subtest_name); + wrr_counts[queue]++; + rte_pktmbuf_free(out_mbufs[i]); + } + + /* + * Check the number of packets dequeued from each WRR queue + * against the expected counts. + */ + err = 0; + for (i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) { + printf("%s - WRR queue %d, dequeued: %u, expected: %u\n", + subtest_name, i, wrr_counts[i], expected_counts[i]); + if (wrr_counts[i] != expected_counts[i]) + err = -1; + } + return err; +} + +/* + * This function does the test config set-up and tear-down. + * If we see failures in here it is probably due to the test configuration. + */ +static int +test_sched_wrr_test(const char *subtest_name, uint16_t *tc_qlengths, + uint8_t *wrr_weights, int32_t enqueue_packets, + int32_t dequeue_packets, uint32_t *expected_counts) +{ + struct rte_mbuf **in_mbufs; + struct rte_mbuf **out_mbufs; + struct rte_mempool *mp = NULL; + struct rte_sched_port *port = NULL; + int32_t total_expected = 0; + uint32_t pipe; + int32_t i; + int err; + + /* + * Some inbound argument checking + */ + TEST_ASSERT_EQUAL((tc_qlengths[TC] * 4), enqueue_packets, + "%s: Queue length/Enqueue packet mismatch\n", + subtest_name); + TEST_ASSERT((dequeue_packets <= enqueue_packets), + "%s: Dequeue packets %d > Enqueue packets %d\n", + subtest_name, dequeue_packets, enqueue_packets); + + for (i = 0; i < RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; i++) + total_expected += expected_counts[i]; + + TEST_ASSERT((dequeue_packets == total_expected), + "%s: Dequeue packets %d != Total expected %u\n", + subtest_name, dequeue_packets, total_expected); + + /* + * Create the mempool and allocate arrays to hold the rte_mbuf pointers + */ + mp = create_mempool(enqueue_packets); + TEST_ASSERT_NOT_NULL(mp, "%s: Error creating mempool\n", subtest_name); + + in_mbufs = malloc(sizeof(struct rte_mbuf *) * enqueue_packets); + TEST_ASSERT_NOT_NULL(in_mbufs, "%s: Error creating in_mbuf array\n", + subtest_name); + + out_mbufs = malloc(sizeof(struct rte_mbuf *) * dequeue_packets); + TEST_ASSERT_NOT_NULL(out_mbufs, "%s: Error creating out_mbuf array\n", + subtest_name); + + /* + * Set up the port and pipe profiles with the TC's queue lengths + * and the WRR queue weightings + */ + port_param.socket = 0; + port_param.rate = (uint64_t) 10000 * 1000 * 1000 / 8; + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) + port_param.qsize[i] = tc_qlengths[i]; + + for (i = 0; i < RTE_SCHED_QUEUES_PER_PIPE; i++) + pipe_profile[0].wrr_weights[i] = wrr_weights[i]; + + port = rte_sched_port_config(&port_param); + TEST_ASSERT_NOT_NULL(port, "%s: Error config sched port\n", + subtest_name); + + err = rte_sched_subport_config(port, SUBPORT, subport_param); + TEST_ASSERT_SUCCESS(err, "%s: Error config sched, err=%d\n", + subtest_name, err); + + for (pipe = 0; pipe < port_param.n_pipes_per_subport; pipe++) { + err = rte_sched_pipe_config(port, SUBPORT, pipe, 0); + TEST_ASSERT_SUCCESS(err, + "%s: Error config sched pipe %u, err=%d\n", + subtest_name, pipe, err); + } + + /* + * Enqueue and dequeue packets checking that each WRR queue dequeued + * the correct number of packets. + */ + err = test_sched_wrr_enqueue_dequeue(subtest_name, mp, port, in_mbufs, + out_mbufs, enqueue_packets, + dequeue_packets, + expected_counts); + + /* + * Free up allocated resources + */ + free(in_mbufs); + free(out_mbufs); + rte_sched_port_free(port); + delete_mempool(mp); + + return err; +} + +static int +test_sched_wrr_even_weights(void) +{ + uint16_t tc_qlengths[] = { 64, 64, 64, 64 }; + uint8_t wrr_weights[] = { 1, 1, 1, 1, // TC-0 + 1, 1, 1, 1, // TC-1 + 1, 1, 1, 1, // TC-2 + 1, 1, 1, 1 }; // TC-3 + int32_t enqueue_packets = 64 * 4; + int32_t dequeue_packets = 32; + uint32_t expected_counts[] = { 8, 8, 8, 8 }; + + return test_sched_wrr_test("wrr-even-weights", tc_qlengths, wrr_weights, + enqueue_packets, dequeue_packets, + expected_counts); +} + +static int +test_sched_wrr_8_4_2_1_weights(void) +{ + uint16_t tc_qlengths[] = { 64, 64, 64, 64 }; + uint8_t wrr_weights[] = { 8, 4, 2, 1, // TC-0 + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1 }; + int32_t enqueue_packets = 64 * 4; + int32_t dequeue_packets = 15; + uint32_t expected_counts[] = { 8, 4, 2, 1 }; + + return test_sched_wrr_test("wrr-8-4-2-1-weights", tc_qlengths, + wrr_weights, enqueue_packets, + dequeue_packets, expected_counts); +} + +static int +test_sched_wrr_1_2_3_4_weights(void) +{ + uint16_t tc_qlengths[] = { 64, 64, 64, 64 }; + uint8_t wrr_weights[] = { 1, 2, 3, 4, + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1 }; + int32_t enqueue_packets = 64 * 4; + int32_t dequeue_packets = 40; + uint32_t expected_counts[] = { 4, 8, 12, 16 }; + + return test_sched_wrr_test("wrr-1-2-3-4-weights", tc_qlengths, + wrr_weights, enqueue_packets, + dequeue_packets, expected_counts); +} + +static int +test_sched_wrr_11_7_5_3_weights(void) +{ + uint16_t tc_qlengths[] = { 64, 64, 64, 64 }; + uint8_t wrr_weights[] = { 11, 7, 5, 3, + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1 }; + int32_t enqueue_packets = 64 * 4; + int32_t dequeue_packets = 26; + uint32_t expected_counts[] = { 11, 7, 5, 3 }; + + return test_sched_wrr_test("wrr-11-7-5-3-weights", tc_qlengths, + wrr_weights, enqueue_packets, + dequeue_packets, expected_counts); +} + +static int +test_sched_wrr_100_to_97_weights(void) +{ + uint16_t tc_qlengths[] = { 128, 1, 1, 1 }; + uint8_t wrr_weights[] = { 100, 99, 98, 97, + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1 }; + int32_t enqueue_packets = 128 * 4; + int32_t dequeue_packets = 394; + uint32_t expected_counts[] = { 100, 99, 98, 97 }; + + return test_sched_wrr_test("wrr-100-to-97-weights", tc_qlengths, + wrr_weights, enqueue_packets, + dequeue_packets, expected_counts); +} + +/** + * WRR test main entrance for library sched + */ +static int +test_sched_wrr(void) +{ + TEST_ASSERT_SUCCESS(test_sched_wrr_even_weights(), + "even-weight test failed\n"); + TEST_ASSERT_SUCCESS(test_sched_wrr_8_4_2_1_weights(), + "8-4-2-1-weight test failed\n"); + TEST_ASSERT_SUCCESS(test_sched_wrr_1_2_3_4_weights(), + "1-2-3-4-weight test failed\n"); + TEST_ASSERT_SUCCESS(test_sched_wrr_11_7_5_3_weights(), + "11-7-5-3-weight test failed\n"); + TEST_ASSERT_SUCCESS(test_sched_wrr_100_to_97_weights(), + "100-to-97-weight test failed\n"); + return 0; +} + +REGISTER_TEST_COMMAND(sched_wrr_test, test_sched_wrr);