From patchwork Mon May 30 18:47:14 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Danilewicz, MarcinX" X-Patchwork-Id: 112092 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 34DA9A0544; Mon, 30 May 2022 20:47:24 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id E4CA5400EF; Mon, 30 May 2022 20:47:23 +0200 (CEST) Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by mails.dpdk.org (Postfix) with ESMTP id 69771400D6 for ; Mon, 30 May 2022 20:47:22 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1653936442; x=1685472442; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=dRCeGq0aUSoKW2x0tOaW35+3QwX0h1BsXhPmWOMdI+I=; b=msZwcmL9A5/o1qceuG+5qQs+0k43zzlc3loRzB2YlD5MYVGvqbWC9EcQ 1fa8Akwopg3MBo0gF+ibyKhNAUpe7zh3ZGOhRAEwmJRgDkOyAVVagaBoE PDnKMiDqoOqAMYDkVo/5YNQ16LxXBerRLUYcvOqBKae5btjeQOTCxZXHu yJB80iBZspRyummPtFDubLUqDgkYQDQevBBxw5ibe62IGfHEDLcnfI4il 1dMEKMYdvo+Jqit4AtViwKjkZTGBEmfK17k8RTZFvgSeFcFT5RaeCD6zq y5hfOqMZYZml/B9QyAmBF+pQkZkbUPJaNLVqNfF48TIZCZ1kPO/MPHh2t A==; X-IronPort-AV: E=McAfee;i="6400,9594,10363"; a="274781668" X-IronPort-AV: E=Sophos;i="5.91,263,1647327600"; d="scan'208";a="274781668" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 30 May 2022 11:47:21 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.91,263,1647327600"; d="scan'208";a="611525214" Received: from silpixa00400629.ir.intel.com ([10.237.213.88]) by orsmga001.jf.intel.com with ESMTP; 30 May 2022 11:47:19 -0700 From: Marcin Danilewicz To: dev@dpdk.org, jasvinder.singh@intel.com, cristian.dumitrescu@intel.com Cc: megha.ajmera@intel.com Subject: [PATCH v9] sched: enable traffic class oversubscription conditionally Date: Mon, 30 May 2022 18:47:14 +0000 Message-Id: <20220530184714.834764-1-marcinx.danilewicz@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220530133831.830307-1-marcinx.danilewicz@intel.com> References: <20220530133831.830307-1-marcinx.danilewicz@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Added new API for flag to enable or disable TC oversubscription for best effort traffic class at subport level. By default TC OV is enabled. Signed-off-by: Marcin Danilewicz --- History: - v1 - TC OV disabled by default - v2 - throughput improvements - v3, v4, v5 - changes from comments - v6 - removed rte_sched_subport_tc_ov_config declaration and map - v7 - changes from comments on v6 - v8, v9 - changes from comments on v7 --- lib/sched/rte_sched.c | 118 ++++++++++++++++++++++++++++++++++++++++-- lib/sched/rte_sched.h | 18 +++++++ lib/sched/version.map | 3 ++ 3 files changed, 136 insertions(+), 3 deletions(-) diff --git a/lib/sched/rte_sched.c b/lib/sched/rte_sched.c index ec74bee939..599c7e9536 100644 --- a/lib/sched/rte_sched.c +++ b/lib/sched/rte_sched.c @@ -213,6 +213,9 @@ struct rte_sched_subport { uint8_t *bmp_array; struct rte_mbuf **queue_array; uint8_t memory[0] __rte_cache_aligned; + + /* TC oversubscription activation */ + int tc_ov_enabled; } __rte_cache_aligned; struct rte_sched_port { @@ -1165,6 +1168,31 @@ rte_sched_cman_config(struct rte_sched_port *port, } #endif +int +rte_sched_subport_tc_ov_config(struct rte_sched_port *port, + uint32_t subport_id, + bool tc_ov_enable) +{ + struct rte_sched_subport *s; + + if (port == NULL) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for parameter port\n", __func__); + return -EINVAL; + } + + if (subport_id >= port->n_subports_per_port) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for parameter subport id\n", __func__); + return -EINVAL; + } + + s = port->subports[subport_id]; + s->tc_ov_enabled = tc_ov_enable ? 1 : 0; + + return 0; +} + int rte_sched_subport_config(struct rte_sched_port *port, uint32_t subport_id, @@ -1254,6 +1282,9 @@ rte_sched_subport_config(struct rte_sched_port *port, s->n_pipe_profiles = params->n_pipe_profiles; s->n_max_pipe_profiles = params->n_max_pipe_profiles; + /* TC oversubscription is enabled by default */ + s->tc_ov_enabled = 1; + #ifdef RTE_SCHED_CMAN if (params->cman_params != NULL) { s->cman_enabled = true; @@ -2318,6 +2349,45 @@ grinder_credits_update(struct rte_sched_port *port, pipe->tb_credits = RTE_MIN(pipe->tb_credits, params->tb_size); pipe->tb_time += n_periods * params->tb_period; + /* Subport TCs */ + if (unlikely(port->time >= subport->tc_time)) { + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) + subport->tc_credits[i] = sp->tc_credits_per_period[i]; + + subport->tc_time = port->time + sp->tc_period; + } + + /* Pipe TCs */ + if (unlikely(port->time >= pipe->tc_time)) { + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) + pipe->tc_credits[i] = params->tc_credits_per_period[i]; + pipe->tc_time = port->time + params->tc_period; + } +} + +static inline void +grinder_credits_update_with_tc_ov(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) +{ + struct rte_sched_grinder *grinder = subport->grinder + pos; + struct rte_sched_pipe *pipe = grinder->pipe; + struct rte_sched_pipe_profile *params = grinder->pipe_params; + struct rte_sched_subport_profile *sp = grinder->subport_params; + uint64_t n_periods; + uint32_t i; + + /* Subport TB */ + n_periods = (port->time - subport->tb_time) / sp->tb_period; + subport->tb_credits += n_periods * sp->tb_credits_per_period; + subport->tb_credits = RTE_MIN(subport->tb_credits, sp->tb_size); + subport->tb_time += n_periods * sp->tb_period; + + /* Pipe TB */ + n_periods = (port->time - pipe->tb_time) / params->tb_period; + pipe->tb_credits += n_periods * params->tb_credits_per_period; + pipe->tb_credits = RTE_MIN(pipe->tb_credits, params->tb_size); + pipe->tb_time += n_periods * params->tb_period; + /* Subport TCs */ if (unlikely(port->time >= subport->tc_time)) { subport->tc_ov_wm = @@ -2348,6 +2418,39 @@ grinder_credits_update(struct rte_sched_port *port, static inline int grinder_credits_check(struct rte_sched_port *port, struct rte_sched_subport *subport, uint32_t pos) +{ + struct rte_sched_grinder *grinder = subport->grinder + pos; + struct rte_sched_pipe *pipe = grinder->pipe; + struct rte_mbuf *pkt = grinder->pkt; + uint32_t tc_index = grinder->tc_index; + uint64_t pkt_len = pkt->pkt_len + port->frame_overhead; + uint64_t subport_tb_credits = subport->tb_credits; + uint64_t subport_tc_credits = subport->tc_credits[tc_index]; + uint64_t pipe_tb_credits = pipe->tb_credits; + uint64_t pipe_tc_credits = pipe->tc_credits[tc_index]; + int enough_credits; + + /* Check pipe and subport credits */ + enough_credits = (pkt_len <= subport_tb_credits) && + (pkt_len <= subport_tc_credits) && + (pkt_len <= pipe_tb_credits) && + (pkt_len <= pipe_tc_credits); + + if (!enough_credits) + return 0; + + /* Update pipe and subport credits */ + subport->tb_credits -= pkt_len; + subport->tc_credits[tc_index] -= pkt_len; + pipe->tb_credits -= pkt_len; + pipe->tc_credits[tc_index] -= pkt_len; + + return 1; +} + +static inline int +grinder_credits_check_with_tc_ov(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; @@ -2403,8 +2506,13 @@ grinder_schedule(struct rte_sched_port *port, uint32_t pkt_len = pkt->pkt_len + port->frame_overhead; uint32_t be_tc_active; - if (!grinder_credits_check(port, subport, pos)) - return 0; + if (subport->tc_ov_enabled) { + if (!grinder_credits_check_with_tc_ov(port, subport, pos)) + return 0; + } else { + if (!grinder_credits_check(port, subport, pos)) + return 0; + } /* Advance port time */ port->time += pkt_len; @@ -2770,7 +2878,11 @@ grinder_handle(struct rte_sched_port *port, subport->profile; grinder_prefetch_tc_queue_arrays(subport, pos); - grinder_credits_update(port, subport, pos); + + if (subport->tc_ov_enabled) + grinder_credits_update_with_tc_ov(port, subport, pos); + else + grinder_credits_update(port, subport, pos); grinder->state = e_GRINDER_PREFETCH_MBUF; return 0; diff --git a/lib/sched/rte_sched.h b/lib/sched/rte_sched.h index 5ece64e527..317ab3b68e 100644 --- a/lib/sched/rte_sched.h +++ b/lib/sched/rte_sched.h @@ -579,6 +579,24 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, uint int rte_sched_port_dequeue(struct rte_sched_port *port, struct rte_mbuf **pkts, uint32_t n_pkts); +/** + * Hierarchical scheduler subport traffic class oversubscription called + * to enable/disable feature at runtime. + * This function should be called at the time of subport initialization. + * + * @param port + * Handle to port scheduler instance + * @param subport_id + * Subport ID + * @param tc_ov_enable + * Boolean flag to enable/disable TC OV + * @return + * 0 upon success, error code otherwise + */ +__rte_experimental +int +rte_sched_subport_tc_ov_config(struct rte_sched_port *port, uint32_t subport_id, bool tc_ov_enable); + #ifdef __cplusplus } #endif diff --git a/lib/sched/version.map b/lib/sched/version.map index d22c07fc9f..13d7510584 100644 --- a/lib/sched/version.map +++ b/lib/sched/version.map @@ -34,4 +34,7 @@ EXPERIMENTAL { # added in 21.11 rte_pie_rt_data_init; rte_pie_config_init; + + # added in 22.07 + rte_sched_subport_tc_ov_config; };