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 63C92A0471 for ; Tue, 16 Jul 2019 02:37:24 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 3EED02C5E; Tue, 16 Jul 2019 02:37:23 +0200 (CEST) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by dpdk.org (Postfix) with ESMTP id 920CAF04 for ; Tue, 16 Jul 2019 02:37:20 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 15 Jul 2019 17:37:20 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.63,494,1557212400"; d="scan'208";a="169770371" Received: from irsmsx152.ger.corp.intel.com ([163.33.192.66]) by orsmga003.jf.intel.com with ESMTP; 15 Jul 2019 17:37:18 -0700 Received: from irsmsx108.ger.corp.intel.com ([169.254.11.229]) by IRSMSX152.ger.corp.intel.com ([169.254.6.27]) with mapi id 14.03.0439.000; Tue, 16 Jul 2019 01:37:17 +0100 From: "Dumitrescu, Cristian" To: "Singh, Jasvinder" , "dev@dpdk.org" CC: "Tovar, AbrahamX" , "Krakowiak, LukaszX" Thread-Topic: [PATCH v4 02/11] sched: add config flexibility to tc queue sizes Thread-Index: AQHVOJhCfRXPuXbGVEOwlaPhQ0jzf6bMXw+w Date: Tue, 16 Jul 2019 00:37:17 +0000 Message-ID: <3EB4FA525960D640B5BDFFD6A3D891268E8EEDD4@IRSMSX108.ger.corp.intel.com> References: <20190711102659.59001-2-jasvinder.singh@intel.com> <20190712095729.159767-1-jasvinder.singh@intel.com> <20190712095729.159767-3-jasvinder.singh@intel.com> In-Reply-To: <20190712095729.159767-3-jasvinder.singh@intel.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-titus-metadata-40: eyJDYXRlZ29yeUxhYmVscyI6IiIsIk1ldGFkYXRhIjp7Im5zIjoiaHR0cDpcL1wvd3d3LnRpdHVzLmNvbVwvbnNcL0ludGVsMyIsImlkIjoiMmE3NDg2MjEtZTM1Zi00YjA3LWE3M2ItZDUxMmRhY2QwNWM0IiwicHJvcHMiOlt7Im4iOiJDVFBDbGFzc2lmaWNhdGlvbiIsInZhbHMiOlt7InZhbHVlIjoiQ1RQX05UIn1dfV19LCJTdWJqZWN0TGFiZWxzIjpbXSwiVE1DVmVyc2lvbiI6IjE3LjEwLjE4MDQuNDkiLCJUcnVzdGVkTGFiZWxIYXNoIjoicGQwVE5pVEhQNnVTTGFqKzdrK0pnb2Yya1VaQ0lqZk96eXdnM3h5Wlc3T2pqVk0yU0dVeTdkU2Y5bFRncW5xNiJ9 x-ctpclassification: CTP_NT dlp-product: dlpe-windows dlp-version: 11.2.0.6 dlp-reaction: no-action x-originating-ip: [163.33.239.180] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Subject: Re: [dpdk-dev] [PATCH v4 02/11] sched: add config flexibility to tc queue sizes 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" > -----Original Message----- > From: Singh, Jasvinder > Sent: Friday, July 12, 2019 11:57 AM > To: dev@dpdk.org > Cc: Dumitrescu, Cristian ; Tovar, AbrahamX > ; Krakowiak, LukaszX > > Subject: [PATCH v4 02/11] sched: add config flexibility to tc queue sizes >=20 > Add support for zero queue sizes of the traffic classes. The queues > which are not used can be set to zero size. This helps in reducing > memory footprint of the hierarchical scheduler. >=20 > Signed-off-by: Jasvinder Singh > Signed-off-by: Abraham Tovar > Signed-off-by: Lukasz Krakowiak > --- > lib/librte_sched/rte_sched.c | 354 +++++++++++++++++++---------------- > lib/librte_sched/rte_sched.h | 12 +- > 2 files changed, 198 insertions(+), 168 deletions(-) >=20 > diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c > index b1f521794..411924c36 100644 > --- a/lib/librte_sched/rte_sched.c > +++ b/lib/librte_sched/rte_sched.c > @@ -149,15 +149,15 @@ struct rte_sched_grinder { > struct rte_sched_pipe_profile *pipe_params; >=20 > /* TC cache */ > - uint8_t tccache_qmask[4]; > - uint32_t tccache_qindex[4]; > + uint8_t tccache_qmask[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; > + uint32_t tccache_qindex[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; > uint32_t tccache_w; > uint32_t tccache_r; >=20 > /* Current TC */ > uint32_t tc_index; > - struct rte_sched_queue > *queue[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; > - struct rte_mbuf **qbase[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; > + struct rte_sched_queue > *queue[RTE_SCHED_MAX_QUEUES_PER_TC]; > + struct rte_mbuf **qbase[RTE_SCHED_MAX_QUEUES_PER_TC]; > uint32_t qindex[RTE_SCHED_MAX_QUEUES_PER_TC]; > uint16_t qsize[RTE_SCHED_MAX_QUEUES_PER_TC]; > uint32_t qmask; > @@ -178,7 +178,7 @@ struct rte_sched_port { > uint32_t rate; > uint32_t mtu; > uint32_t frame_overhead; > - uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; > + uint16_t qsize[RTE_SCHED_QUEUES_PER_PIPE]; > uint32_t n_pipe_profiles; > uint32_t pipe_tc3_rate_max; > #ifdef RTE_SCHED_RED > @@ -260,14 +260,13 @@ rte_sched_port_qbase(struct rte_sched_port > *port, uint32_t qindex) > static inline uint16_t > rte_sched_port_qsize(struct rte_sched_port *port, uint32_t qindex) > { > - uint32_t tc =3D (qindex >> 2) & 0x3; > - > - return port->qsize[tc]; > + uint32_t qpos =3D qindex & 0xF; > + return port->qsize[qpos]; > } >=20 > static int > pipe_profile_check(struct rte_sched_pipe_params *params, > - uint32_t rate) > + uint32_t rate, uint16_t *qsize) > { > uint32_t i; >=20 > @@ -285,12 +284,17 @@ pipe_profile_check(struct rte_sched_pipe_params > *params, > return -12; >=20 > /* TC rate: non-zero, less than pipe rate */ > - for (i =3D 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { > - if (params->tc_rate[i] =3D=3D 0 || > - params->tc_rate[i] > params->tb_rate) > + for (i =3D 0; i < RTE_SCHED_TRAFFIC_CLASS_BE; i++) { > + if ((qsize[i] =3D=3D 0 && params->tc_rate[i] !=3D 0) || > + (qsize[i] !=3D 0 && (params->tc_rate[i] =3D=3D 0 || > + params->tc_rate[i] > params->tb_rate))) > return -13; > + > } >=20 > + if (params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE] =3D=3D 0) > + return -13; You forgot to check that pipe BE TC rate is not bigger than the pipe rate, = which is a check that is enforced for the other higher priority traffic cla= sses. > + > /* TC period: non-zero */ > if (params->tc_period =3D=3D 0) > return -14; > @@ -302,8 +306,10 @@ pipe_profile_check(struct rte_sched_pipe_params > *params, > #endif >=20 > /* Queue WRR weights: non-zero */ > - for (i =3D 0; i < RTE_SCHED_QUEUES_PER_PIPE; i++) { > - if (params->wrr_weights[i] =3D=3D 0) > + for (i =3D 0; i < RTE_SCHED_BE_QUEUES_PER_PIPE; i++) { > + uint32_t qindex =3D RTE_SCHED_TRAFFIC_CLASS_BE + i; > + if ((qsize[qindex] !=3D 0 && params->wrr_weights[i] =3D=3D 0) || > + (qsize[qindex] =3D=3D 0 && params->wrr_weights[i] !=3D > 0)) > return -16; > } > return 0; > @@ -343,10 +349,10 @@ rte_sched_port_check_params(struct > rte_sched_port_params *params) > /* qsize: non-zero, power of 2, > * no bigger than 32K (due to 16-bit read/write pointers) > */ > - for (i =3D 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { > + for (i =3D 0; i < RTE_SCHED_QUEUES_PER_PIPE; i++) { > uint16_t qsize =3D params->qsize[i]; > - > - if (qsize =3D=3D 0 || !rte_is_power_of_2(qsize)) > + if ((qsize !=3D 0 && !rte_is_power_of_2(qsize)) || > + ((i =3D=3D RTE_SCHED_TRAFFIC_CLASS_BE) && (qsize =3D=3D > 0))) > return -8; > } >=20 > @@ -360,7 +366,7 @@ rte_sched_port_check_params(struct > rte_sched_port_params *params) > struct rte_sched_pipe_params *p =3D params->pipe_profiles + > i; > int status; >=20 > - status =3D pipe_profile_check(p, params->rate); > + status =3D pipe_profile_check(p, params->rate, ¶ms- > >qsize[0]); > if (status !=3D 0) > return status; > } > @@ -389,9 +395,9 @@ rte_sched_port_get_array_base(struct > rte_sched_port_params *params, enum rte_sch > uint32_t base, i; >=20 > size_per_pipe_queue_array =3D 0; > - for (i =3D 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { > - size_per_pipe_queue_array +=3D > RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS > - * params->qsize[i] * sizeof(struct rte_mbuf *); > + for (i =3D 0; i < RTE_SCHED_QUEUES_PER_PIPE; i++) { > + size_per_pipe_queue_array +=3D > + params->qsize[i] * sizeof(struct rte_mbuf *); > } > size_queue_array =3D n_pipes_per_port * > size_per_pipe_queue_array; >=20 > @@ -451,31 +457,12 @@ rte_sched_port_get_memory_footprint(struct > rte_sched_port_params *params) > static void > rte_sched_port_config_qsize(struct rte_sched_port *port) > { > - /* TC 0 */ > + uint32_t i; > port->qsize_add[0] =3D 0; > - port->qsize_add[1] =3D port->qsize_add[0] + port->qsize[0]; > - port->qsize_add[2] =3D port->qsize_add[1] + port->qsize[0]; > - port->qsize_add[3] =3D port->qsize_add[2] + port->qsize[0]; > - > - /* TC 1 */ > - port->qsize_add[4] =3D port->qsize_add[3] + port->qsize[0]; > - port->qsize_add[5] =3D port->qsize_add[4] + port->qsize[1]; > - port->qsize_add[6] =3D port->qsize_add[5] + port->qsize[1]; > - port->qsize_add[7] =3D port->qsize_add[6] + port->qsize[1]; > - > - /* TC 2 */ > - port->qsize_add[8] =3D port->qsize_add[7] + port->qsize[1]; > - port->qsize_add[9] =3D port->qsize_add[8] + port->qsize[2]; > - port->qsize_add[10] =3D port->qsize_add[9] + port->qsize[2]; > - port->qsize_add[11] =3D port->qsize_add[10] + port->qsize[2]; > - > - /* TC 3 */ > - port->qsize_add[12] =3D port->qsize_add[11] + port->qsize[2]; > - port->qsize_add[13] =3D port->qsize_add[12] + port->qsize[3]; > - port->qsize_add[14] =3D port->qsize_add[13] + port->qsize[3]; > - port->qsize_add[15] =3D port->qsize_add[14] + port->qsize[3]; > - > - port->qsize_sum =3D port->qsize_add[15] + port->qsize[3]; > + for (i =3D 1; i < RTE_SCHED_QUEUES_PER_PIPE; i++) > + port->qsize_add[i] =3D port->qsize_add[i-1] + port->qsize[i-1]; > + > + port->qsize_sum =3D port->qsize_add[15] + port->qsize[15]; > } >=20 > static void > @@ -484,10 +471,11 @@ rte_sched_port_log_pipe_profile(struct > rte_sched_port *port, uint32_t i) > struct rte_sched_pipe_profile *p =3D port->pipe_profiles + i; >=20 > RTE_LOG(DEBUG, SCHED, "Low level config for pipe profile %u:\n" > - " Token bucket: period =3D %u, credits per period =3D %u, size =3D > %u\n" > - " Traffic classes: period =3D %u, credits per period =3D [%u, %u, > %u, %u]\n" > - " Traffic class 3 oversubscription: weight =3D %hhu\n" > - " WRR cost: [%hhu, %hhu, %hhu, %hhu]\n", > + " Token bucket: period =3D %u, credits per period =3D %u, > size =3D %u\n" > + " Traffic classes: period =3D %u,\n" > + " credits per period =3D [%u, %u, %u, %u, %u, %u, %u, > %u, %u, %u, %u, %u, %u]\n" > + " Best-effort traffic class oversubscription: weight =3D > %hhu\n" > + " WRR cost: [%hhu, %hhu, %hhu, %hhu]\n", > i, >=20 > /* Token bucket */ > @@ -501,8 +489,17 @@ rte_sched_port_log_pipe_profile(struct > rte_sched_port *port, uint32_t i) > p->tc_credits_per_period[1], > p->tc_credits_per_period[2], > p->tc_credits_per_period[3], > - > - /* Traffic class 3 oversubscription */ > + 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], > + > + /* Best-effort traffic class oversubscription */ > p->tc_ov_weight, >=20 > /* WRR */ > @@ -548,9 +545,10 @@ rte_sched_pipe_profile_convert(struct > rte_sched_port *port, > rate); >=20 > for (i =3D 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) > - dst->tc_credits_per_period[i] > - =3D rte_sched_time_ms_to_bytes(src->tc_period, > - src->tc_rate[i]); > + if (port->qsize[i]) > + dst->tc_credits_per_period[i] > + =3D rte_sched_time_ms_to_bytes(src- > >tc_period, > + src->tc_rate[i]); >=20 > #ifdef RTE_SCHED_SUBPORT_TC_OV The TC_OV logic should be enabled for all the configuration/initialization = code; the only place it should be conditionally enabled is the run-time cod= e (e.g. grinder update/schedule), so no need for this #ifdef here. Same in = many other places, should be easy to change for a consistent approach. > dst->tc_ov_weight =3D src->tc_ov_weight; > @@ -558,7 +556,7 @@ rte_sched_pipe_profile_convert(struct > rte_sched_port *port, >=20 > /* WRR queues */ > for (i =3D 0; i < RTE_SCHED_BE_QUEUES_PER_PIPE; i++) > - if (port->qsize[i]) > + if (port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE + i]) > dst->n_be_queues++; >=20 > if (dst->n_be_queues =3D=3D 1) > @@ -620,7 +618,7 @@ rte_sched_port_config_pipe_profile_table(struct > rte_sched_port *port, > port->pipe_tc3_rate_max =3D 0; > for (i =3D 0; i < port->n_pipe_profiles; i++) { > struct rte_sched_pipe_params *src =3D params->pipe_profiles > + i; > - uint32_t pipe_tc3_rate =3D src->tc_rate[3]; > + uint32_t pipe_tc3_rate =3D src- > >tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; >=20 > if (port->pipe_tc3_rate_max < pipe_tc3_rate) > port->pipe_tc3_rate_max =3D pipe_tc3_rate; > @@ -762,12 +760,14 @@ rte_sched_port_free(struct rte_sched_port *port) > for (qindex =3D 0; qindex < n_queues_per_port; qindex++) { > struct rte_mbuf **mbufs =3D rte_sched_port_qbase(port, > qindex); > uint16_t qsize =3D rte_sched_port_qsize(port, qindex); > - struct rte_sched_queue *queue =3D port->queue + qindex; > - uint16_t qr =3D queue->qr & (qsize - 1); > - uint16_t qw =3D queue->qw & (qsize - 1); > + if (qsize !=3D 0) { > + struct rte_sched_queue *queue =3D port->queue + > qindex; > + uint16_t qr =3D queue->qr & (qsize - 1); > + uint16_t qw =3D queue->qw & (qsize - 1); >=20 > - for (; qr !=3D qw; qr =3D (qr + 1) & (qsize - 1)) > - rte_pktmbuf_free(mbufs[qr]); > + for (; qr !=3D qw; qr =3D (qr + 1) & (qsize - 1)) > + rte_pktmbuf_free(mbufs[qr]); > + } > } >=20 > rte_bitmap_free(port->bmp); > @@ -780,9 +780,10 @@ rte_sched_port_log_subport_config(struct > rte_sched_port *port, uint32_t i) > struct rte_sched_subport *s =3D port->subport + i; >=20 > RTE_LOG(DEBUG, SCHED, "Low level config for subport %u:\n" > - " Token bucket: period =3D %u, credits per period =3D %u, size =3D > %u\n" > - " Traffic classes: period =3D %u, credits per period =3D [%u, %u, > %u, %u]\n" > - " Traffic class 3 oversubscription: wm min =3D %u, wm max =3D > %u\n", > + " Token bucket: period =3D %u, credits per period =3D %u, > size =3D %u\n" > + " Traffic classes: period =3D %u\n" > + " credits per period =3D [%u, %u, %u, %u, %u, %u, %u, > %u, %u, %u, %u, %u, %u]\n" > + " Best effort traffic class oversubscription: wm min =3D > %u, wm max =3D %u\n", > i, >=20 > /* Token bucket */ > @@ -796,8 +797,17 @@ rte_sched_port_log_subport_config(struct > rte_sched_port *port, uint32_t i) > s->tc_credits_per_period[1], > s->tc_credits_per_period[2], > s->tc_credits_per_period[3], > - > - /* Traffic class 3 oversubscription */ > + s->tc_credits_per_period[4], > + s->tc_credits_per_period[5], > + s->tc_credits_per_period[6], > + s->tc_credits_per_period[7], > + s->tc_credits_per_period[8], > + s->tc_credits_per_period[9], > + s->tc_credits_per_period[10], > + s->tc_credits_per_period[11], > + s->tc_credits_per_period[12], > + > + /* Best effort traffic class oversubscription */ > s->tc_ov_wm_min, > s->tc_ov_wm_max); > } > @@ -808,7 +818,7 @@ rte_sched_subport_config(struct rte_sched_port > *port, > struct rte_sched_subport_params *params) > { > struct rte_sched_subport *s; > - uint32_t i; > + uint32_t i, j; >=20 > /* Check user parameters */ > if (port =3D=3D NULL || > @@ -822,12 +832,24 @@ rte_sched_subport_config(struct rte_sched_port > *port, > if (params->tb_size =3D=3D 0) > return -3; >=20 > - for (i =3D 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { > - if (params->tc_rate[i] =3D=3D 0 || > - params->tc_rate[i] > params->tb_rate) > - return -4; > + for (i =3D 0, j =3D 0; i < RTE_SCHED_QUEUES_PER_PIPE; i++) { > + uint32_t tc_rate =3D params->tc_rate[j]; > + uint16_t qsize =3D port->qsize[i]; > + > + if (((qsize =3D=3D 0) && > + ((tc_rate !=3D 0) && (j !=3D > RTE_SCHED_TRAFFIC_CLASS_BE))) || > + ((qsize !=3D 0) && (tc_rate =3D=3D 0)) || > + (tc_rate > params->tb_rate)) > + return -3; > + > + if (j < RTE_SCHED_TRAFFIC_CLASS_BE) > + j++; > } >=20 > + if (port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE] =3D=3D 0 || > + params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE] =3D=3D 0) > + return -3; > + > if (params->tc_period =3D=3D 0) > return -5; >=20 > @@ -851,13 +873,16 @@ rte_sched_subport_config(struct rte_sched_port > *port, > /* Traffic Classes (TCs) */ > s->tc_period =3D rte_sched_time_ms_to_bytes(params->tc_period, > port->rate); > for (i =3D 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { > - s->tc_credits_per_period[i] > - =3D rte_sched_time_ms_to_bytes(params->tc_period, > - params->tc_rate[i]); > + if (port->qsize[i]) > + s->tc_credits_per_period[i] > + =3D rte_sched_time_ms_to_bytes(params- > >tc_period, > + params- > >tc_rate[i]); > + > } > s->tc_time =3D port->time + s->tc_period; > for (i =3D 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) > - s->tc_credits[i] =3D s->tc_credits_per_period[i]; > + if (port->qsize[i]) > + s->tc_credits[i] =3D s->tc_credits_per_period[i]; >=20 > #ifdef RTE_SCHED_SUBPORT_TC_OV > /* TC oversubscription */ > @@ -910,9 +935,9 @@ rte_sched_pipe_config(struct rte_sched_port *port, > params =3D port->pipe_profiles + p->profile; >=20 > #ifdef RTE_SCHED_SUBPORT_TC_OV > - double subport_tc3_rate =3D (double) s- > >tc_credits_per_period[3] > + double subport_tc3_rate =3D (double) s- > >tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASS_BE] > / (double) s->tc_period; > - double pipe_tc3_rate =3D (double) params- > >tc_credits_per_period[3] > + double pipe_tc3_rate =3D (double) params- > >tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASS_BE] > / (double) params->tc_period; > uint32_t tc3_ov =3D s->tc_ov; >=20 > @@ -945,15 +970,19 @@ rte_sched_pipe_config(struct rte_sched_port > *port, >=20 > /* Traffic Classes (TCs) */ > p->tc_time =3D port->time + params->tc_period; > + p->n_be_queues =3D params->n_be_queues; > for (i =3D 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) > - p->tc_credits[i] =3D params->tc_credits_per_period[i]; > + if (port->qsize[i]) > + p->tc_credits[i] =3D params->tc_credits_per_period[i]; >=20 > #ifdef RTE_SCHED_SUBPORT_TC_OV > { > /* Subport TC3 oversubscription */ > - double subport_tc3_rate =3D (double) s- > >tc_credits_per_period[3] > + double subport_tc3_rate =3D > + (double) s- > >tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASS_BE] > / (double) s->tc_period; > - double pipe_tc3_rate =3D (double) params- > >tc_credits_per_period[3] > + double pipe_tc3_rate =3D > + (double) params- > >tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASS_BE] > / (double) params->tc_period; > uint32_t tc3_ov =3D s->tc_ov; >=20 > @@ -992,7 +1021,7 @@ rte_sched_port_pipe_profile_add(struct > rte_sched_port *port, > return -2; >=20 > /* Pipe params */ > - status =3D pipe_profile_check(params, port->rate); > + status =3D pipe_profile_check(params, port->rate, &port->qsize[0]); > if (status !=3D 0) > return status; >=20 > @@ -1008,8 +1037,8 @@ rte_sched_port_pipe_profile_add(struct > rte_sched_port *port, > *pipe_profile_id =3D port->n_pipe_profiles; > port->n_pipe_profiles++; >=20 > - if (port->pipe_tc3_rate_max < params->tc_rate[3]) > - port->pipe_tc3_rate_max =3D params->tc_rate[3]; > + if (port->pipe_tc3_rate_max < params- > >tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]) > + port->pipe_tc3_rate_max =3D params- > >tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; >=20 > rte_sched_port_log_pipe_profile(port, *pipe_profile_id); >=20 > @@ -1020,15 +1049,12 @@ static inline uint32_t > rte_sched_port_qindex(struct rte_sched_port *port, > uint32_t subport, > uint32_t pipe, > - uint32_t traffic_class, > uint32_t queue) > { > return ((subport & (port->n_subports_per_port - 1)) << > (port->n_pipes_per_subport_log2 + 4)) | > ((pipe & (port->n_pipes_per_subport - 1)) << 4) | > - ((traffic_class & > - (RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE - 1)) << > 2) | > - (queue & > (RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS - 1)); > + (queue & (RTE_SCHED_QUEUES_PER_PIPE - 1)); > } >=20 > void > @@ -1038,8 +1064,8 @@ rte_sched_port_pkt_write(struct rte_sched_port > *port, > uint32_t traffic_class, > uint32_t queue, enum rte_color color) > { > - uint32_t queue_id =3D rte_sched_port_qindex(port, subport, pipe, > - traffic_class, queue); > + uint32_t queue_id =3D rte_sched_port_qindex(port, subport, pipe, > queue); > + > rte_mbuf_sched_set(pkt, queue_id, traffic_class, (uint8_t)color); > } Ouch, this is a bug! The queue parameter of public function rte_sched_port_= pkt_write() is not the "queue within the pipe" (0 .. 15), it is actually th= e "queue within the traffic class" (0 for high priority TCs, 0 .. 3 for BE = TC), as explained in the API Doxygen description. You removed the traffic class parameter in the above rte_sched_port_qindex,= we should put it back and keep the initial meaning of the queue parameter = for the _qindex function, which is internal function. The way to quickly fix this is simply having a per-port pre-computed small = table of 16 entries indexed by the traffic class ID and provides the ID of = the first pipe queue of that traffic class; then you simply add "queue with= in traffic class" ID on top of this to get the "queue within pipe", which = provides the lower bits of the "queue within port" that this function is lo= oking to compute. Makes sense? It would be good to do some more tests to trace the packet through differen= t pipe traffic classes and queues. >=20 > @@ -1050,12 +1076,12 @@ rte_sched_port_pkt_read_tree_path(struct > rte_sched_port *port, > uint32_t *traffic_class, uint32_t *queue) > { > uint32_t queue_id =3D rte_mbuf_sched_queue_get(pkt); > + uint32_t tc_id =3D rte_mbuf_sched_traffic_class_get(pkt); I am afraid this is also incorrect, as although the mbuf->sched.traffic_cla= ss should be in sync with the traffic class built into the librte_sched hie= rarchy (and mbuf->sched.queue_id), there is no guarantee that: 1. The application is using and populating the mbuf->sched.traffic_class fi= eld 2. The application is assigning the same meaning or equivalence levels betw= een the mbuf->sched.traffic_class and the librte_sched hierarchy traffic cl= ass. We need to obtain the traffic class ID from queue ID, please. Thank you for= your understanding! There is also a quick way to do this as well through a similar small precom= puted table: input =3D "queue within pipe" ID, outputs are traffic class ID= and "queue within traffic class" ID. Makes sense? We need to use this strategy for all the places in this file, so in this fi= le we only use mbuf->sched.queue and not use mbuf->sched.traffic_class (nor= its accessor function rte_mbuf_sched_traffic_class_get()) at all. This acc= essor function shows up 4 times currently. >=20 > *subport =3D queue_id >> (port->n_pipes_per_subport_log2 + 4); > *pipe =3D (queue_id >> 4) & (port->n_pipes_per_subport - 1); > - *traffic_class =3D (queue_id >> 2) & > - (RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE - > 1); > - *queue =3D queue_id & (RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS - > 1); > + *traffic_class =3D tc_id; > + *queue =3D queue_id & (RTE_SCHED_QUEUES_PER_PIPE - 1); > } >=20 > enum rte_color > @@ -1136,7 +1162,7 @@ static inline void > rte_sched_port_update_subport_stats(struct rte_sched_port *port, > uint32_t qindex, struct rte_mbuf *pkt) > { > struct rte_sched_subport *s =3D port->subport + (qindex / > rte_sched_port_queues_per_subport(port)); > - uint32_t tc_index =3D (qindex >> 2) & 0x3; > + uint32_t tc_index =3D rte_mbuf_sched_traffic_class_get(pkt); See above comment. > uint32_t pkt_len =3D pkt->pkt_len; >=20 > s->stats.n_pkts_tc[tc_index] +=3D 1; > @@ -1156,7 +1182,7 @@ > rte_sched_port_update_subport_stats_on_drop(struct rte_sched_port > *port, > #endif > { > struct rte_sched_subport *s =3D port->subport + (qindex / > rte_sched_port_queues_per_subport(port)); > - uint32_t tc_index =3D (qindex >> 2) & 0x3; > + uint32_t tc_index =3D rte_mbuf_sched_traffic_class_get(pkt); See above comment. > uint32_t pkt_len =3D pkt->pkt_len; >=20 > s->stats.n_pkts_tc_dropped[tc_index] +=3D 1; > @@ -1211,7 +1237,7 @@ rte_sched_port_red_drop(struct rte_sched_port > *port, struct rte_mbuf *pkt, uint3 > uint32_t tc_index; > enum rte_color color; >=20 > - tc_index =3D (qindex >> 2) & 0x3; > + tc_index =3D rte_mbuf_sched_traffic_class_get(pkt); > color =3D rte_sched_port_pkt_read_color(pkt); > red_cfg =3D &port->red_config[tc_index][color]; >=20 > @@ -1528,6 +1554,7 @@ grinder_credits_update(struct rte_sched_port > *port, uint32_t pos) > struct rte_sched_pipe *pipe =3D grinder->pipe; > struct rte_sched_pipe_profile *params =3D grinder->pipe_params; > uint64_t n_periods; > + uint32_t i; >=20 > /* Subport TB */ > n_periods =3D (port->time - subport->tb_time) / subport->tb_period; > @@ -1543,19 +1570,17 @@ grinder_credits_update(struct rte_sched_port > *port, uint32_t pos) >=20 > /* Subport TCs */ > if (unlikely(port->time >=3D subport->tc_time)) { > - subport->tc_credits[0] =3D subport->tc_credits_per_period[0]; > - subport->tc_credits[1] =3D subport->tc_credits_per_period[1]; > - subport->tc_credits[2] =3D subport->tc_credits_per_period[2]; > - subport->tc_credits[3] =3D subport->tc_credits_per_period[3]; > + for (i =3D 0; i <=3D RTE_SCHED_TRAFFIC_CLASS_BE; i++) > + subport->tc_credits[i] =3D subport- > >tc_credits_per_period[i]; > + > subport->tc_time =3D port->time + subport->tc_period; > } >=20 > /* Pipe TCs */ > if (unlikely(port->time >=3D pipe->tc_time)) { > - pipe->tc_credits[0] =3D params->tc_credits_per_period[0]; > - pipe->tc_credits[1] =3D params->tc_credits_per_period[1]; > - pipe->tc_credits[2] =3D params->tc_credits_per_period[2]; > - pipe->tc_credits[3] =3D params->tc_credits_per_period[3]; > + for (i =3D 0; i <=3D RTE_SCHED_TRAFFIC_CLASS_BE; i++) > + pipe->tc_credits[i] =3D params- > >tc_credits_per_period[i]; > + > pipe->tc_time =3D port->time + params->tc_period; > } > } > @@ -1568,21 +1593,29 @@ grinder_tc_ov_credits_update(struct > rte_sched_port *port, uint32_t pos) > struct rte_sched_grinder *grinder =3D port->grinder + pos; > struct rte_sched_subport *subport =3D grinder->subport; > uint32_t > tc_ov_consumption[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; > - uint32_t tc_ov_consumption_max; > + uint32_t tc_consumption =3D 0, tc_ov_consumption_max; > uint32_t tc_ov_wm =3D subport->tc_ov_wm; > + uint32_t i; >=20 > if (subport->tc_ov =3D=3D 0) > return subport->tc_ov_wm_max; >=20 > - tc_ov_consumption[0] =3D subport->tc_credits_per_period[0] - > subport->tc_credits[0]; > - tc_ov_consumption[1] =3D subport->tc_credits_per_period[1] - > subport->tc_credits[1]; > - tc_ov_consumption[2] =3D subport->tc_credits_per_period[2] - > subport->tc_credits[2]; > - tc_ov_consumption[3] =3D subport->tc_credits_per_period[3] - > subport->tc_credits[3]; > + for (i =3D 0; i < RTE_SCHED_TRAFFIC_CLASS_BE; i++) { > + tc_ov_consumption[i] =3D > + subport->tc_credits_per_period[i] - subport- > >tc_credits[i]; > + tc_consumption +=3D tc_ov_consumption[i]; > + } > + > + tc_ov_consumption[RTE_SCHED_TRAFFIC_CLASS_BE] =3D > + subport- > >tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASS_BE] - > + subport->tc_credits[RTE_SCHED_TRAFFIC_CLASS_BE]; > + >=20 > - tc_ov_consumption_max =3D subport->tc_credits_per_period[3] - > - (tc_ov_consumption[0] + tc_ov_consumption[1] + > tc_ov_consumption[2]); > + tc_ov_consumption_max =3D > + subport- > >tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASS_BE] - tc_consumption; >=20 > - if (tc_ov_consumption[3] > (tc_ov_consumption_max - port->mtu)) > { > + if (tc_ov_consumption[RTE_SCHED_TRAFFIC_CLASS_BE] > > + (tc_ov_consumption_max - port->mtu)) { > tc_ov_wm -=3D tc_ov_wm >> 7; > if (tc_ov_wm < subport->tc_ov_wm_min) > tc_ov_wm =3D subport->tc_ov_wm_min; > @@ -1605,6 +1638,7 @@ grinder_credits_update(struct rte_sched_port > *port, uint32_t pos) > struct rte_sched_pipe *pipe =3D grinder->pipe; > struct rte_sched_pipe_profile *params =3D grinder->pipe_params; > uint64_t n_periods; > + uint32_t i; >=20 > /* Subport TB */ > n_periods =3D (port->time - subport->tb_time) / subport->tb_period; > @@ -1622,10 +1656,8 @@ grinder_credits_update(struct rte_sched_port > *port, uint32_t pos) > if (unlikely(port->time >=3D subport->tc_time)) { > subport->tc_ov_wm =3D grinder_tc_ov_credits_update(port, > pos); >=20 > - subport->tc_credits[0] =3D subport->tc_credits_per_period[0]; > - subport->tc_credits[1] =3D subport->tc_credits_per_period[1]; > - subport->tc_credits[2] =3D subport->tc_credits_per_period[2]; > - subport->tc_credits[3] =3D subport->tc_credits_per_period[3]; > + for (i =3D 0; i <=3D RTE_SCHED_TRAFFIC_CLASS_BE; i++) > + subport->tc_credits[i] =3D subport- > >tc_credits_per_period[i]; >=20 > subport->tc_time =3D port->time + subport->tc_period; > subport->tc_ov_period_id++; > @@ -1633,10 +1665,8 @@ grinder_credits_update(struct rte_sched_port > *port, uint32_t pos) >=20 > /* Pipe TCs */ > if (unlikely(port->time >=3D pipe->tc_time)) { > - pipe->tc_credits[0] =3D params->tc_credits_per_period[0]; > - pipe->tc_credits[1] =3D params->tc_credits_per_period[1]; > - pipe->tc_credits[2] =3D params->tc_credits_per_period[2]; > - pipe->tc_credits[3] =3D params->tc_credits_per_period[3]; > + for (i =3D 0; i <=3D RTE_SCHED_TRAFFIC_CLASS_BE; i++) > + pipe->tc_credits[i] =3D params- > >tc_credits_per_period[i]; > pipe->tc_time =3D port->time + params->tc_period; > } >=20 > @@ -1701,11 +1731,18 @@ grinder_credits_check(struct rte_sched_port > *port, uint32_t pos) > uint32_t subport_tc_credits =3D subport->tc_credits[tc_index]; > uint32_t pipe_tb_credits =3D pipe->tb_credits; > uint32_t pipe_tc_credits =3D pipe->tc_credits[tc_index]; > - uint32_t pipe_tc_ov_mask1[] =3D {UINT32_MAX, UINT32_MAX, > UINT32_MAX, pipe->tc_ov_credits}; > - uint32_t pipe_tc_ov_mask2[] =3D {0, 0, 0, UINT32_MAX}; > - uint32_t pipe_tc_ov_credits =3D pipe_tc_ov_mask1[tc_index]; > + uint32_t > pipe_tc_ov_mask1[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; > + uint32_t > pipe_tc_ov_mask2[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE] =3D {0}; > + uint32_t pipe_tc_ov_credits, i; > int enough_credits; >=20 > + for (i =3D 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) > + pipe_tc_ov_mask1[i] =3D UINT32_MAX; > + > + pipe_tc_ov_mask1[RTE_SCHED_TRAFFIC_CLASS_BE] =3D pipe- > >tc_ov_credits; > + pipe_tc_ov_mask2[RTE_SCHED_TRAFFIC_CLASS_BE] =3D > UINT32_MAX; > + pipe_tc_ov_credits =3D pipe_tc_ov_mask1[tc_index]; > + > /* Check pipe and subport credits */ > enough_credits =3D (pkt_len <=3D subport_tb_credits) && > (pkt_len <=3D subport_tc_credits) && > @@ -1860,68 +1897,65 @@ static inline void > grinder_tccache_populate(struct rte_sched_port *port, uint32_t pos, > uint32_t qindex, uint16_t qmask) > { > struct rte_sched_grinder *grinder =3D port->grinder + pos; > - uint8_t b[4]; > + uint8_t b, i; >=20 > grinder->tccache_w =3D 0; > grinder->tccache_r =3D 0; >=20 > - b[0] =3D (uint8_t) (qmask & 0xF); > - b[1] =3D (uint8_t) ((qmask >> 4) & 0xF); > - b[2] =3D (uint8_t) ((qmask >> 8) & 0xF); > - b[3] =3D (uint8_t) ((qmask >> 12) & 0xF); > - > - grinder->tccache_qmask[grinder->tccache_w] =3D b[0]; > - grinder->tccache_qindex[grinder->tccache_w] =3D qindex; > - grinder->tccache_w +=3D (b[0] !=3D 0); > - > - grinder->tccache_qmask[grinder->tccache_w] =3D b[1]; > - grinder->tccache_qindex[grinder->tccache_w] =3D qindex + 4; > - grinder->tccache_w +=3D (b[1] !=3D 0); > - > - grinder->tccache_qmask[grinder->tccache_w] =3D b[2]; > - grinder->tccache_qindex[grinder->tccache_w] =3D qindex + 8; > - grinder->tccache_w +=3D (b[2] !=3D 0); > + for (i =3D 0; i < RTE_SCHED_TRAFFIC_CLASS_BE; i++) { > + b =3D (uint8_t) ((qmask >> i) & 0x1); > + grinder->tccache_qmask[grinder->tccache_w] =3D b; > + grinder->tccache_qindex[grinder->tccache_w] =3D qindex + i; > + grinder->tccache_w +=3D (b !=3D 0); > + } >=20 > - grinder->tccache_qmask[grinder->tccache_w] =3D b[3]; > - grinder->tccache_qindex[grinder->tccache_w] =3D qindex + 12; > - grinder->tccache_w +=3D (b[3] !=3D 0); > + b =3D (uint8_t) (qmask >> (RTE_SCHED_TRAFFIC_CLASS_BE)); > + grinder->tccache_qmask[grinder->tccache_w] =3D b; > + grinder->tccache_qindex[grinder->tccache_w] =3D qindex + > + RTE_SCHED_TRAFFIC_CLASS_BE; > + grinder->tccache_w +=3D (b !=3D 0); > } >=20 > static inline int > grinder_next_tc(struct rte_sched_port *port, uint32_t pos) > { > struct rte_sched_grinder *grinder =3D port->grinder + pos; > + struct rte_sched_pipe *pipe =3D grinder->pipe; > struct rte_mbuf **qbase; > - uint32_t qindex; > + uint32_t qindex, qpos =3D 0; > uint16_t qsize; >=20 > if (grinder->tccache_r =3D=3D grinder->tccache_w) > return 0; >=20 > qindex =3D grinder->tccache_qindex[grinder->tccache_r]; > + grinder->tc_index =3D qindex & 0xf; > qbase =3D rte_sched_port_qbase(port, qindex); > - qsize =3D rte_sched_port_qsize(port, qindex); > - > - grinder->tc_index =3D (qindex >> 2) & 0x3; > - grinder->qmask =3D grinder->tccache_qmask[grinder->tccache_r]; > - grinder->qsize[grinder->tc_index] =3D qsize; >=20 > - grinder->qindex[0] =3D qindex; > - grinder->qindex[1] =3D qindex + 1; > - grinder->qindex[2] =3D qindex + 2; > - grinder->qindex[3] =3D qindex + 3; > + if (grinder->tc_index < RTE_SCHED_TRAFFIC_CLASS_BE) { > + qsize =3D rte_sched_port_qsize(port, qindex); >=20 > - grinder->queue[0] =3D port->queue + qindex; > - grinder->queue[1] =3D port->queue + qindex + 1; > - grinder->queue[2] =3D port->queue + qindex + 2; > - grinder->queue[3] =3D port->queue + qindex + 3; > + grinder->queue[qpos] =3D port->queue + qindex; > + grinder->qbase[qpos] =3D qbase; > + grinder->qindex[qpos] =3D qindex; > + grinder->qsize[qpos] =3D qsize; > + grinder->qmask =3D grinder->tccache_qmask[grinder- > >tccache_r]; > + grinder->tccache_r++; >=20 > - grinder->qbase[0] =3D qbase; > - grinder->qbase[1] =3D qbase + qsize; > - grinder->qbase[2] =3D qbase + 2 * qsize; > - grinder->qbase[3] =3D qbase + 3 * qsize; > + return 1; > + } >=20 > + for ( ; qpos < pipe->n_be_queues; qpos++) { > + qsize =3D rte_sched_port_qsize(port, qindex + qpos); > + grinder->queue[qpos] =3D port->queue + qindex + qpos; > + grinder->qbase[qpos] =3D qbase + qpos * qsize; > + grinder->qindex[qpos] =3D qindex + qpos; > + grinder->qsize[qpos] =3D qsize; > + } > + grinder->tc_index =3D RTE_SCHED_TRAFFIC_CLASS_BE; > + grinder->qmask =3D grinder->tccache_qmask[grinder->tccache_r]; > grinder->tccache_r++; > + > return 1; > } >=20 > diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h > index 2a935998a..ae4dfb311 100644 > --- a/lib/librte_sched/rte_sched.h > +++ b/lib/librte_sched/rte_sched.h > @@ -83,9 +83,9 @@ extern "C" { > #define RTE_SCHED_BE_QUEUES_PER_PIPE 4 >=20 > /** Number of traffic classes per pipe (as well as subport). > - * Cannot be changed. > */ > -#define RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE 4 > +#define RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE \ > +(RTE_SCHED_QUEUES_PER_PIPE - RTE_SCHED_BE_QUEUES_PER_PIPE + 1) >=20 > /** Number of queues per pipe traffic class. Cannot be changed. */ > #define RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS 4 > @@ -171,9 +171,7 @@ struct rte_sched_pipe_params { > /**< Traffic class rates (measured in bytes per second) */ > uint32_t tc_period; > /**< Enforcement period (measured in milliseconds) */ > -#ifdef RTE_SCHED_SUBPORT_TC_OV > uint8_t tc_ov_weight; /**< Weight Traffic class 3 > oversubscription */ > -#endif >=20 > /* Pipe queues */ > uint8_t wrr_weights[RTE_SCHED_BE_QUEUES_PER_PIPE]; /**< > WRR weights */ > @@ -206,11 +204,9 @@ struct rte_sched_port_params { > * (measured in bytes) */ > uint32_t n_subports_per_port; /**< Number of subports */ > uint32_t n_pipes_per_subport; /**< Number of pipes per subport > */ > - uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; > + uint16_t qsize[RTE_SCHED_QUEUES_PER_PIPE]; > /**< Packet queue size for each traffic class. > - * All queues within the same pipe traffic class have the same > - * size. Queues from different pipes serving the same traffic > - * class have the same size. */ > + * Queues which are not needed are allowed to have zero size. */ > struct rte_sched_pipe_params *pipe_profiles; > /**< Pipe profile table. > * Every pipe is configured using one of the profiles from this table. > */ > -- > 2.21.0