From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 4FE97A04BB; Tue, 6 Oct 2020 17:39:52 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 8E57E1B9E8; Tue, 6 Oct 2020 17:39:50 +0200 (CEST) Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by dpdk.org (Postfix) with ESMTP id 1C0F61B9E0 for ; Tue, 6 Oct 2020 17:39:45 +0200 (CEST) IronPort-SDR: ysWNp6F4mgDDKNs4CqzH+zseBC72pbTWgv36rlIXTHmsd+7TAlgBVL7B2JvL7wsZekgR1bXe9R ip3HWPfcDEdw== X-IronPort-AV: E=McAfee;i="6000,8403,9765"; a="152306158" X-IronPort-AV: E=Sophos;i="5.77,343,1596524400"; d="scan'208";a="152306158" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga004.jf.intel.com ([10.7.209.38]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 06 Oct 2020 08:27:46 -0700 IronPort-SDR: MHqMlWLWIMf7RKVDK+FmODr1aGFXGOhqm1EMOMEGuCp8WLGrterlzITKULsYobWmZx/2W0U+8X BSDlokyvvGMQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.77,343,1596524400"; d="scan'208";a="460844464" Received: from silpixa00400629.ir.intel.com ([10.237.214.112]) by orsmga004.jf.intel.com with ESMTP; 06 Oct 2020 08:27:45 -0700 From: Savinay Dharmappa To: cristian.dumitrescu@intel.com, jasvinder.singh@intel.com, dev@dpdk.org Cc: savinay.dharmappa@intel.com Date: Tue, 6 Oct 2020 16:27:26 +0100 Message-Id: <20201006152733.52178-2-savinay.dharmappa@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201006152733.52178-1-savinay.dharmappa@intel.com> References: <20200930192434.47793-1-savinay.dharmappa@intel.com> <20201006152733.52178-1-savinay.dharmappa@intel.com> Subject: [dpdk-dev] [PATCH v6 1/8] sched: add support profile table 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" Add subport profile table to internal port data structure and update the port config function. Signed-off-by: Savinay Dharmappa Signed-off-by: Jasvinder Singh --- lib/librte_sched/rte_sched.c | 197 ++++++++++++++++++++++++++++++++++- lib/librte_sched/rte_sched.h | 25 +++++ 2 files changed, 219 insertions(+), 3 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 75be8b6bd..a44638f31 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -101,6 +101,16 @@ enum grinder_state { e_GRINDER_READ_MBUF }; +struct rte_sched_subport_profile { + /* Token bucket (TB) */ + uint64_t tb_period; + uint64_t tb_credits_per_period; + uint64_t tb_size; + + uint64_t tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + uint64_t tc_period; +}; + struct rte_sched_grinder { /* Pipe cache */ uint16_t pcache_qmask[RTE_SCHED_GRINDER_PCACHE_SIZE]; @@ -212,6 +222,8 @@ struct rte_sched_port { uint16_t pipe_queue[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; uint8_t pipe_tc[RTE_SCHED_QUEUES_PER_PIPE]; uint8_t tc_queue[RTE_SCHED_QUEUES_PER_PIPE]; + uint32_t n_subport_profiles; + uint32_t n_max_subport_profiles; uint64_t rate; uint32_t mtu; uint32_t frame_overhead; @@ -230,6 +242,7 @@ struct rte_sched_port { uint32_t subport_id; /* Large data structures */ + struct rte_sched_subport_profile *subport_profiles; struct rte_sched_subport *subports[0] __rte_cache_aligned; } __rte_cache_aligned; @@ -375,9 +388,61 @@ pipe_profile_check(struct rte_sched_pipe_params *params, return 0; } +static int +subport_profile_check(struct rte_sched_subport_profile_params *params, + uint64_t rate) +{ + uint32_t i; + + /* Check user parameters */ + if (params == NULL) { + RTE_LOG(ERR, SCHED, "%s: " + "Incorrect value for parameter params\n", __func__); + return -EINVAL; + } + + if (params->tb_rate == 0 || params->tb_rate > rate) { + RTE_LOG(ERR, SCHED, "%s: " + "Incorrect value for tb rate\n", __func__); + return -EINVAL; + } + + if (params->tb_size == 0) { + RTE_LOG(ERR, SCHED, "%s: " + "Incorrect value for tb size\n", __func__); + return -EINVAL; + } + + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + uint64_t tc_rate = params->tc_rate[i]; + + if (tc_rate == 0 || (tc_rate > params->tb_rate)) { + RTE_LOG(ERR, SCHED, "%s: " + "Incorrect value for tc rate\n", __func__); + return -EINVAL; + } + } + + if (params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE] == 0) { + RTE_LOG(ERR, SCHED, "%s: " + "Incorrect tc rate(best effort)\n", __func__); + return -EINVAL; + } + + if (params->tc_period == 0) { + RTE_LOG(ERR, SCHED, "%s: " + "Incorrect value for tc period\n", __func__); + return -EINVAL; + } + + return 0; +} + static int rte_sched_port_check_params(struct rte_sched_port_params *params) { + uint32_t i; + if (params == NULL) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for parameter params\n", __func__); @@ -414,6 +479,29 @@ rte_sched_port_check_params(struct rte_sched_port_params *params) return -EINVAL; } + if (params->subport_profiles == NULL || + params->n_subport_profiles == 0 || + params->n_max_subport_profiles == 0 || + params->n_subport_profiles > params->n_max_subport_profiles) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for subport profiles\n", __func__); + return -EINVAL; + } + + for (i = 0; i < params->n_subport_profiles; i++) { + struct rte_sched_subport_profile_params *p = + params->subport_profiles + i; + int status; + + status = subport_profile_check(p, params->rate); + if (status != 0) { + RTE_LOG(ERR, SCHED, + "%s: subport profile check failed(%d)\n", + __func__, status); + return -EINVAL; + } + } + /* n_pipes_per_subport: non-zero, power of 2 */ if (params->n_pipes_per_subport == 0 || !rte_is_power_of_2(params->n_pipes_per_subport)) { @@ -555,6 +643,42 @@ rte_sched_port_log_pipe_profile(struct rte_sched_subport *subport, uint32_t i) p->wrr_cost[0], p->wrr_cost[1], p->wrr_cost[2], p->wrr_cost[3]); } +static void +rte_sched_port_log_subport_profile(struct rte_sched_port *port, uint32_t i) +{ + struct rte_sched_subport_profile *p = port->subport_profiles + i; + + RTE_LOG(DEBUG, SCHED, "Low level config for subport profile %u:\n" + "Token bucket: period = %"PRIu64", credits per period = %"PRIu64"," + "size = %"PRIu64"\n" + "Traffic classes: period = %"PRIu64",\n" + "credits per period = [%"PRIu64", %"PRIu64", %"PRIu64", %"PRIu64 + " %"PRIu64", %"PRIu64", %"PRIu64", %"PRIu64", %"PRIu64", %"PRIu64 + " %"PRIu64", %"PRIu64", %"PRIu64"]\n", + i, + + /* Token bucket */ + p->tb_period, + p->tb_credits_per_period, + p->tb_size, + + /* Traffic classes */ + p->tc_period, + p->tc_credits_per_period[0], + p->tc_credits_per_period[1], + p->tc_credits_per_period[2], + p->tc_credits_per_period[3], + p->tc_credits_per_period[4], + p->tc_credits_per_period[5], + p->tc_credits_per_period[6], + p->tc_credits_per_period[7], + p->tc_credits_per_period[8], + p->tc_credits_per_period[9], + p->tc_credits_per_period[10], + p->tc_credits_per_period[11], + p->tc_credits_per_period[12]); +} + static inline uint64_t rte_sched_time_ms_to_bytes(uint64_t time_ms, uint64_t rate) { @@ -623,6 +747,37 @@ rte_sched_pipe_profile_convert(struct rte_sched_subport *subport, dst->wrr_cost[3] = (uint8_t) wrr_cost[3]; } +static void +rte_sched_subport_profile_convert(struct rte_sched_subport_profile_params *src, + struct rte_sched_subport_profile *dst, + uint64_t rate) +{ + uint32_t i; + + /* Token Bucket */ + if (src->tb_rate == rate) { + dst->tb_credits_per_period = 1; + dst->tb_period = 1; + } else { + double tb_rate = (double) src->tb_rate + / (double) rate; + double d = RTE_SCHED_TB_RATE_CONFIG_ERR; + + rte_approx_64(tb_rate, d, &dst->tb_credits_per_period, + &dst->tb_period); + } + + dst->tb_size = src->tb_size; + + /* Traffic Classes */ + dst->tc_period = rte_sched_time_ms_to_bytes(src->tc_period, rate); + + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) + dst->tc_credits_per_period[i] + = rte_sched_time_ms_to_bytes(src->tc_period, + src->tc_rate[i]); +} + static void rte_sched_subport_config_pipe_profile_table(struct rte_sched_subport *subport, struct rte_sched_subport_params *params, uint64_t rate) @@ -647,6 +802,24 @@ rte_sched_subport_config_pipe_profile_table(struct rte_sched_subport *subport, } } +static void +rte_sched_port_config_subport_profile_table(struct rte_sched_port *port, + struct rte_sched_port_params *params, + uint64_t rate) +{ + uint32_t i; + + for (i = 0; i < port->n_subport_profiles; i++) { + struct rte_sched_subport_profile_params *src + = params->subport_profiles + i; + struct rte_sched_subport_profile *dst + = port->subport_profiles + i; + + rte_sched_subport_profile_convert(src, dst, rate); + rte_sched_port_log_subport_profile(port, i); + } +} + static int rte_sched_subport_check_params(struct rte_sched_subport_params *params, uint32_t n_max_pipes_per_subport, @@ -793,7 +966,7 @@ struct rte_sched_port * rte_sched_port_config(struct rte_sched_port_params *params) { struct rte_sched_port *port = NULL; - uint32_t size0, size1; + uint32_t size0, size1, size2; uint32_t cycles_per_byte; uint32_t i, j; int status; @@ -808,10 +981,21 @@ rte_sched_port_config(struct rte_sched_port_params *params) size0 = sizeof(struct rte_sched_port); size1 = params->n_subports_per_port * sizeof(struct rte_sched_subport *); + size2 = params->n_max_subport_profiles * + sizeof(struct rte_sched_subport_profile); /* Allocate memory to store the data structures */ - port = rte_zmalloc_socket("qos_params", size0 + size1, RTE_CACHE_LINE_SIZE, - params->socket); + port = rte_zmalloc_socket("qos_params", size0 + size1, + RTE_CACHE_LINE_SIZE, params->socket); + if (port == NULL) { + RTE_LOG(ERR, SCHED, "%s: Memory allocation fails\n", __func__); + + return NULL; + } + + /* Allocate memory to store the subport profile */ + port->subport_profiles = rte_zmalloc_socket("subport_profile", size2, + RTE_CACHE_LINE_SIZE, params->socket); if (port == NULL) { RTE_LOG(ERR, SCHED, "%s: Memory allocation fails\n", __func__); @@ -820,6 +1004,8 @@ rte_sched_port_config(struct rte_sched_port_params *params) /* User parameters */ port->n_subports_per_port = params->n_subports_per_port; + port->n_subport_profiles = params->n_subport_profiles; + port->n_max_subport_profiles = params->n_max_subport_profiles; port->n_pipes_per_subport = params->n_pipes_per_subport; port->n_pipes_per_subport_log2 = __builtin_ctz(params->n_pipes_per_subport); @@ -850,6 +1036,9 @@ rte_sched_port_config(struct rte_sched_port_params *params) port->time_cpu_bytes = 0; port->time = 0; + /* Subport profile table */ + rte_sched_port_config_subport_profile_table(port, params, port->rate); + cycles_per_byte = (rte_get_tsc_hz() << RTE_SCHED_TIME_SHIFT) / params->rate; port->inv_cycles_per_byte = rte_reciprocal_value(cycles_per_byte); @@ -905,6 +1094,7 @@ rte_sched_port_free(struct rte_sched_port *port) for (i = 0; i < port->n_subports_per_port; i++) rte_sched_subport_free(port, port->subports[i]); + rte_free(port->subport_profiles); rte_free(port); } @@ -961,6 +1151,7 @@ rte_sched_free_memory(struct rte_sched_port *port, uint32_t n_subports) rte_sched_subport_free(port, subport); } + rte_free(port->subport_profiles); rte_free(port); } diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index 8a5a93c98..39339b7f1 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -192,6 +192,20 @@ struct rte_sched_subport_params { #endif }; +struct rte_sched_subport_profile_params { + /** Token bucket rate (measured in bytes per second) */ + uint64_t tb_rate; + + /** Token bucket size (measured in credits) */ + uint64_t tb_size; + + /** Traffic class rates (measured in bytes per second) */ + uint64_t tc_rate[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + + /** Enforcement period for rates (measured in milliseconds) */ + uint64_t tc_period; +}; + /** Subport statistics */ struct rte_sched_subport_stats { /** Number of packets successfully written */ @@ -254,6 +268,17 @@ struct rte_sched_port_params { /** Number of subports */ uint32_t n_subports_per_port; + /** subport profile table. + * Every pipe is configured using one of the profiles from this table. + */ + struct rte_sched_subport_profile_params *subport_profiles; + + /** Profiles in the pipe profile table */ + uint32_t n_subport_profiles; + + /** Max allowed profiles in the pipe profile table */ + uint32_t n_max_subport_profiles; + /** Maximum number of subport pipes. * This parameter is used to reserve a fixed number of bits * in struct rte_mbuf::sched.queue_id for the pipe_id for all -- 2.17.1