This patchset refactors the dpdk qos sched library to allow subport level configuration flexibility of the pipe nodes. Currently, all parameters for the pipe nodes (subscribers) configuration are part of the port level structure which forces all groups of subscribers (pipes) in different subports to have similar configurations in terms of their number, queue sizes, traffic-classes, etc. The new implementation moves pipe nodes configuration parameters from port level to subport level structure. This allows different subports of the same port to have different configuration for the pipe nodes, for examples- number of pipes, queue sizes, pipe profiles, etc. In order to keep the implementation complexity under control, all pipes within the same subport share the same configuration for queue sizes. Jasvinder Singh (15): sched: add pipe config params to subport struct sched: modify internal structs for config flexibility sched: remove pipe params config from port level shced: add pipe config to subport level sched: modify pipe functions for config flexibility sched: modify pkt enqueue for config flexibility sched: update memory compute to support flexiblity sched: update grinder functions for config flexibility sched: update pkt dequeue for flexible config sched: update queue stats read for config flexibility test/sched: modify tests for subport config flexibility net/softnic: add subport config flexibility to TM function ip_pipeline: add subport config flexibility to TM function examples/qos_sched: add subport configuration flexibility sched: remove redundant code app/test/test_sched.c | 35 +- doc/guides/rel_notes/release_19_11.rst | 6 +- drivers/net/softnic/rte_eth_softnic_tm.c | 51 +- examples/ip_pipeline/cli.c | 71 +- examples/ip_pipeline/tmgr.c | 23 +- examples/ip_pipeline/tmgr.h | 7 +- examples/qos_sched/app_thread.c | 4 +- examples/qos_sched/cfg_file.c | 226 ++-- examples/qos_sched/init.c | 54 +- examples/qos_sched/main.h | 1 + examples/qos_sched/profile.cfg | 5 +- examples/qos_sched/profile_ov.cfg | 5 +- examples/qos_sched/stats.c | 36 +- lib/librte_sched/Makefile | 2 +- lib/librte_sched/meson.build | 2 +- lib/librte_sched/rte_sched.c | 1400 +++++++++++++--------- lib/librte_sched/rte_sched.h | 114 +- 17 files changed, 1180 insertions(+), 862 deletions(-) -- 2.21.0
Add pipe configuration parameters to subport level structure to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/Makefile | 2 +- lib/librte_sched/meson.build | 2 +- lib/librte_sched/rte_sched.h | 81 +++++++++++++++++++++++------------- 3 files changed, 55 insertions(+), 30 deletions(-) diff --git a/lib/librte_sched/Makefile b/lib/librte_sched/Makefile index 3d7f410e1..6e4a72d89 100644 --- a/lib/librte_sched/Makefile +++ b/lib/librte_sched/Makefile @@ -18,7 +18,7 @@ LDLIBS += -lrte_timer EXPORT_MAP := rte_sched_version.map -LIBABIVER := 3 +LIBABIVER := 4 # # all source are stored in SRCS-y diff --git a/lib/librte_sched/meson.build b/lib/librte_sched/meson.build index 59d43c6d8..9f40a2368 100644 --- a/lib/librte_sched/meson.build +++ b/lib/librte_sched/meson.build @@ -1,7 +1,7 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2017 Intel Corporation -version = 3 +version = 4 sources = files('rte_sched.c', 'rte_red.c', 'rte_approx.c') headers = files('rte_sched.h', 'rte_sched_common.h', 'rte_red.h', 'rte_approx.h') diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index eac6db274..48be702bc 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -111,7 +111,7 @@ extern "C" { #endif /* - * Subport configuration parameters. The period and credits_per_period + * Pipe configuration parameters. The period and credits_per_period * parameters are measured in bytes, with one byte meaning the time * duration associated with the transmission of one byte on the * physical medium of the output port, with pipe or pipe traffic class @@ -119,7 +119,7 @@ extern "C" { * credits_per_period divided by period. One credit represents one * byte. */ -struct rte_sched_subport_params { +struct rte_sched_pipe_params { /** Token bucket rate (measured in bytes per second) */ uint32_t tb_rate; @@ -129,32 +129,18 @@ struct rte_sched_subport_params { /** Traffic class rates (measured in bytes per second) */ uint32_t tc_rate[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - /** Enforcement period for rates (measured in milliseconds) */ + /** Enforcement period (measured in milliseconds) */ uint32_t tc_period; -}; - -/** Subport statistics */ -struct rte_sched_subport_stats { - /** Number of packets successfully written */ - uint32_t n_pkts_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - - /** Number of packets dropped */ - uint32_t n_pkts_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - /** Number of bytes successfully written for each traffic class */ - uint32_t n_bytes_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - - /** Number of bytes dropped for each traffic class */ - uint32_t n_bytes_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + /** Best-effort traffic class oversubscription weight */ + uint8_t tc_ov_weight; -#ifdef RTE_SCHED_RED - /** Number of packets dropped by red */ - uint32_t n_pkts_red_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; -#endif + /** WRR weights of best-effort traffic class queues */ + uint8_t wrr_weights[RTE_SCHED_BE_QUEUES_PER_PIPE]; }; /* - * Pipe configuration parameters. The period and credits_per_period + * Subport configuration parameters. The period and credits_per_period * parameters are measured in bytes, with one byte meaning the time * duration associated with the transmission of one byte on the * physical medium of the output port, with pipe or pipe traffic class @@ -162,7 +148,7 @@ struct rte_sched_subport_stats { * credits_per_period divided by period. One credit represents one * byte. */ -struct rte_sched_pipe_params { +struct rte_sched_subport_params { /** Token bucket rate (measured in bytes per second) */ uint32_t tb_rate; @@ -172,14 +158,50 @@ struct rte_sched_pipe_params { /** Traffic class rates (measured in bytes per second) */ uint32_t tc_rate[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - /** Enforcement period (measured in milliseconds) */ + /** Enforcement period for rates (measured in milliseconds) */ uint32_t tc_period; - /** Best-effort traffic class oversubscription weight */ - uint8_t tc_ov_weight; + /** Number of subport_pipes */ + uint32_t n_pipes_per_subport; - /** WRR weights of best-effort traffic class queues */ - uint8_t wrr_weights[RTE_SCHED_BE_QUEUES_PER_PIPE]; + /** Packet queue size for each traffic class. + * All the pipes within the same subport share the similar + * configuration for the queues. + */ + uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + + /** Pipe profile table. + * Every pipe is configured using one of the profiles from this table. + */ + struct rte_sched_pipe_params *pipe_profiles; + + /** Profiles in the pipe profile table */ + uint32_t n_pipe_profiles; + +#ifdef RTE_SCHED_RED + /** RED parameters */ + struct rte_red_params red_params[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; +#endif +}; + +/** Subport statistics */ +struct rte_sched_subport_stats { + /** Number of packets successfully written */ + uint32_t n_pkts_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + + /** Number of packets dropped */ + uint32_t n_pkts_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + + /** Number of bytes successfully written for each traffic class */ + uint32_t n_bytes_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + + /** Number of bytes dropped for each traffic class */ + uint32_t n_bytes_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + +#ifdef RTE_SCHED_RED + /** Number of packets dropped by red */ + uint32_t n_pkts_red_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; +#endif }; /** Queue statistics */ @@ -227,6 +249,9 @@ struct rte_sched_port_params { /** Number of subport_pipes */ uint32_t n_pipes_per_subport; + /** Maximum number of subport_pipes */ + uint32_t n_max_pipes_per_subport; + /** Packet queue size for each traffic class. * All the pipes within the same subport share the similar * configuration for the queues. -- 2.21.0
Update internal structures related to port and subport to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 106 ++++++++++++++++++++++++++--------- 1 file changed, 79 insertions(+), 27 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index d8ab21d64..6a9990e5e 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -47,33 +47,6 @@ */ #define RTE_SCHED_TIME_SHIFT 8 -struct rte_sched_subport { - /* Token bucket (TB) */ - uint64_t tb_time; /* time of last update */ - uint32_t tb_period; - uint32_t tb_credits_per_period; - uint32_t tb_size; - uint32_t tb_credits; - - /* Traffic classes (TCs) */ - uint64_t tc_time; /* time of next update */ - uint32_t tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - uint32_t tc_credits[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - uint32_t tc_period; - - /* TC oversubscription */ - uint32_t tc_ov_wm; - uint32_t tc_ov_wm_min; - uint32_t tc_ov_wm_max; - uint8_t tc_ov_period_id; - uint8_t tc_ov; - uint32_t tc_ov_n; - double tc_ov_rate; - - /* Statistics */ - struct rte_sched_subport_stats stats; -}; - struct rte_sched_pipe_profile { /* Token bucket (TB) */ uint32_t tb_period; @@ -166,10 +139,77 @@ struct rte_sched_grinder { uint8_t wrr_cost[RTE_SCHED_BE_QUEUES_PER_PIPE]; }; +struct rte_sched_subport { + /* Token bucket (TB) */ + uint64_t tb_time; /* time of last update */ + uint32_t tb_period; + uint32_t tb_credits_per_period; + uint32_t tb_size; + uint32_t tb_credits; + + /* Traffic classes (TCs) */ + uint64_t tc_time; /* time of next update */ + uint32_t tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + uint32_t tc_credits[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + uint32_t tc_period; + + /* TC oversubscription */ + uint32_t tc_ov_wm; + uint32_t tc_ov_wm_min; + uint32_t tc_ov_wm_max; + uint8_t tc_ov_period_id; + uint8_t tc_ov; + uint32_t tc_ov_n; + double tc_ov_rate; + + /* Statistics */ + struct rte_sched_subport_stats stats; + + /* Subport pipes */ + uint32_t n_pipes_per_subport; + uint32_t n_pipe_profiles; + + /* Pipe best-effort TC rate */ + uint32_t pipe_tc_be_rate_max; + + /* Pipe queues size */ + uint16_t qsize[RTE_SCHED_QUEUES_PER_PIPE]; + +#ifdef RTE_SCHED_RED + struct rte_red_config red_config[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; +#endif + + /* Scheduling loop detection */ + uint32_t pipe_loop; + uint32_t pipe_exhaustion; + + /* Bitmap */ + struct rte_bitmap *bmp; + uint32_t grinder_base_bmp_pos[RTE_SCHED_PORT_N_GRINDERS] __rte_aligned_16; + + /* Grinders */ + struct rte_sched_grinder grinder[RTE_SCHED_PORT_N_GRINDERS]; + uint32_t busy_grinders; + + /* Queue base calculation */ + uint32_t qsize_add[RTE_SCHED_QUEUES_PER_PIPE]; + uint32_t qsize_sum; + + struct rte_sched_pipe *pipe; + struct rte_sched_queue *queue; + struct rte_sched_queue_extra *queue_extra; + struct rte_sched_pipe_profile *pipe_profiles; + uint8_t *bmp_array; + struct rte_mbuf **queue_array; + uint8_t memory[0] __rte_cache_aligned; +} __rte_cache_aligned; + struct rte_sched_port { /* User parameters */ uint32_t n_subports_per_port; uint32_t n_pipes_per_subport; + uint32_t n_max_pipes_per_subport; + uint32_t n_max_pipes_per_subport_log2; uint32_t n_pipes_per_subport_log2; uint16_t pipe_queue[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; uint8_t pipe_tc[RTE_SCHED_QUEUES_PER_PIPE]; @@ -177,6 +217,7 @@ struct rte_sched_port { uint32_t rate; uint32_t mtu; uint32_t frame_overhead; + int socket; uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; uint32_t n_pipe_profiles; uint32_t n_max_pipe_profiles; @@ -210,6 +251,7 @@ struct rte_sched_port { uint32_t qsize_sum; /* Large data structures */ + struct rte_sched_subport *subports[0]; struct rte_sched_subport *subport; struct rte_sched_pipe *pipe; struct rte_sched_queue *queue; @@ -231,6 +273,16 @@ enum rte_sched_port_array { e_RTE_SCHED_PORT_ARRAY_TOTAL, }; +enum rte_sched_subport_array { + e_RTE_SCHED_SUBPORT_ARRAY_PIPE = 0, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_EXTRA, + e_RTE_SCHED_SUBPORT_ARRAY_PIPE_PROFILES, + e_RTE_SCHED_SUBPORT_ARRAY_BMP_ARRAY, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_ARRAY, + e_RTE_SCHED_SUBPORT_ARRAY_TOTAL, +}; + #ifdef RTE_SCHED_COLLECT_STATS static inline uint32_t -- 2.21.0
Remove pipes configuration from the port level to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 266 +++++++++++------------------------ 1 file changed, 81 insertions(+), 185 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 6a9990e5e..db8b0485a 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -293,6 +293,31 @@ rte_sched_port_queues_per_subport(struct rte_sched_port *port) #endif +static inline uint32_t +rte_sched_subport_pipe_queues(struct rte_sched_subport *subport) +{ + return RTE_SCHED_QUEUES_PER_PIPE * subport->n_pipes_per_subport; +} + +static inline struct rte_mbuf ** +rte_sched_subport_pipe_qbase(struct rte_sched_subport *subport, uint32_t qindex) +{ + uint32_t pindex = qindex >> 4; + uint32_t qpos = qindex & (RTE_SCHED_QUEUES_PER_PIPE - 1); + + return (subport->queue_array + pindex * + subport->qsize_sum + subport->qsize_add[qpos]); +} + +static inline uint16_t +rte_sched_subport_pipe_qsize(struct rte_sched_port *port, +struct rte_sched_subport *subport, uint32_t qindex) +{ + uint32_t tc = port->pipe_tc[qindex & (RTE_SCHED_QUEUES_PER_PIPE - 1)]; + + return subport->qsize[tc]; +} + static inline uint32_t rte_sched_port_queues_per_port(struct rte_sched_port *port) { @@ -416,8 +441,6 @@ pipe_profile_check(struct rte_sched_pipe_params *params, 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__); @@ -454,49 +477,21 @@ rte_sched_port_check_params(struct rte_sched_port_params *params) 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)) { + /* n_max_pipes_per_subport: non-zero, power of 2 */ + if (params->n_max_pipes_per_subport == 0 || + !rte_is_power_of_2(params->n_max_pipes_per_subport)) { RTE_LOG(ERR, SCHED, - "%s: Incorrect value for pipes number\n", __func__); + "%s: Incorrect value for maximum pipes number\n", __func__); return -EINVAL; } - /* qsize: if non-zero, power of 2, - * no bigger than 32K (due to 16-bit read/write pointers) - */ - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - uint16_t qsize = params->qsize[i]; - - if ((qsize != 0 && !rte_is_power_of_2(qsize)) || - ((i == RTE_SCHED_TRAFFIC_CLASS_BE) && (qsize == 0))) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tc rate\n", __func__); - return -EINVAL; - } - } - - /* pipe_profiles and n_pipe_profiles */ - if (params->pipe_profiles == NULL || - params->n_pipe_profiles == 0 || - params->n_pipe_profiles > params->n_max_pipe_profiles) { + /* n_max_pipe_profiles: non-zero */ + if (params->n_max_pipe_profiles == 0) { RTE_LOG(ERR, SCHED, - "%s: Incorrect value for number of pipe profiles\n", __func__); + "%s: Incorrect value for maximum pipe profiles\n", __func__); return -EINVAL; } - for (i = 0; i < params->n_pipe_profiles; i++) { - struct rte_sched_pipe_params *p = params->pipe_profiles + i; - int status; - - status = pipe_profile_check(p, params->rate, ¶ms->qsize[0]); - if (status != 0) { - RTE_LOG(ERR, SCHED, - "%s: Pipe profile check failed(%d)\n", __func__, status); - return -EINVAL; - } - } - return 0; } @@ -584,32 +579,6 @@ rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params) return size0 + size1; } -static void -rte_sched_port_config_qsize(struct rte_sched_port *port) -{ - uint32_t i; - - port->qsize_add[0] = 0; - - /* Strict prority traffic class */ - for (i = 1; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - port->qsize_add[i] = port->qsize_add[i-1] + port->qsize[i-1]; - - /* Best-effort traffic class */ - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 1] = - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE] + - port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 2] = - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 1] + - port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 3] = - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 2] + - port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; - - port->qsize_sum = port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 3] + - port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; -} - static void rte_sched_port_log_pipe_profile(struct rte_sched_port *port, uint32_t i) { @@ -719,56 +688,42 @@ rte_sched_pipe_profile_convert(struct rte_sched_port *port, dst->wrr_cost[3] = (uint8_t) wrr_cost[3]; } -static void -rte_sched_port_config_pipe_profile_table(struct rte_sched_port *port, - struct rte_sched_port_params *params) -{ - uint32_t i; - - for (i = 0; i < port->n_pipe_profiles; i++) { - struct rte_sched_pipe_params *src = params->pipe_profiles + i; - struct rte_sched_pipe_profile *dst = port->pipe_profiles + i; - - rte_sched_pipe_profile_convert(port, src, dst, params->rate); - rte_sched_port_log_pipe_profile(port, i); - } - - port->pipe_tc_be_rate_max = 0; - for (i = 0; i < port->n_pipe_profiles; i++) { - struct rte_sched_pipe_params *src = params->pipe_profiles + i; - uint32_t pipe_tc_be_rate = src->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; - - if (port->pipe_tc_be_rate_max < pipe_tc_be_rate) - port->pipe_tc_be_rate_max = pipe_tc_be_rate; - } -} - struct rte_sched_port * rte_sched_port_config(struct rte_sched_port_params *params) { struct rte_sched_port *port = NULL; - uint32_t mem_size, bmp_mem_size, n_queues_per_port, i, j, cycles_per_byte; + uint32_t size0, size1; + uint32_t cycles_per_byte; + uint32_t i, j; + int status; - /* Check user parameters. Determine the amount of memory to allocate */ - mem_size = rte_sched_port_get_memory_footprint(params); - if (mem_size == 0) + status = rte_sched_port_check_params(params); + if (status != 0) { + RTE_LOG(ERR, SCHED, + "%s: Port scheduler params check failed (%d)\n", + __func__, status); return NULL; + } + + size0 = sizeof(struct rte_sched_port); + size1 = params->n_subports_per_port * sizeof(struct rte_sched_subport *); /* Allocate memory to store the data structures */ - port = rte_zmalloc_socket("qos_params", mem_size, RTE_CACHE_LINE_SIZE, + port = rte_zmalloc_socket("qos_params", size0 + size1, RTE_CACHE_LINE_SIZE, params->socket); - if (port == NULL) - return NULL; + if (port == NULL) { + RTE_LOG(ERR, SCHED, "%s: Memory allocation fails\n", __func__); - /* compile time checks */ - RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS == 0); - RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS & (RTE_SCHED_PORT_N_GRINDERS - 1)); + return NULL; + } /* User parameters */ port->n_subports_per_port = params->n_subports_per_port; - port->n_pipes_per_subport = params->n_pipes_per_subport; - port->n_pipes_per_subport_log2 = - __builtin_ctz(params->n_pipes_per_subport); + port->n_max_pipes_per_subport = params->n_max_pipes_per_subport; + port->n_max_pipes_per_subport_log2 = + __builtin_ctz(params->n_max_pipes_per_subport); + port->n_max_pipe_profiles = params->n_max_pipe_profiles; + port->socket = params->socket; for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) port->pipe_queue[i] = i; @@ -789,32 +744,6 @@ rte_sched_port_config(struct rte_sched_port_params *params) port->rate = params->rate; port->mtu = params->mtu + params->frame_overhead; port->frame_overhead = params->frame_overhead; - memcpy(port->qsize, params->qsize, sizeof(params->qsize)); - port->n_pipe_profiles = params->n_pipe_profiles; - port->n_max_pipe_profiles = params->n_max_pipe_profiles; - -#ifdef RTE_SCHED_RED - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - uint32_t j; - - for (j = 0; j < RTE_COLORS; j++) { - /* if min/max are both zero, then RED is disabled */ - if ((params->red_params[i][j].min_th | - params->red_params[i][j].max_th) == 0) { - continue; - } - - if (rte_red_config_init(&port->red_config[i][j], - params->red_params[i][j].wq_log2, - params->red_params[i][j].min_th, - params->red_params[i][j].max_th, - params->red_params[i][j].maxp_inv) != 0) { - rte_free(port); - return NULL; - } - } - } -#endif /* Timing */ port->time_cpu_cycles = rte_get_tsc_cycles(); @@ -825,79 +754,32 @@ rte_sched_port_config(struct rte_sched_port_params *params) / params->rate; port->inv_cycles_per_byte = rte_reciprocal_value(cycles_per_byte); - /* Scheduling loop detection */ - port->pipe_loop = RTE_SCHED_PIPE_INVALID; - port->pipe_exhaustion = 0; - /* Grinders */ - port->busy_grinders = 0; port->pkts_out = NULL; port->n_pkts_out = 0; - /* Queue base calculation */ - rte_sched_port_config_qsize(port); - - /* Large data structures */ - port->subport = (struct rte_sched_subport *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_SUBPORT)); - port->pipe = (struct rte_sched_pipe *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_PIPE)); - port->queue = (struct rte_sched_queue *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_QUEUE)); - port->queue_extra = (struct rte_sched_queue_extra *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_QUEUE_EXTRA)); - port->pipe_profiles = (struct rte_sched_pipe_profile *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_PIPE_PROFILES)); - port->bmp_array = port->memory - + rte_sched_port_get_array_base(params, e_RTE_SCHED_PORT_ARRAY_BMP_ARRAY); - port->queue_array = (struct rte_mbuf **) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_QUEUE_ARRAY)); - - /* Pipe profile table */ - rte_sched_port_config_pipe_profile_table(port, params); - - /* Bitmap */ - n_queues_per_port = rte_sched_port_queues_per_port(port); - bmp_mem_size = rte_bitmap_get_memory_footprint(n_queues_per_port); - port->bmp = rte_bitmap_init(n_queues_per_port, port->bmp_array, - bmp_mem_size); - if (port->bmp == NULL) { - RTE_LOG(ERR, SCHED, "Bitmap init error\n"); - rte_free(port); - return NULL; - } - - for (i = 0; i < RTE_SCHED_PORT_N_GRINDERS; i++) - port->grinder_base_bmp_pos[i] = RTE_SCHED_PIPE_INVALID; - - return port; } -void -rte_sched_port_free(struct rte_sched_port *port) +static inline void +rte_sched_subport_free(struct rte_sched_port *port, + struct rte_sched_subport *subport) { + uint32_t n_subport_pipe_queues; uint32_t qindex; - uint32_t n_queues_per_port; - /* Check user parameters */ - if (port == NULL) + if (subport == NULL) return; - n_queues_per_port = rte_sched_port_queues_per_port(port); + n_subport_pipe_queues = rte_sched_subport_pipe_queues(subport); /* Free enqueued mbufs */ - for (qindex = 0; qindex < n_queues_per_port; qindex++) { - struct rte_mbuf **mbufs = rte_sched_port_qbase(port, qindex); - uint16_t qsize = rte_sched_port_qsize(port, qindex); + for (qindex = 0; qindex < n_subport_pipe_queues; qindex++) { + struct rte_mbuf **mbufs = + rte_sched_subport_pipe_qbase(subport, qindex); + uint16_t qsize = rte_sched_subport_pipe_qsize(port, subport, qindex); if (qsize != 0) { - struct rte_sched_queue *queue = port->queue + qindex; + struct rte_sched_queue *queue = subport->queue + qindex; uint16_t qr = queue->qr & (qsize - 1); uint16_t qw = queue->qw & (qsize - 1); @@ -906,7 +788,21 @@ rte_sched_port_free(struct rte_sched_port *port) } } - rte_bitmap_free(port->bmp); + rte_bitmap_free(subport->bmp); +} + +void +rte_sched_port_free(struct rte_sched_port *port) +{ + uint32_t i; + + /* Check user parameters */ + if (port == NULL) + return; + + for (i = 0; i < port->n_subports_per_port; i++) + rte_sched_subport_free(port, port->subports[i]); + rte_free(port); } -- 2.21.0
Add pipes configuration from the port level to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 390 ++++++++++++++++++++++++++++++----- 1 file changed, 334 insertions(+), 56 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index db8b0485a..1491cb695 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -559,24 +559,92 @@ rte_sched_port_get_array_base(struct rte_sched_port_params *params, enum rte_sch return base; } -uint32_t -rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params) +static uint32_t +rte_sched_subport_get_array_base(struct rte_sched_subport_params *params, + uint32_t n_max_pipe_profiles, + enum rte_sched_subport_array array) { - uint32_t size0, size1; - int status; + uint32_t n_pipes_per_subport = params->n_pipes_per_subport; + uint32_t n_subport_pipe_queues = + RTE_SCHED_QUEUES_PER_PIPE * n_pipes_per_subport; - status = rte_sched_port_check_params(params); - if (status != 0) { - RTE_LOG(NOTICE, SCHED, - "Port scheduler params check failed (%d)\n", status); + uint32_t size_pipe = n_pipes_per_subport * sizeof(struct rte_sched_pipe); + uint32_t size_queue = + n_subport_pipe_queues * sizeof(struct rte_sched_queue); + uint32_t size_queue_extra + = n_subport_pipe_queues * sizeof(struct rte_sched_queue_extra); + uint32_t size_pipe_profiles = n_max_pipe_profiles * + sizeof(struct rte_sched_pipe_profile); + uint32_t size_bmp_array = + rte_bitmap_get_memory_footprint(n_subport_pipe_queues); + uint32_t size_per_pipe_queue_array, size_queue_array; - return 0; + uint32_t base, i; + + size_per_pipe_queue_array = 0; + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + if (i < RTE_SCHED_TRAFFIC_CLASS_BE) + size_per_pipe_queue_array += + params->qsize[i] * sizeof(struct rte_mbuf *); + else + size_per_pipe_queue_array += RTE_SCHED_MAX_QUEUES_PER_TC * + params->qsize[i] * sizeof(struct rte_mbuf *); } + size_queue_array = n_pipes_per_subport * size_per_pipe_queue_array; - size0 = sizeof(struct rte_sched_port); - size1 = rte_sched_port_get_array_base(params, e_RTE_SCHED_PORT_ARRAY_TOTAL); + base = 0; - return size0 + size1; + if (array == e_RTE_SCHED_SUBPORT_ARRAY_PIPE) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_pipe); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_QUEUE) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_queue); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_EXTRA) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_queue_extra); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_PIPE_PROFILES) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_pipe_profiles); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_BMP_ARRAY) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_bmp_array); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_ARRAY) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_queue_array); + + return base; +} + +static void +rte_sched_subport_config_qsize(struct rte_sched_subport *subport) +{ + uint32_t i; + + subport->qsize_add[0] = 0; + + /* Strict prority traffic class */ + for (i = 1; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) + subport->qsize_add[i] = subport->qsize_add[i-1] + subport->qsize[i-1]; + + /* Best-effort traffic class */ + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 1] = + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE] + + subport->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 2] = + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 1] + + subport->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 3] = + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 2] + + subport->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; + + subport->qsize_sum = subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 3] + + subport->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; } static void @@ -688,6 +756,126 @@ rte_sched_pipe_profile_convert(struct rte_sched_port *port, dst->wrr_cost[3] = (uint8_t) wrr_cost[3]; } +static int +rte_sched_subport_check_params(struct rte_sched_subport_params *params, + uint32_t n_max_pipes_per_subport, + uint32_t n_max_pipe_profiles, + uint32_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; + } + + /* qsize: if non-zero, power of 2, + * no bigger than 32K (due to 16-bit read/write pointers) + */ + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + uint16_t qsize = params->qsize[i]; + + if (qsize != 0 && !rte_is_power_of_2(qsize)) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for qsize\n", __func__); + return -EINVAL; + } + } + + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + uint32_t tc_rate = params->tc_rate[i]; + uint16_t qsize = params->qsize[i]; + + if ((qsize == 0 && tc_rate != 0) || + (qsize != 0 && tc_rate == 0) || + (tc_rate > params->tb_rate)) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for tc rate\n", __func__); + return -EINVAL; + } + } + + if (params->qsize[RTE_SCHED_TRAFFIC_CLASS_BE] == 0 || + params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE] == 0) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect qsize or 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; + } + + /* n_pipes_per_subport: non-zero, power of 2 */ + if (params->n_pipes_per_subport == 0 || + params->n_pipes_per_subport > n_max_pipes_per_subport || + !rte_is_power_of_2(params->n_pipes_per_subport)) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for pipes number\n", __func__); + return -EINVAL; + } + + /* pipe_profiles and n_pipe_profiles */ + if (params->pipe_profiles == NULL || + params->n_pipe_profiles == 0 || + params->n_pipe_profiles > n_max_pipe_profiles) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for pipe profiles\n", __func__); + return -EINVAL; + } + + for (i = 0; i < params->n_pipe_profiles; i++) { + struct rte_sched_pipe_params *p = params->pipe_profiles + i; + int status; + + status = pipe_profile_check(p, rate, ¶ms->qsize[0]); + if (status != 0) { + RTE_LOG(ERR, SCHED, + "%s: Pipe profile check failed(%d)\n", __func__, status); + return -EINVAL; + } + } + + return 0; +} + +uint32_t +rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params) +{ + uint32_t size0, size1; + int status; + + status = rte_sched_port_check_params(params); + if (status != 0) { + RTE_LOG(NOTICE, SCHED, + "Port scheduler params check failed (%d)\n", status); + + return 0; + } + + size0 = sizeof(struct rte_sched_port); + size1 = rte_sched_port_get_array_base(params, + e_RTE_SCHED_PORT_ARRAY_TOTAL); + + return size0 + size1; +} + struct rte_sched_port * rte_sched_port_config(struct rte_sched_port_params *params) { @@ -809,7 +997,7 @@ rte_sched_port_free(struct rte_sched_port *port) static void rte_sched_port_log_subport_config(struct rte_sched_port *port, uint32_t i) { - struct rte_sched_subport *s = port->subport + i; + struct rte_sched_subport *s = port->subports[i]; RTE_LOG(DEBUG, SCHED, "Low level config for subport %u:\n" " Token bucket: period = %u, credits per period = %u, size = %u\n" @@ -844,72 +1032,80 @@ rte_sched_port_log_subport_config(struct rte_sched_port *port, uint32_t i) s->tc_ov_wm_max); } +static void +rte_sched_free_memory(struct rte_sched_port *port, uint32_t n_subports) +{ + uint32_t i; + + for (i = 0; i < n_subports; i++) { + struct rte_sched_subport *subport = port->subports[i]; + + rte_sched_subport_free(port, subport); + } + + rte_free(port); +} + int rte_sched_subport_config(struct rte_sched_port *port, uint32_t subport_id, struct rte_sched_subport_params *params) { - struct rte_sched_subport *s; - uint32_t i; + struct rte_sched_subport *s = NULL; + uint32_t n_subports = subport_id; + uint32_t n_subport_pipe_queues, i; + uint32_t size0, size1, bmp_mem_size; + int status; /* Check user parameters */ if (port == NULL) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for parameter port\n", __func__); - return -EINVAL; + return 0; } if (subport_id >= port->n_subports_per_port) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for subport id\n", __func__); - return -EINVAL; - } - if (params == NULL) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for parameter params\n", __func__); + rte_sched_free_memory(port, n_subports); return -EINVAL; } - if (params->tb_rate == 0 || params->tb_rate > port->rate) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tb rate\n", __func__); - return -EINVAL; - } + status = rte_sched_subport_check_params(params, + port->n_max_pipes_per_subport, + port->n_max_pipe_profiles, + port->rate); + if (status != 0) { + RTE_LOG(NOTICE, SCHED, + "%s: Port scheduler params check failed (%d)\n", + __func__, status); - if (params->tb_size == 0) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tb size\n", __func__); + rte_sched_free_memory(port, n_subports); return -EINVAL; } - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - uint32_t tc_rate = params->tc_rate[i]; - uint16_t qsize = port->qsize[i]; + /* Determine the amount of memory to allocate */ + size0 = sizeof(struct rte_sched_subport); + size1 = rte_sched_subport_get_array_base(params, + port->n_max_pipe_profiles, + e_RTE_SCHED_SUBPORT_ARRAY_TOTAL); - if ((qsize == 0 && tc_rate != 0) || - (qsize != 0 && tc_rate == 0) || - (tc_rate > params->tb_rate)) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tc rate\n", __func__); - return -EINVAL; - } - } - - if (port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE] == 0 || - params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE] == 0) { + /* Allocate memory to store the data structures */ + s = rte_zmalloc_socket("subport_params", size0 + size1, + RTE_CACHE_LINE_SIZE, port->socket); + if (s == NULL) { RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tc rate(best effort)\n", __func__); - return -EINVAL; - } + "%s: Memory allocation fails\n", __func__); - if (params->tc_period == 0) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tc period\n", __func__); - return -EINVAL; + rte_sched_free_memory(port, n_subports); + return -ENOMEM; } - s = port->subport + subport_id; + n_subports++; + + /* Port */ + port->subports[subport_id] = s; /* Token Bucket (TB) */ if (params->tb_rate == port->rate) { @@ -929,26 +1125,108 @@ rte_sched_subport_config(struct rte_sched_port *port, /* Traffic Classes (TCs) */ s->tc_period = rte_sched_time_ms_to_bytes(params->tc_period, port->rate); for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - if (port->qsize[i]) + if (params->qsize[i]) s->tc_credits_per_period[i] = rte_sched_time_ms_to_bytes(params->tc_period, - params->tc_rate[i]); - + params->tc_rate[i]); } s->tc_time = port->time + s->tc_period; for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - if (port->qsize[i]) + if (params->qsize[i]) s->tc_credits[i] = s->tc_credits_per_period[i]; + /* compile time checks */ + RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS == 0); + RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS & + (RTE_SCHED_PORT_N_GRINDERS - 1)); + + /* User parameters */ + s->n_pipes_per_subport = params->n_pipes_per_subport; + memcpy(s->qsize, params->qsize, sizeof(params->qsize)); + s->n_pipe_profiles = params->n_pipe_profiles; + +#ifdef RTE_SCHED_RED + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + uint32_t j; + + for (j = 0; j < RTE_COLORS; j++) { + /* if min/max are both zero, then RED is disabled */ + if ((params->red_params[i][j].min_th | + params->red_params[i][j].max_th) == 0) { + continue; + } + + if (rte_red_config_init(&s->red_config[i][j], + params->red_params[i][j].wq_log2, + params->red_params[i][j].min_th, + params->red_params[i][j].max_th, + params->red_params[i][j].maxp_inv) != 0) { + rte_sched_free_memory(port, n_subports); + + RTE_LOG(NOTICE, SCHED, + "%s: RED configuration init fails\n", __func__); + return -EINVAL; + } + } + } +#endif + + /* Scheduling loop detection */ + s->pipe_loop = RTE_SCHED_PIPE_INVALID; + s->pipe_exhaustion = 0; + + /* Grinders */ + s->busy_grinders = 0; + + /* Queue base calculation */ + rte_sched_subport_config_qsize(s); + + /* Large data structures */ + s->pipe = (struct rte_sched_pipe *) + (s->memory + rte_sched_subport_get_array_base(params, + port->n_max_pipe_profiles, e_RTE_SCHED_SUBPORT_ARRAY_PIPE)); + s->queue = (struct rte_sched_queue *) + (s->memory + rte_sched_subport_get_array_base(params, + port->n_max_pipe_profiles, e_RTE_SCHED_SUBPORT_ARRAY_QUEUE)); + s->queue_extra = (struct rte_sched_queue_extra *) + (s->memory + rte_sched_subport_get_array_base(params, + port->n_max_pipe_profiles, e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_EXTRA)); + s->pipe_profiles = (struct rte_sched_pipe_profile *) + (s->memory + rte_sched_subport_get_array_base(params, + port->n_max_pipe_profiles, e_RTE_SCHED_SUBPORT_ARRAY_PIPE_PROFILES)); + s->bmp_array = s->memory + rte_sched_subport_get_array_base(params, + port->n_max_pipe_profiles, e_RTE_SCHED_SUBPORT_ARRAY_BMP_ARRAY); + s->queue_array = (struct rte_mbuf **) + (s->memory + rte_sched_subport_get_array_base(params, + port->n_max_pipe_profiles, e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_ARRAY)); + + /* Bitmap */ + n_subport_pipe_queues = rte_sched_subport_pipe_queues(s); + bmp_mem_size = rte_bitmap_get_memory_footprint(n_subport_pipe_queues); + s->bmp = rte_bitmap_init(n_subport_pipe_queues, s->bmp_array, + bmp_mem_size); + if (s->bmp == NULL) { + RTE_LOG(ERR, SCHED, + "%s: Subport bitmap init error\n", __func__); + + rte_sched_free_memory(port, n_subports); + return -EINVAL; + } + + for (i = 0; i < RTE_SCHED_PORT_N_GRINDERS; i++) + s->grinder_base_bmp_pos[i] = RTE_SCHED_PIPE_INVALID; + +#ifdef RTE_SCHED_SUBPORT_TC_OV /* TC oversubscription */ s->tc_ov_wm_min = port->mtu; s->tc_ov_wm_max = rte_sched_time_ms_to_bytes(params->tc_period, - port->pipe_tc_be_rate_max); + s->pipe_tc_be_rate_max); s->tc_ov_wm = s->tc_ov_wm_max; s->tc_ov_period_id = 0; s->tc_ov = 0; s->tc_ov_n = 0; s->tc_ov_rate = 0; +#endif rte_sched_port_log_subport_config(port, subport_id); -- 2.21.0
Modify pipe level functions to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 95 +++++++++++++++++++++++++----------- lib/librte_sched/rte_sched.h | 5 +- 2 files changed, 70 insertions(+), 30 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 1491cb695..6bafbd8fe 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -648,9 +648,9 @@ rte_sched_subport_config_qsize(struct rte_sched_subport *subport) } static void -rte_sched_port_log_pipe_profile(struct rte_sched_port *port, uint32_t i) +rte_sched_port_log_pipe_profile(struct rte_sched_subport *subport, uint32_t i) { - struct rte_sched_pipe_profile *p = port->pipe_profiles + i; + struct rte_sched_pipe_profile *p = subport->pipe_profiles + i; RTE_LOG(DEBUG, SCHED, "Low level config for pipe profile %u:\n" " Token bucket: period = %u, credits per period = %u, size = %u\n" @@ -699,7 +699,7 @@ rte_sched_time_ms_to_bytes(uint32_t time_ms, uint32_t rate) } static void -rte_sched_pipe_profile_convert(struct rte_sched_port *port, +rte_sched_pipe_profile_convert(struct rte_sched_subport *subport, struct rte_sched_pipe_params *src, struct rte_sched_pipe_profile *dst, uint32_t rate) @@ -728,7 +728,7 @@ rte_sched_pipe_profile_convert(struct rte_sched_port *port, rate); for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - if (port->qsize[i]) + if (subport->qsize[i]) dst->tc_credits_per_period[i] = rte_sched_time_ms_to_bytes(src->tc_period, src->tc_rate[i]); @@ -756,6 +756,30 @@ rte_sched_pipe_profile_convert(struct rte_sched_port *port, dst->wrr_cost[3] = (uint8_t) wrr_cost[3]; } +static void +rte_sched_subport_config_pipe_profile_table(struct rte_sched_subport *subport, + struct rte_sched_subport_params *params, uint32_t rate) +{ + uint32_t i; + + for (i = 0; i < subport->n_pipe_profiles; i++) { + struct rte_sched_pipe_params *src = params->pipe_profiles + i; + struct rte_sched_pipe_profile *dst = subport->pipe_profiles + i; + + rte_sched_pipe_profile_convert(subport, src, dst, rate); + rte_sched_port_log_pipe_profile(subport, i); + } + + subport->pipe_tc_be_rate_max = 0; + for (i = 0; i < subport->n_pipe_profiles; i++) { + struct rte_sched_pipe_params *src = params->pipe_profiles + i; + uint32_t pipe_tc_be_rate = src->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; + + if (subport->pipe_tc_be_rate_max < pipe_tc_be_rate) + subport->pipe_tc_be_rate_max = pipe_tc_be_rate; + } +} + static int rte_sched_subport_check_params(struct rte_sched_subport_params *params, uint32_t n_max_pipes_per_subport, @@ -1200,6 +1224,9 @@ rte_sched_subport_config(struct rte_sched_port *port, (s->memory + rte_sched_subport_get_array_base(params, port->n_max_pipe_profiles, e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_ARRAY)); + /* Pipe profile table */ + rte_sched_subport_config_pipe_profile_table(s, params, port->rate); + /* Bitmap */ n_subport_pipe_queues = rte_sched_subport_pipe_queues(s); bmp_mem_size = rte_bitmap_get_memory_footprint(n_subport_pipe_queues); @@ -1242,6 +1269,7 @@ rte_sched_pipe_config(struct rte_sched_port *port, struct rte_sched_subport *s; struct rte_sched_pipe *p; struct rte_sched_pipe_profile *params; + uint32_t n_subports = subport_id + 1; uint32_t deactivate, profile, i; /* Check user parameters */ @@ -1257,34 +1285,32 @@ rte_sched_pipe_config(struct rte_sched_port *port, if (subport_id >= port->n_subports_per_port) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for parameter subport id\n", __func__); + + rte_sched_free_memory(port, n_subports); return -EINVAL; } - if (pipe_id >= port->n_pipes_per_subport) { + s = port->subports[subport_id]; + if (pipe_id >= s->n_pipes_per_subport) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for parameter pipe id\n", __func__); + + rte_sched_free_memory(port, n_subports); return -EINVAL; } - if (!deactivate && profile >= port->n_pipe_profiles) { + if (!deactivate && profile >= s->n_pipe_profiles) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for parameter pipe profile\n", __func__); - return -EINVAL; - } - /* Check that subport configuration is valid */ - s = port->subport + subport_id; - if (s->tb_period == 0) { - RTE_LOG(ERR, SCHED, - "%s: Subport configuration invalid\n", __func__); + rte_sched_free_memory(port, n_subports); return -EINVAL; } - p = port->pipe + (subport_id * port->n_pipes_per_subport + pipe_id); - /* Handle the case when pipe already has a valid configuration */ + p = s->pipe + pipe_id; if (p->tb_time) { - params = port->pipe_profiles + p->profile; + params = s->pipe_profiles + p->profile; double subport_tc_be_rate = (double) s->tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASS_BE] @@ -1314,7 +1340,7 @@ rte_sched_pipe_config(struct rte_sched_port *port, /* Apply the new pipe configuration */ p->profile = profile; - params = port->pipe_profiles + p->profile; + params = s->pipe_profiles + p->profile; /* Token Bucket (TB) */ p->tb_time = port->time; @@ -1324,7 +1350,7 @@ rte_sched_pipe_config(struct rte_sched_port *port, p->tc_time = port->time + params->tc_period; for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - if (port->qsize[i]) + if (s->qsize[i]) p->tc_credits[i] = params->tc_credits_per_period[i]; { @@ -1355,9 +1381,11 @@ rte_sched_pipe_config(struct rte_sched_port *port, int rte_sched_port_pipe_profile_add(struct rte_sched_port *port, + uint32_t subport_id, struct rte_sched_pipe_params *params, uint32_t *pipe_profile_id) { + struct rte_sched_subport *s; struct rte_sched_pipe_profile *pp; uint32_t i; int status; @@ -1369,40 +1397,49 @@ rte_sched_port_pipe_profile_add(struct rte_sched_port *port, return -EINVAL; } + /* Subport id not exceeds the max limit */ + if (subport_id > port->n_subports_per_port) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for subport id\n", __func__); + return -EINVAL; + } + + s = port->subports[subport_id]; + /* Pipe profiles not exceeds the max limit */ - if (port->n_pipe_profiles >= port->n_max_pipe_profiles) { + if (s->n_pipe_profiles >= port->n_max_pipe_profiles) { RTE_LOG(ERR, SCHED, "%s: Number of pipe profiles exceeds the max limit\n", __func__); return -EINVAL; } /* Pipe params */ - status = pipe_profile_check(params, port->rate, &port->qsize[0]); + status = pipe_profile_check(params, port->rate, &s->qsize[0]); if (status != 0) { RTE_LOG(ERR, SCHED, "%s: Pipe profile check failed(%d)\n", __func__, status); return -EINVAL; } - pp = &port->pipe_profiles[port->n_pipe_profiles]; - rte_sched_pipe_profile_convert(port, params, pp, port->rate); + pp = &s->pipe_profiles[s->n_pipe_profiles]; + rte_sched_pipe_profile_convert(s, params, pp, port->rate); /* Pipe profile not exists */ - for (i = 0; i < port->n_pipe_profiles; i++) - if (memcmp(port->pipe_profiles + i, pp, sizeof(*pp)) == 0) { + for (i = 0; i < s->n_pipe_profiles; i++) + if (memcmp(s->pipe_profiles + i, pp, sizeof(*pp)) == 0) { RTE_LOG(ERR, SCHED, "%s: Pipe profile doesn't exist\n", __func__); return -EINVAL; } /* Pipe profile commit */ - *pipe_profile_id = port->n_pipe_profiles; - port->n_pipe_profiles++; + *pipe_profile_id = s->n_pipe_profiles; + s->n_pipe_profiles++; - if (port->pipe_tc_be_rate_max < params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]) - port->pipe_tc_be_rate_max = params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; + if (s->pipe_tc_be_rate_max < params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]) + s->pipe_tc_be_rate_max = params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; - rte_sched_port_log_pipe_profile(port, *pipe_profile_id); + rte_sched_port_log_pipe_profile(s, *pipe_profile_id); return 0; } diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index 48be702bc..56e9fbfa7 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -308,6 +308,8 @@ rte_sched_port_free(struct rte_sched_port *port); * * @param port * Handle to port scheduler instance + * @param subport_id + * Subport ID * @param params * Pipe profile parameters * @param pipe_profile_id @@ -318,6 +320,7 @@ rte_sched_port_free(struct rte_sched_port *port); __rte_experimental int rte_sched_port_pipe_profile_add(struct rte_sched_port *port, + uint32_t subport_id, struct rte_sched_pipe_params *params, uint32_t *pipe_profile_id); @@ -348,7 +351,7 @@ rte_sched_subport_config(struct rte_sched_port *port, * @param pipe_id * Pipe ID within subport * @param pipe_profile - * ID of port-level pre-configured pipe profile + * ID of subport-level pre-configured pipe profile * @return * 0 upon success, error code otherwise */ -- 2.21.0
Modify scheduler packet enqueue operation of the scheduler to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 278 ++++++++++++++++++++++------------- 1 file changed, 178 insertions(+), 100 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 6bafbd8fe..a5e4c45b4 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -1452,10 +1452,10 @@ rte_sched_port_qindex(struct rte_sched_port *port, 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) | - ((rte_sched_port_pipe_queue(port, traffic_class) + queue) & - (RTE_SCHED_QUEUES_PER_PIPE - 1)); + (port->n_max_pipes_per_subport_log2 + 4)) | + ((pipe & (port->subports[subport]->n_pipes_per_subport - 1)) << 4) | + ((rte_sched_port_pipe_queue(port, traffic_class) + queue) & + (RTE_SCHED_QUEUES_PER_PIPE - 1)); } void @@ -1479,8 +1479,9 @@ rte_sched_port_pkt_read_tree_path(struct rte_sched_port *port, { uint32_t queue_id = rte_mbuf_sched_queue_get(pkt); - *subport = queue_id >> (port->n_pipes_per_subport_log2 + 4); - *pipe = (queue_id >> 4) & (port->n_pipes_per_subport - 1); + *subport = queue_id >> (port->n_max_pipes_per_subport_log2 + 4); + *pipe = (queue_id >> 4) & + (port->subports[*subport]->n_pipes_per_subport - 1); *traffic_class = rte_sched_port_pipe_tc(port, queue_id); *queue = rte_sched_port_tc_queue(port, queue_id); } @@ -1524,7 +1525,7 @@ rte_sched_subport_read_stats(struct rte_sched_port *port, return -EINVAL; } - s = port->subport + subport_id; + s = port->subports[subport_id]; /* Copy subport stats and clear */ memcpy(stats, &s->stats, sizeof(struct rte_sched_subport_stats)); @@ -1597,43 +1598,50 @@ rte_sched_port_queue_is_empty(struct rte_sched_port *port, uint32_t qindex) #ifdef RTE_SCHED_COLLECT_STATS static inline void -rte_sched_port_update_subport_stats(struct rte_sched_port *port, uint32_t qindex, struct rte_mbuf *pkt) +rte_sched_port_update_subport_stats(struct rte_sched_port *port, + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt) { - struct rte_sched_subport *s = port->subport + (qindex / rte_sched_port_queues_per_subport(port)); uint32_t tc_index = rte_sched_port_pipe_tc(port, qindex); uint32_t pkt_len = pkt->pkt_len; - s->stats.n_pkts_tc[tc_index] += 1; - s->stats.n_bytes_tc[tc_index] += pkt_len; + subport->stats.n_pkts_tc[tc_index] += 1; + subport->stats.n_bytes_tc[tc_index] += pkt_len; } #ifdef RTE_SCHED_RED static inline void rte_sched_port_update_subport_stats_on_drop(struct rte_sched_port *port, - uint32_t qindex, - struct rte_mbuf *pkt, uint32_t red) + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt, + uint32_t red) #else static inline void rte_sched_port_update_subport_stats_on_drop(struct rte_sched_port *port, - uint32_t qindex, - struct rte_mbuf *pkt, __rte_unused uint32_t red) + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt, + __rte_unused uint32_t red) #endif { - struct rte_sched_subport *s = port->subport + (qindex / rte_sched_port_queues_per_subport(port)); uint32_t tc_index = rte_sched_port_pipe_tc(port, qindex); uint32_t pkt_len = pkt->pkt_len; - s->stats.n_pkts_tc_dropped[tc_index] += 1; - s->stats.n_bytes_tc_dropped[tc_index] += pkt_len; + subport->stats.n_pkts_tc_dropped[tc_index] += 1; + subport->stats.n_bytes_tc_dropped[tc_index] += pkt_len; #ifdef RTE_SCHED_RED - s->stats.n_pkts_red_dropped[tc_index] += red; + subport->stats.n_pkts_red_dropped[tc_index] += red; #endif } static inline void -rte_sched_port_update_queue_stats(struct rte_sched_port *port, uint32_t qindex, struct rte_mbuf *pkt) +rte_sched_port_update_queue_stats(struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt) { - struct rte_sched_queue_extra *qe = port->queue_extra + qindex; + struct rte_sched_queue_extra *qe = subport->queue_extra + qindex; uint32_t pkt_len = pkt->pkt_len; qe->stats.n_pkts += 1; @@ -1642,17 +1650,19 @@ rte_sched_port_update_queue_stats(struct rte_sched_port *port, uint32_t qindex, #ifdef RTE_SCHED_RED static inline void -rte_sched_port_update_queue_stats_on_drop(struct rte_sched_port *port, - uint32_t qindex, - struct rte_mbuf *pkt, uint32_t red) +rte_sched_port_update_queue_stats_on_drop(struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt, + uint32_t red) #else static inline void -rte_sched_port_update_queue_stats_on_drop(struct rte_sched_port *port, - uint32_t qindex, - struct rte_mbuf *pkt, __rte_unused uint32_t red) +rte_sched_port_update_queue_stats_on_drop(struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt, + __rte_unused uint32_t red) #endif { - struct rte_sched_queue_extra *qe = port->queue_extra + qindex; + struct rte_sched_queue_extra *qe = subport->queue_extra + qindex; uint32_t pkt_len = pkt->pkt_len; qe->stats.n_pkts_dropped += 1; @@ -1667,7 +1677,11 @@ rte_sched_port_update_queue_stats_on_drop(struct rte_sched_port *port, #ifdef RTE_SCHED_RED static inline int -rte_sched_port_red_drop(struct rte_sched_port *port, struct rte_mbuf *pkt, uint32_t qindex, uint16_t qlen) +rte_sched_port_red_drop(struct rte_sched_port *port, + struct rte_sched_subport *subport, + struct rte_mbuf *pkt, + uint32_t qindex, + uint16_t qlen) { struct rte_sched_queue_extra *qe; struct rte_red_config *red_cfg; @@ -1677,12 +1691,12 @@ rte_sched_port_red_drop(struct rte_sched_port *port, struct rte_mbuf *pkt, uint3 tc_index = rte_sched_port_pipe_tc(port, qindex); color = rte_sched_port_pkt_read_color(pkt); - red_cfg = &port->red_config[tc_index][color]; + red_cfg = &subport->red_config[tc_index][color]; if ((red_cfg->min_th | red_cfg->max_th) == 0) return 0; - qe = port->queue_extra + qindex; + qe = subport->queue_extra + qindex; red = &qe->red; return rte_red_enqueue(red_cfg, red, qlen, port->time); @@ -1699,7 +1713,14 @@ rte_sched_port_set_queue_empty_timestamp(struct rte_sched_port *port, uint32_t q #else -#define rte_sched_port_red_drop(port, pkt, qindex, qlen) 0 +static inline int rte_sched_port_red_drop(struct rte_sched_port *port __rte_unused, + struct rte_sched_subport *subport __rte_unused, + struct rte_mbuf *pkt __rte_unused, + uint32_t qindex __rte_unused, + uint16_t qlen __rte_unused) +{ + return 0; +} #define rte_sched_port_set_queue_empty_timestamp(port, qindex) @@ -1734,63 +1755,79 @@ debug_check_queue_slab(struct rte_sched_port *port, uint32_t bmp_pos, #endif /* RTE_SCHED_DEBUG */ +static inline struct rte_sched_subport * +rte_sched_port_subport(struct rte_sched_port *port, + struct rte_mbuf *pkt) +{ + uint32_t queue_id = rte_mbuf_sched_queue_get(pkt); + uint32_t subport_id = queue_id >> (port->n_max_pipes_per_subport_log2 + 4); + + return port->subports[subport_id]; +} + static inline uint32_t -rte_sched_port_enqueue_qptrs_prefetch0(struct rte_sched_port *port, - struct rte_mbuf *pkt) +rte_sched_port_enqueue_qptrs_prefetch0(struct rte_sched_subport *subport, + struct rte_mbuf *pkt, uint32_t subport_qmask) { struct rte_sched_queue *q; #ifdef RTE_SCHED_COLLECT_STATS struct rte_sched_queue_extra *qe; #endif uint32_t qindex = rte_mbuf_sched_queue_get(pkt); + uint32_t subport_queue_id = subport_qmask & qindex; - q = port->queue + qindex; + q = subport->queue + subport_queue_id; rte_prefetch0(q); #ifdef RTE_SCHED_COLLECT_STATS - qe = port->queue_extra + qindex; + qe = subport->queue_extra + subport_queue_id; rte_prefetch0(qe); #endif - return qindex; + return subport_queue_id; } static inline void rte_sched_port_enqueue_qwa_prefetch0(struct rte_sched_port *port, - uint32_t qindex, struct rte_mbuf **qbase) + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf **qbase) { struct rte_sched_queue *q; struct rte_mbuf **q_qw; uint16_t qsize; - q = port->queue + qindex; - qsize = rte_sched_port_qsize(port, qindex); + q = subport->queue + qindex; + qsize = rte_sched_subport_pipe_qsize(port, subport, qindex); q_qw = qbase + (q->qw & (qsize - 1)); rte_prefetch0(q_qw); - rte_bitmap_prefetch0(port->bmp, qindex); + rte_bitmap_prefetch0(subport->bmp, qindex); } static inline int -rte_sched_port_enqueue_qwa(struct rte_sched_port *port, uint32_t qindex, - struct rte_mbuf **qbase, struct rte_mbuf *pkt) +rte_sched_port_enqueue_qwa(struct rte_sched_port *port, + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf **qbase, + struct rte_mbuf *pkt) { struct rte_sched_queue *q; uint16_t qsize; uint16_t qlen; - q = port->queue + qindex; - qsize = rte_sched_port_qsize(port, qindex); + q = subport->queue + qindex; + qsize = rte_sched_subport_pipe_qsize(port, subport, qindex); qlen = q->qw - q->qr; /* Drop the packet (and update drop stats) when queue is full */ - if (unlikely(rte_sched_port_red_drop(port, pkt, qindex, qlen) || + if (unlikely(rte_sched_port_red_drop(port, subport, pkt, qindex, qlen) || (qlen >= qsize))) { rte_pktmbuf_free(pkt); #ifdef RTE_SCHED_COLLECT_STATS - rte_sched_port_update_subport_stats_on_drop(port, qindex, pkt, - qlen < qsize); - rte_sched_port_update_queue_stats_on_drop(port, qindex, pkt, - qlen < qsize); + rte_sched_port_update_subport_stats_on_drop(port, subport, + qindex, pkt, qlen < qsize); + rte_sched_port_update_queue_stats_on_drop(subport, qindex, pkt, + qlen < qsize); #endif return 0; } @@ -1799,13 +1836,13 @@ rte_sched_port_enqueue_qwa(struct rte_sched_port *port, uint32_t qindex, qbase[q->qw & (qsize - 1)] = pkt; q->qw++; - /* Activate queue in the port bitmap */ - rte_bitmap_set(port->bmp, qindex); + /* Activate queue in the subport bitmap */ + rte_bitmap_set(subport->bmp, qindex); /* Statistics */ #ifdef RTE_SCHED_COLLECT_STATS - rte_sched_port_update_subport_stats(port, qindex, pkt); - rte_sched_port_update_queue_stats(port, qindex, pkt); + rte_sched_port_update_subport_stats(port, subport, qindex, pkt); + rte_sched_port_update_queue_stats(subport, qindex, pkt); #endif return 1; @@ -1833,17 +1870,22 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, *pkt30, *pkt31, *pkt_last; struct rte_mbuf **q00_base, **q01_base, **q10_base, **q11_base, **q20_base, **q21_base, **q30_base, **q31_base, **q_last_base; + struct rte_sched_subport *subport00, *subport01, *subport10, *subport11, + *subport20, *subport21, *subport30, *subport31, *subport_last; uint32_t q00, q01, q10, q11, q20, q21, q30, q31, q_last; uint32_t r00, r01, r10, r11, r20, r21, r30, r31, r_last; + uint32_t subport_qmask; uint32_t result, i; result = 0; + subport_qmask = (1 << (port->n_max_pipes_per_subport_log2 + 4)) - 1; /* * Less then 6 input packets available, which is not enough to * feed the pipeline */ if (unlikely(n_pkts < 6)) { + struct rte_sched_subport *subports[5]; struct rte_mbuf **q_base[5]; uint32_t q[5]; @@ -1851,22 +1893,26 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, for (i = 0; i < n_pkts; i++) rte_prefetch0(pkts[i]); + /* Prefetch the subport structure for each packet */ + for (i = 0; i < n_pkts; i++) + subports[i] = rte_sched_port_subport(port, pkts[i]); + /* Prefetch the queue structure for each queue */ for (i = 0; i < n_pkts; i++) - q[i] = rte_sched_port_enqueue_qptrs_prefetch0(port, - pkts[i]); + q[i] = rte_sched_port_enqueue_qptrs_prefetch0(subports[i], + pkts[i], subport_qmask); /* Prefetch the write pointer location of each queue */ for (i = 0; i < n_pkts; i++) { - q_base[i] = rte_sched_port_qbase(port, q[i]); - rte_sched_port_enqueue_qwa_prefetch0(port, q[i], - q_base[i]); + q_base[i] = rte_sched_subport_pipe_qbase(subports[i], q[i]); + rte_sched_port_enqueue_qwa_prefetch0(port, subports[i], + q[i], q_base[i]); } /* Write each packet to its queue */ for (i = 0; i < n_pkts; i++) - result += rte_sched_port_enqueue_qwa(port, q[i], - q_base[i], pkts[i]); + result += rte_sched_port_enqueue_qwa(port, subports[i], + q[i], q_base[i], pkts[i]); return result; } @@ -1882,21 +1928,29 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, rte_prefetch0(pkt10); rte_prefetch0(pkt11); - q20 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt20); - q21 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt21); + subport20 = rte_sched_port_subport(port, pkt20); + subport21 = rte_sched_port_subport(port, pkt21); + q20 = rte_sched_port_enqueue_qptrs_prefetch0(subport20, + pkt20, subport_qmask); + q21 = rte_sched_port_enqueue_qptrs_prefetch0(subport21, + pkt21, subport_qmask); pkt00 = pkts[4]; pkt01 = pkts[5]; rte_prefetch0(pkt00); rte_prefetch0(pkt01); - q10 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt10); - q11 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt11); + subport10 = rte_sched_port_subport(port, pkt10); + subport11 = rte_sched_port_subport(port, pkt11); + q10 = rte_sched_port_enqueue_qptrs_prefetch0(subport10, + pkt10, subport_qmask); + q11 = rte_sched_port_enqueue_qptrs_prefetch0(subport11, + pkt11, subport_qmask); - q20_base = rte_sched_port_qbase(port, q20); - q21_base = rte_sched_port_qbase(port, q21); - rte_sched_port_enqueue_qwa_prefetch0(port, q20, q20_base); - rte_sched_port_enqueue_qwa_prefetch0(port, q21, q21_base); + q20_base = rte_sched_subport_pipe_qbase(subport20, q20); + q21_base = rte_sched_subport_pipe_qbase(subport21, q21); + rte_sched_port_enqueue_qwa_prefetch0(port, subport20, q20, q20_base); + rte_sched_port_enqueue_qwa_prefetch0(port, subport21, q21, q21_base); /* Run the pipeline */ for (i = 6; i < (n_pkts & (~1)); i += 2) { @@ -1911,6 +1965,10 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, q31 = q21; q20 = q10; q21 = q11; + subport30 = subport20; + subport31 = subport21; + subport20 = subport10; + subport21 = subport11; q30_base = q20_base; q31_base = q21_base; @@ -1920,19 +1978,25 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, rte_prefetch0(pkt00); rte_prefetch0(pkt01); - /* Stage 1: Prefetch queue structure storing queue pointers */ - q10 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt10); - q11 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt11); + /* Stage 1: Prefetch subport and queue structure storing queue pointers */ + subport10 = rte_sched_port_subport(port, pkt10); + subport11 = rte_sched_port_subport(port, pkt11); + q10 = rte_sched_port_enqueue_qptrs_prefetch0(subport10, + pkt10, subport_qmask); + q11 = rte_sched_port_enqueue_qptrs_prefetch0(subport11, + pkt11, subport_qmask); /* Stage 2: Prefetch queue write location */ - q20_base = rte_sched_port_qbase(port, q20); - q21_base = rte_sched_port_qbase(port, q21); - rte_sched_port_enqueue_qwa_prefetch0(port, q20, q20_base); - rte_sched_port_enqueue_qwa_prefetch0(port, q21, q21_base); + q20_base = rte_sched_subport_pipe_qbase(subport20, q20); + q21_base = rte_sched_subport_pipe_qbase(subport21, q21); + rte_sched_port_enqueue_qwa_prefetch0(port, subport20, q20, q20_base); + rte_sched_port_enqueue_qwa_prefetch0(port, subport21, q21, q21_base); /* Stage 3: Write packet to queue and activate queue */ - r30 = rte_sched_port_enqueue_qwa(port, q30, q30_base, pkt30); - r31 = rte_sched_port_enqueue_qwa(port, q31, q31_base, pkt31); + r30 = rte_sched_port_enqueue_qwa(port, subport30, + q30, q30_base, pkt30); + r31 = rte_sched_port_enqueue_qwa(port, subport31, + q31, q31_base, pkt31); result += r30 + r31; } @@ -1944,38 +2008,52 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, pkt_last = pkts[n_pkts - 1]; rte_prefetch0(pkt_last); - q00 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt00); - q01 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt01); - - q10_base = rte_sched_port_qbase(port, q10); - q11_base = rte_sched_port_qbase(port, q11); - rte_sched_port_enqueue_qwa_prefetch0(port, q10, q10_base); - rte_sched_port_enqueue_qwa_prefetch0(port, q11, q11_base); - - r20 = rte_sched_port_enqueue_qwa(port, q20, q20_base, pkt20); - r21 = rte_sched_port_enqueue_qwa(port, q21, q21_base, pkt21); + subport00 = rte_sched_port_subport(port, pkt00); + subport01 = rte_sched_port_subport(port, pkt01); + q00 = rte_sched_port_enqueue_qptrs_prefetch0(subport00, + pkt00, subport_qmask); + q01 = rte_sched_port_enqueue_qptrs_prefetch0(subport01, + pkt01, subport_qmask); + + q10_base = rte_sched_subport_pipe_qbase(subport10, q10); + q11_base = rte_sched_subport_pipe_qbase(subport11, q11); + rte_sched_port_enqueue_qwa_prefetch0(port, subport10, q10, q10_base); + rte_sched_port_enqueue_qwa_prefetch0(port, subport11, q11, q11_base); + + r20 = rte_sched_port_enqueue_qwa(port, subport20, + q20, q20_base, pkt20); + r21 = rte_sched_port_enqueue_qwa(port, subport21, + q21, q21_base, pkt21); result += r20 + r21; - q_last = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt_last); + subport_last = rte_sched_port_subport(port, pkt_last); + q_last = rte_sched_port_enqueue_qptrs_prefetch0(subport_last, + pkt_last, subport_qmask); - q00_base = rte_sched_port_qbase(port, q00); - q01_base = rte_sched_port_qbase(port, q01); - rte_sched_port_enqueue_qwa_prefetch0(port, q00, q00_base); - rte_sched_port_enqueue_qwa_prefetch0(port, q01, q01_base); + q00_base = rte_sched_subport_pipe_qbase(subport00, q00); + q01_base = rte_sched_subport_pipe_qbase(subport01, q01); + rte_sched_port_enqueue_qwa_prefetch0(port, subport00, q00, q00_base); + rte_sched_port_enqueue_qwa_prefetch0(port, subport01, q01, q01_base); - r10 = rte_sched_port_enqueue_qwa(port, q10, q10_base, pkt10); - r11 = rte_sched_port_enqueue_qwa(port, q11, q11_base, pkt11); + r10 = rte_sched_port_enqueue_qwa(port, subport10, q10, + q10_base, pkt10); + r11 = rte_sched_port_enqueue_qwa(port, subport11, q11, + q11_base, pkt11); result += r10 + r11; - q_last_base = rte_sched_port_qbase(port, q_last); - rte_sched_port_enqueue_qwa_prefetch0(port, q_last, q_last_base); + q_last_base = rte_sched_subport_pipe_qbase(subport_last, q_last); + rte_sched_port_enqueue_qwa_prefetch0(port, subport_last, + q_last, q_last_base); - r00 = rte_sched_port_enqueue_qwa(port, q00, q00_base, pkt00); - r01 = rte_sched_port_enqueue_qwa(port, q01, q01_base, pkt01); + r00 = rte_sched_port_enqueue_qwa(port, subport00, q00, + q00_base, pkt00); + r01 = rte_sched_port_enqueue_qwa(port, subport01, q01, + q01_base, pkt01); result += r00 + r01; if (n_pkts & 1) { - r_last = rte_sched_port_enqueue_qwa(port, q_last, q_last_base, pkt_last); + r_last = rte_sched_port_enqueue_qwa(port, subport_last, + q_last, q_last_base, pkt_last); result += r_last; } -- 2.21.0
Update memory footprint compute function for allowing subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 102 +++++++++++------------------------ lib/librte_sched/rte_sched.h | 8 +-- 2 files changed, 36 insertions(+), 74 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index a5e4c45b4..f8d13c66d 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -495,70 +495,6 @@ rte_sched_port_check_params(struct rte_sched_port_params *params) return 0; } -static uint32_t -rte_sched_port_get_array_base(struct rte_sched_port_params *params, enum rte_sched_port_array array) -{ - uint32_t n_subports_per_port = params->n_subports_per_port; - uint32_t n_pipes_per_subport = params->n_pipes_per_subport; - uint32_t n_pipes_per_port = n_pipes_per_subport * n_subports_per_port; - uint32_t n_queues_per_port = RTE_SCHED_QUEUES_PER_PIPE * n_pipes_per_subport * n_subports_per_port; - - uint32_t size_subport = n_subports_per_port * sizeof(struct rte_sched_subport); - uint32_t size_pipe = n_pipes_per_port * sizeof(struct rte_sched_pipe); - uint32_t size_queue = n_queues_per_port * sizeof(struct rte_sched_queue); - uint32_t size_queue_extra - = n_queues_per_port * sizeof(struct rte_sched_queue_extra); - uint32_t size_pipe_profiles - = params->n_max_pipe_profiles * sizeof(struct rte_sched_pipe_profile); - uint32_t size_bmp_array = rte_bitmap_get_memory_footprint(n_queues_per_port); - uint32_t size_per_pipe_queue_array, size_queue_array; - - uint32_t base, i; - - size_per_pipe_queue_array = 0; - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - if (i < RTE_SCHED_TRAFFIC_CLASS_BE) - size_per_pipe_queue_array += - params->qsize[i] * sizeof(struct rte_mbuf *); - else - size_per_pipe_queue_array += RTE_SCHED_MAX_QUEUES_PER_TC * - params->qsize[i] * sizeof(struct rte_mbuf *); - } - size_queue_array = n_pipes_per_port * size_per_pipe_queue_array; - - base = 0; - - if (array == e_RTE_SCHED_PORT_ARRAY_SUBPORT) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_subport); - - if (array == e_RTE_SCHED_PORT_ARRAY_PIPE) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_pipe); - - if (array == e_RTE_SCHED_PORT_ARRAY_QUEUE) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_queue); - - if (array == e_RTE_SCHED_PORT_ARRAY_QUEUE_EXTRA) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_queue_extra); - - if (array == e_RTE_SCHED_PORT_ARRAY_PIPE_PROFILES) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_pipe_profiles); - - if (array == e_RTE_SCHED_PORT_ARRAY_BMP_ARRAY) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_bmp_array); - - if (array == e_RTE_SCHED_PORT_ARRAY_QUEUE_ARRAY) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_queue_array); - - return base; -} - static uint32_t rte_sched_subport_get_array_base(struct rte_sched_subport_params *params, uint32_t n_max_pipe_profiles, @@ -880,22 +816,46 @@ rte_sched_subport_check_params(struct rte_sched_subport_params *params, } uint32_t -rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params) +rte_sched_port_get_memory_footprint(struct rte_sched_port_params *port_params, + struct rte_sched_subport_params **subport_params) { - uint32_t size0, size1; + uint32_t size0 = 0, size1 = 0, i; int status; - status = rte_sched_port_check_params(params); + status = rte_sched_port_check_params(port_params); if (status != 0) { - RTE_LOG(NOTICE, SCHED, - "Port scheduler params check failed (%d)\n", status); + RTE_LOG(ERR, SCHED, + "%s: Port scheduler port params check failed (%d)\n", + __func__, status); return 0; } + for (i = 0; i < port_params->n_subports_per_port; i++) { + struct rte_sched_subport_params *sp = subport_params[i]; + + status = rte_sched_subport_check_params(sp, + port_params->n_max_pipes_per_subport, + port_params->n_max_pipe_profiles, + port_params->rate); + if (status != 0) { + RTE_LOG(ERR, SCHED, + "%s: Port scheduler subport params check failed (%d)\n", + __func__, status); + + return 0; + } + } + size0 = sizeof(struct rte_sched_port); - size1 = rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_TOTAL); + + for (i = 0; i < port_params->n_subports_per_port; i++) { + struct rte_sched_subport_params *sp = subport_params[i]; + + size1 += rte_sched_subport_get_array_base(sp, + port_params->n_max_pipe_profiles, + e_RTE_SCHED_SUBPORT_ARRAY_TOTAL); + } return size0 + size1; } diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index 56e9fbfa7..ea2b07448 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -364,14 +364,16 @@ rte_sched_pipe_config(struct rte_sched_port *port, /** * Hierarchical scheduler memory footprint size per port * - * @param params + * @param port_params * Port scheduler configuration parameter structure + * @param subport_params + * Array of subport parameter structures * @return * Memory footprint size in bytes upon success, 0 otherwise */ uint32_t -rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params); - +rte_sched_port_get_memory_footprint(struct rte_sched_port_params *port_params, + struct rte_sched_subport_params **subport_params); /* * Statistics * -- 2.21.0
Modify packet grinder functions of the schedule to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 223 +++++++++++++++++------------------ 1 file changed, 106 insertions(+), 117 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index f8d13c66d..0451e10ea 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -324,24 +324,6 @@ rte_sched_port_queues_per_port(struct rte_sched_port *port) return RTE_SCHED_QUEUES_PER_PIPE * port->n_pipes_per_subport * port->n_subports_per_port; } -static inline struct rte_mbuf ** -rte_sched_port_qbase(struct rte_sched_port *port, uint32_t qindex) -{ - uint32_t pindex = qindex >> 4; - uint32_t qpos = qindex & 0xF; - - return (port->queue_array + pindex * - port->qsize_sum + port->qsize_add[qpos]); -} - -static inline uint16_t -rte_sched_port_qsize(struct rte_sched_port *port, uint32_t qindex) -{ - uint32_t tc = port->pipe_tc[qindex & (RTE_SCHED_QUEUES_PER_PIPE - 1)]; - - return port->qsize[tc]; -} - static inline uint16_t rte_sched_port_pipe_queue(struct rte_sched_port *port, uint32_t traffic_class) { @@ -1546,9 +1528,10 @@ rte_sched_queue_read_stats(struct rte_sched_port *port, #ifdef RTE_SCHED_DEBUG static inline int -rte_sched_port_queue_is_empty(struct rte_sched_port *port, uint32_t qindex) +rte_sched_port_queue_is_empty(struct rte_sched_subport *subport, + uint32_t qindex) { - struct rte_sched_queue *queue = port->queue + qindex; + struct rte_sched_queue *queue = subport->queue + qindex; return queue->qr == queue->qw; } @@ -1663,9 +1646,10 @@ rte_sched_port_red_drop(struct rte_sched_port *port, } static inline void -rte_sched_port_set_queue_empty_timestamp(struct rte_sched_port *port, uint32_t qindex) +rte_sched_port_set_queue_empty_timestamp(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t qindex) { - struct rte_sched_queue_extra *qe = port->queue_extra + qindex; + struct rte_sched_queue_extra *qe = subport->queue_extra + qindex; struct rte_red *red = &qe->red; rte_red_mark_queue_empty(red, port->time); @@ -1682,14 +1666,14 @@ static inline int rte_sched_port_red_drop(struct rte_sched_port *port __rte_unus return 0; } -#define rte_sched_port_set_queue_empty_timestamp(port, qindex) +#define rte_sched_port_set_queue_empty_timestamp(port, subport, qindex) #endif /* RTE_SCHED_RED */ #ifdef RTE_SCHED_DEBUG static inline void -debug_check_queue_slab(struct rte_sched_port *port, uint32_t bmp_pos, +debug_check_queue_slab(struct rte_sched_subport *subport, uint32_t bmp_pos, uint64_t bmp_slab) { uint64_t mask; @@ -1701,7 +1685,7 @@ debug_check_queue_slab(struct rte_sched_port *port, uint32_t bmp_pos, panic = 0; for (i = 0, mask = 1; i < 64; i++, mask <<= 1) { if (mask & bmp_slab) { - if (rte_sched_port_queue_is_empty(port, bmp_pos + i)) { + if (rte_sched_port_queue_is_empty(subport, bmp_pos + i)) { printf("Queue %u (slab offset %u) is empty\n", bmp_pos + i, i); panic = 1; } @@ -2023,10 +2007,10 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, #ifndef RTE_SCHED_SUBPORT_TC_OV static inline void -grinder_credits_update(struct rte_sched_port *port, uint32_t pos) +grinder_credits_update(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; struct rte_sched_pipe_profile *params = grinder->pipe_params; uint64_t n_periods; @@ -2064,10 +2048,9 @@ grinder_credits_update(struct rte_sched_port *port, uint32_t pos) #else static inline uint32_t -grinder_tc_ov_credits_update(struct rte_sched_port *port, uint32_t pos) +grinder_tc_ov_credits_update(struct rte_sched_port *port, + struct rte_sched_subport *subport) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; uint32_t tc_ov_consumption[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; uint32_t tc_consumption = 0, tc_ov_consumption_max; uint32_t tc_ov_wm = subport->tc_ov_wm; @@ -2107,10 +2090,10 @@ grinder_tc_ov_credits_update(struct rte_sched_port *port, uint32_t pos) } static inline void -grinder_credits_update(struct rte_sched_port *port, uint32_t pos) +grinder_credits_update(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; struct rte_sched_pipe_profile *params = grinder->pipe_params; uint64_t n_periods; @@ -2130,7 +2113,7 @@ grinder_credits_update(struct rte_sched_port *port, uint32_t pos) /* Subport TCs */ if (unlikely(port->time >= subport->tc_time)) { - subport->tc_ov_wm = grinder_tc_ov_credits_update(port, pos); + subport->tc_ov_wm = grinder_tc_ov_credits_update(port, subport); for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) subport->tc_credits[i] = subport->tc_credits_per_period[i]; @@ -2160,10 +2143,10 @@ grinder_credits_update(struct rte_sched_port *port, uint32_t pos) #ifndef RTE_SCHED_SUBPORT_TC_OV static inline int -grinder_credits_check(struct rte_sched_port *port, uint32_t pos) +grinder_credits_check(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; + 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; @@ -2195,10 +2178,10 @@ grinder_credits_check(struct rte_sched_port *port, uint32_t pos) #else static inline int -grinder_credits_check(struct rte_sched_port *port, uint32_t pos) +grinder_credits_check(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; + 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; @@ -2243,15 +2226,16 @@ grinder_credits_check(struct rte_sched_port *port, uint32_t pos) static inline int -grinder_schedule(struct rte_sched_port *port, uint32_t pos) +grinder_schedule(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_queue *queue = grinder->queue[grinder->qpos]; struct rte_mbuf *pkt = grinder->pkt; uint32_t pkt_len = pkt->pkt_len + port->frame_overhead; uint32_t be_tc_active; - if (!grinder_credits_check(port, pos)) + if (!grinder_credits_check(port, subport, pos)) return 0; /* Advance port time */ @@ -2268,15 +2252,15 @@ grinder_schedule(struct rte_sched_port *port, uint32_t pos) if (queue->qr == queue->qw) { uint32_t qindex = grinder->qindex[grinder->qpos]; - rte_bitmap_clear(port->bmp, qindex); + rte_bitmap_clear(subport->bmp, qindex); grinder->qmask &= ~(1 << grinder->qpos); if (be_tc_active) grinder->wrr_mask[grinder->qpos] = 0; - rte_sched_port_set_queue_empty_timestamp(port, qindex); + rte_sched_port_set_queue_empty_timestamp(port, subport, qindex); } /* Reset pipe loop detection */ - port->pipe_loop = RTE_SCHED_PIPE_INVALID; + subport->pipe_loop = RTE_SCHED_PIPE_INVALID; grinder->productive = 1; return 1; @@ -2285,13 +2269,13 @@ grinder_schedule(struct rte_sched_port *port, uint32_t pos) #ifdef SCHED_VECTOR_SSE4 static inline int -grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) +grinder_pipe_exists(struct rte_sched_subport *subport, uint32_t base_pipe) { __m128i index = _mm_set1_epi32(base_pipe); - __m128i pipes = _mm_load_si128((__m128i *)port->grinder_base_bmp_pos); + __m128i pipes = _mm_load_si128((__m128i *)subport->grinder_base_bmp_pos); __m128i res = _mm_cmpeq_epi32(pipes, index); - pipes = _mm_load_si128((__m128i *)(port->grinder_base_bmp_pos + 4)); + pipes = _mm_load_si128((__m128i *)(subport->grinder_base_bmp_pos + 4)); pipes = _mm_cmpeq_epi32(pipes, index); res = _mm_or_si128(res, pipes); @@ -2304,10 +2288,10 @@ grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) #elif defined(SCHED_VECTOR_NEON) static inline int -grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) +grinder_pipe_exists(struct rte_sched_subport *subport, uint32_t base_pipe) { uint32x4_t index, pipes; - uint32_t *pos = (uint32_t *)port->grinder_base_bmp_pos; + uint32_t *pos = (uint32_t *)subport->grinder_base_bmp_pos; index = vmovq_n_u32(base_pipe); pipes = vld1q_u32(pos); @@ -2324,12 +2308,12 @@ grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) #else static inline int -grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) +grinder_pipe_exists(struct rte_sched_subport *subport, uint32_t base_pipe) { uint32_t i; for (i = 0; i < RTE_SCHED_PORT_N_GRINDERS; i++) { - if (port->grinder_base_bmp_pos[i] == base_pipe) + if (subport->grinder_base_bmp_pos[i] == base_pipe) return 1; } @@ -2339,9 +2323,10 @@ grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) #endif /* RTE_SCHED_OPTIMIZATIONS */ static inline void -grinder_pcache_populate(struct rte_sched_port *port, uint32_t pos, uint32_t bmp_pos, uint64_t bmp_slab) +grinder_pcache_populate(struct rte_sched_subport *subport, + uint32_t pos, uint32_t bmp_pos, uint64_t bmp_slab) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint16_t w[4]; grinder->pcache_w = 0; @@ -2370,9 +2355,10 @@ grinder_pcache_populate(struct rte_sched_port *port, uint32_t pos, uint32_t bmp_ } static inline void -grinder_tccache_populate(struct rte_sched_port *port, uint32_t pos, uint32_t qindex, uint16_t qmask) +grinder_tccache_populate(struct rte_sched_subport *subport, + uint32_t pos, uint32_t qindex, uint16_t qmask) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint8_t b, i; grinder->tccache_w = 0; @@ -2393,9 +2379,10 @@ grinder_tccache_populate(struct rte_sched_port *port, uint32_t pos, uint32_t qin } static inline int -grinder_next_tc(struct rte_sched_port *port, uint32_t pos) +grinder_next_tc(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_mbuf **qbase; uint32_t qindex; uint16_t qsize; @@ -2404,15 +2391,15 @@ grinder_next_tc(struct rte_sched_port *port, uint32_t pos) return 0; qindex = grinder->tccache_qindex[grinder->tccache_r]; - qbase = rte_sched_port_qbase(port, qindex); - qsize = rte_sched_port_qsize(port, qindex); + qbase = rte_sched_subport_pipe_qbase(subport, qindex); + qsize = rte_sched_subport_pipe_qsize(port, subport, qindex); grinder->tc_index = rte_sched_port_pipe_tc(port, qindex); grinder->qmask = grinder->tccache_qmask[grinder->tccache_r]; grinder->qsize = qsize; if (grinder->tc_index < RTE_SCHED_TRAFFIC_CLASS_BE) { - grinder->queue[0] = port->queue + qindex; + grinder->queue[0] = subport->queue + qindex; grinder->qbase[0] = qbase; grinder->qindex[0] = qindex; grinder->tccache_r++; @@ -2420,10 +2407,10 @@ grinder_next_tc(struct rte_sched_port *port, uint32_t pos) return 1; } - grinder->queue[0] = port->queue + qindex; - grinder->queue[1] = port->queue + qindex + 1; - grinder->queue[2] = port->queue + qindex + 2; - grinder->queue[3] = port->queue + qindex + 3; + grinder->queue[0] = subport->queue + qindex; + grinder->queue[1] = subport->queue + qindex + 1; + grinder->queue[2] = subport->queue + qindex + 2; + grinder->queue[3] = subport->queue + qindex + 3; grinder->qbase[0] = qbase; grinder->qbase[1] = qbase + qsize; @@ -2440,9 +2427,10 @@ grinder_next_tc(struct rte_sched_port *port, uint32_t pos) } static inline int -grinder_next_pipe(struct rte_sched_port *port, uint32_t pos) +grinder_next_pipe(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint32_t pipe_qindex; uint16_t pipe_qmask; @@ -2455,22 +2443,22 @@ grinder_next_pipe(struct rte_sched_port *port, uint32_t pos) uint32_t bmp_pos = 0; /* Get another non-empty pipe group */ - if (unlikely(rte_bitmap_scan(port->bmp, &bmp_pos, &bmp_slab) <= 0)) + if (unlikely(rte_bitmap_scan(subport->bmp, &bmp_pos, &bmp_slab) <= 0)) return 0; #ifdef RTE_SCHED_DEBUG - debug_check_queue_slab(port, bmp_pos, bmp_slab); + debug_check_queue_slab(subport, bmp_pos, bmp_slab); #endif /* Return if pipe group already in one of the other grinders */ - port->grinder_base_bmp_pos[pos] = RTE_SCHED_BMP_POS_INVALID; - if (unlikely(grinder_pipe_exists(port, bmp_pos))) + subport->grinder_base_bmp_pos[pos] = RTE_SCHED_BMP_POS_INVALID; + if (unlikely(grinder_pipe_exists(subport, bmp_pos))) return 0; - port->grinder_base_bmp_pos[pos] = bmp_pos; + subport->grinder_base_bmp_pos[pos] = bmp_pos; /* Install new pipe group into grinder's pipe cache */ - grinder_pcache_populate(port, pos, bmp_pos, bmp_slab); + grinder_pcache_populate(subport, pos, bmp_pos, bmp_slab); pipe_qmask = grinder->pcache_qmask[0]; pipe_qindex = grinder->pcache_qindex[0]; @@ -2479,18 +2467,18 @@ grinder_next_pipe(struct rte_sched_port *port, uint32_t pos) /* Install new pipe in the grinder */ grinder->pindex = pipe_qindex >> 4; - grinder->subport = port->subport + (grinder->pindex / port->n_pipes_per_subport); - grinder->pipe = port->pipe + grinder->pindex; + grinder->subport = subport; + grinder->pipe = subport->pipe + grinder->pindex; grinder->pipe_params = NULL; /* to be set after the pipe structure is prefetched */ grinder->productive = 0; - grinder_tccache_populate(port, pos, pipe_qindex, pipe_qmask); - grinder_next_tc(port, pos); + grinder_tccache_populate(subport, pos, pipe_qindex, pipe_qmask); + grinder_next_tc(port, subport, pos); /* Check for pipe exhaustion */ - if (grinder->pindex == port->pipe_loop) { - port->pipe_exhaustion = 1; - port->pipe_loop = RTE_SCHED_PIPE_INVALID; + if (grinder->pindex == subport->pipe_loop) { + subport->pipe_exhaustion = 1; + subport->pipe_loop = RTE_SCHED_PIPE_INVALID; } return 1; @@ -2498,9 +2486,9 @@ grinder_next_pipe(struct rte_sched_port *port, uint32_t pos) static inline void -grinder_wrr_load(struct rte_sched_port *port, uint32_t pos) +grinder_wrr_load(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; struct rte_sched_pipe_profile *pipe_params = grinder->pipe_params; uint32_t qmask = grinder->qmask; @@ -2526,9 +2514,9 @@ grinder_wrr_load(struct rte_sched_port *port, uint32_t pos) } static inline void -grinder_wrr_store(struct rte_sched_port *port, uint32_t pos) +grinder_wrr_store(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; pipe->wrr_tokens[0] = @@ -2546,9 +2534,9 @@ grinder_wrr_store(struct rte_sched_port *port, uint32_t pos) } static inline void -grinder_wrr(struct rte_sched_port *port, uint32_t pos) +grinder_wrr(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint16_t wrr_tokens_min; grinder->wrr_tokens[0] |= ~grinder->wrr_mask[0]; @@ -2566,21 +2554,21 @@ grinder_wrr(struct rte_sched_port *port, uint32_t pos) } -#define grinder_evict(port, pos) +#define grinder_evict(subport, pos) static inline void -grinder_prefetch_pipe(struct rte_sched_port *port, uint32_t pos) +grinder_prefetch_pipe(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; rte_prefetch0(grinder->pipe); rte_prefetch0(grinder->queue[0]); } static inline void -grinder_prefetch_tc_queue_arrays(struct rte_sched_port *port, uint32_t pos) +grinder_prefetch_tc_queue_arrays(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint16_t qsize, qr[RTE_SCHED_MAX_QUEUES_PER_TC]; qsize = grinder->qsize; @@ -2601,17 +2589,17 @@ grinder_prefetch_tc_queue_arrays(struct rte_sched_port *port, uint32_t pos) rte_prefetch0(grinder->qbase[0] + qr[0]); rte_prefetch0(grinder->qbase[1] + qr[1]); - grinder_wrr_load(port, pos); - grinder_wrr(port, pos); + grinder_wrr_load(subport, pos); + grinder_wrr(subport, pos); rte_prefetch0(grinder->qbase[2] + qr[2]); rte_prefetch0(grinder->qbase[3] + qr[3]); } static inline void -grinder_prefetch_mbuf(struct rte_sched_port *port, uint32_t pos) +grinder_prefetch_mbuf(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint32_t qpos = grinder->qpos; struct rte_mbuf **qbase = grinder->qbase[qpos]; uint16_t qsize = grinder->qsize; @@ -2630,14 +2618,15 @@ grinder_prefetch_mbuf(struct rte_sched_port *port, uint32_t pos) static inline uint32_t grinder_handle(struct rte_sched_port *port, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_subport *subport = port->subport; + struct rte_sched_grinder *grinder = subport->grinder + pos; switch (grinder->state) { case e_GRINDER_PREFETCH_PIPE: { - if (grinder_next_pipe(port, pos)) { - grinder_prefetch_pipe(port, pos); - port->busy_grinders++; + if (grinder_next_pipe(port, subport, pos)) { + grinder_prefetch_pipe(subport, pos); + subport->busy_grinders++; grinder->state = e_GRINDER_PREFETCH_TC_QUEUE_ARRAYS; return 0; @@ -2650,9 +2639,9 @@ grinder_handle(struct rte_sched_port *port, uint32_t pos) { struct rte_sched_pipe *pipe = grinder->pipe; - grinder->pipe_params = port->pipe_profiles + pipe->profile; - grinder_prefetch_tc_queue_arrays(port, pos); - grinder_credits_update(port, pos); + grinder->pipe_params = subport->pipe_profiles + pipe->profile; + grinder_prefetch_tc_queue_arrays(subport, pos); + grinder_credits_update(port, subport, pos); grinder->state = e_GRINDER_PREFETCH_MBUF; return 0; @@ -2660,7 +2649,7 @@ grinder_handle(struct rte_sched_port *port, uint32_t pos) case e_GRINDER_PREFETCH_MBUF: { - grinder_prefetch_mbuf(port, pos); + grinder_prefetch_mbuf(subport, pos); grinder->state = e_GRINDER_READ_MBUF; return 0; @@ -2670,47 +2659,47 @@ grinder_handle(struct rte_sched_port *port, uint32_t pos) { uint32_t wrr_active, result = 0; - result = grinder_schedule(port, pos); + result = grinder_schedule(port, subport, pos); wrr_active = (grinder->tc_index == RTE_SCHED_TRAFFIC_CLASS_BE); /* Look for next packet within the same TC */ if (result && grinder->qmask) { if (wrr_active) - grinder_wrr(port, pos); + grinder_wrr(subport, pos); - grinder_prefetch_mbuf(port, pos); + grinder_prefetch_mbuf(subport, pos); return 1; } if (wrr_active) - grinder_wrr_store(port, pos); + grinder_wrr_store(subport, pos); /* Look for another active TC within same pipe */ - if (grinder_next_tc(port, pos)) { - grinder_prefetch_tc_queue_arrays(port, pos); + if (grinder_next_tc(port, subport, pos)) { + grinder_prefetch_tc_queue_arrays(subport, pos); grinder->state = e_GRINDER_PREFETCH_MBUF; return result; } if (grinder->productive == 0 && - port->pipe_loop == RTE_SCHED_PIPE_INVALID) - port->pipe_loop = grinder->pindex; + subport->pipe_loop == RTE_SCHED_PIPE_INVALID) + subport->pipe_loop = grinder->pindex; - grinder_evict(port, pos); + grinder_evict(subport, pos); /* Look for another active pipe */ - if (grinder_next_pipe(port, pos)) { - grinder_prefetch_pipe(port, pos); + if (grinder_next_pipe(port, subport, pos)) { + grinder_prefetch_pipe(subport, pos); grinder->state = e_GRINDER_PREFETCH_TC_QUEUE_ARRAYS; return result; } /* No active pipe found */ - port->busy_grinders--; + subport->busy_grinders--; grinder->state = e_GRINDER_PREFETCH_PIPE; return result; -- 2.21.0
Modify scheduler packet dequeue operation to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 51 ++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 0451e10ea..e0ef86f40 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -245,6 +245,7 @@ struct rte_sched_port { uint32_t busy_grinders; struct rte_mbuf **pkts_out; uint32_t n_pkts_out; + uint32_t subport_id; /* Queue base calculation */ uint32_t qsize_add[RTE_SCHED_QUEUES_PER_PIPE]; @@ -911,6 +912,7 @@ rte_sched_port_config(struct rte_sched_port_params *params) /* Grinders */ port->pkts_out = NULL; port->n_pkts_out = 0; + port->subport_id = 0; return port; } @@ -2616,9 +2618,9 @@ grinder_prefetch_mbuf(struct rte_sched_subport *subport, uint32_t pos) } static inline uint32_t -grinder_handle(struct rte_sched_port *port, uint32_t pos) +grinder_handle(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_subport *subport = port->subport; struct rte_sched_grinder *grinder = subport->grinder + pos; switch (grinder->state) { @@ -2717,6 +2719,7 @@ rte_sched_port_time_resync(struct rte_sched_port *port) uint64_t cycles = rte_get_tsc_cycles(); uint64_t cycles_diff = cycles - port->time_cpu_cycles; uint64_t bytes_diff; + uint32_t i; /* Compute elapsed time in bytes */ bytes_diff = rte_reciprocal_divide(cycles_diff << RTE_SCHED_TIME_SHIFT, @@ -2729,20 +2732,21 @@ rte_sched_port_time_resync(struct rte_sched_port *port) port->time = port->time_cpu_bytes; /* Reset pipe loop detection */ - port->pipe_loop = RTE_SCHED_PIPE_INVALID; + for (i = 0; i < port->n_subports_per_port; i++) + port->subports[i]->pipe_loop = RTE_SCHED_PIPE_INVALID; } static inline int -rte_sched_port_exceptions(struct rte_sched_port *port, int second_pass) +rte_sched_port_exceptions(struct rte_sched_subport *subport, int second_pass) { int exceptions; /* Check if any exception flag is set */ - exceptions = (second_pass && port->busy_grinders == 0) || - (port->pipe_exhaustion == 1); + exceptions = (second_pass && subport->busy_grinders == 0) || + (subport->pipe_exhaustion == 1); /* Clear exception flags */ - port->pipe_exhaustion = 0; + subport->pipe_exhaustion = 0; return exceptions; } @@ -2750,7 +2754,9 @@ rte_sched_port_exceptions(struct rte_sched_port *port, int second_pass) int rte_sched_port_dequeue(struct rte_sched_port *port, struct rte_mbuf **pkts, uint32_t n_pkts) { - uint32_t i, count; + struct rte_sched_subport *subport; + uint32_t subport_id = port->subport_id; + uint32_t i, n_subports = 0, count; port->pkts_out = pkts; port->n_pkts_out = 0; @@ -2759,9 +2765,32 @@ rte_sched_port_dequeue(struct rte_sched_port *port, struct rte_mbuf **pkts, uint /* Take each queue in the grinder one step further */ for (i = 0, count = 0; ; i++) { - count += grinder_handle(port, i & (RTE_SCHED_PORT_N_GRINDERS - 1)); - if ((count == n_pkts) || - rte_sched_port_exceptions(port, i >= RTE_SCHED_PORT_N_GRINDERS)) { + subport = port->subports[subport_id]; + + count += grinder_handle(port, subport, + i & (RTE_SCHED_PORT_N_GRINDERS - 1)); + + if (count == n_pkts) { + subport_id++; + + if (subport_id == port->n_subports_per_port) + subport_id = 0; + + port->subport_id = subport_id; + break; + } + + if (rte_sched_port_exceptions(subport, i >= RTE_SCHED_PORT_N_GRINDERS)) { + i = 0; + subport_id++; + n_subports++; + } + + if (subport_id == port->n_subports_per_port) + subport_id = 0; + + if (n_subports == port->n_subports_per_port) { + port->subport_id = subport_id; break; } } -- 2.21.0
Modify pipe queue stats read function to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index e0ef86f40..8a7727286 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -284,16 +284,6 @@ enum rte_sched_subport_array { e_RTE_SCHED_SUBPORT_ARRAY_TOTAL, }; -#ifdef RTE_SCHED_COLLECT_STATS - -static inline uint32_t -rte_sched_port_queues_per_subport(struct rte_sched_port *port) -{ - return RTE_SCHED_QUEUES_PER_PIPE * port->n_pipes_per_subport; -} - -#endif - static inline uint32_t rte_sched_subport_pipe_queues(struct rte_sched_subport *subport) { @@ -322,7 +312,12 @@ struct rte_sched_subport *subport, uint32_t qindex) static inline uint32_t rte_sched_port_queues_per_port(struct rte_sched_port *port) { - return RTE_SCHED_QUEUES_PER_PIPE * port->n_pipes_per_subport * port->n_subports_per_port; + uint32_t n_queues = 0, i; + + for (i = 0; i < port->n_subports_per_port; i++) + n_queues += rte_sched_subport_pipe_queues(port->subports[i]); + + return n_queues; } static inline uint16_t @@ -1487,8 +1482,10 @@ rte_sched_queue_read_stats(struct rte_sched_port *port, struct rte_sched_queue_stats *stats, uint16_t *qlen) { + struct rte_sched_subport *s; struct rte_sched_queue *q; struct rte_sched_queue_extra *qe; + uint32_t subport_id, subport_qmask, subport_qindex; /* Check user parameters */ if (port == NULL) { @@ -1514,8 +1511,13 @@ rte_sched_queue_read_stats(struct rte_sched_port *port, "%s: Incorrect value for parameter qlen\n", __func__); return -EINVAL; } - q = port->queue + queue_id; - qe = port->queue_extra + queue_id; + subport_qmask = port->n_max_pipes_per_subport_log2 + 4; + subport_id = (queue_id >> subport_qmask) & (port->n_subports_per_port - 1); + + s = port->subports[subport_id]; + subport_qindex = ((1 << subport_qmask) - 1) & queue_id; + q = s->queue + subport_qindex; + qe = s->queue_extra + subport_qindex; /* Copy queue stats and clear */ memcpy(stats, &qe->stats, sizeof(struct rte_sched_queue_stats)); -- 2.21.0
Modify tests function to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- app/test/test_sched.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/app/test/test_sched.c b/app/test/test_sched.c index afe0b0765..6a2896234 100644 --- a/app/test/test_sched.c +++ b/app/test/test_sched.c @@ -22,18 +22,6 @@ #define TC 2 #define QUEUE 0 -static struct rte_sched_subport_params subport_param[] = { - { - .tb_rate = 1250000000, - .tb_size = 1000000, - - .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000, - 1250000000, 1250000000, 1250000000, 1250000000, 1250000000, - 1250000000, 1250000000, 1250000000, 1250000000}, - .tc_period = 10, - }, -}; - static struct rte_sched_pipe_params pipe_profile[] = { { /* Profile #0 */ .tb_rate = 305175, @@ -48,16 +36,29 @@ static struct rte_sched_pipe_params pipe_profile[] = { }, }; +static struct rte_sched_subport_params subport_param[] = { + { + .tb_rate = 1250000000, + .tb_size = 1000000, + + .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000, + 1250000000, 1250000000, 1250000000, 1250000000, 1250000000, + 1250000000, 1250000000, 1250000000, 1250000000}, + .tc_period = 10, + .n_pipes_per_subport = 1024, + .qsize = {32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}, + .pipe_profiles = pipe_profile, + .n_pipe_profiles = 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, 32, 32, 32, 32, 32, 32, 32, 32, 32}, - .pipe_profiles = pipe_profile, - .n_pipe_profiles = 1, + .n_max_pipes_per_subport = 1024, .n_max_pipe_profiles = 1, }; @@ -140,7 +141,7 @@ test_sched(void) err = rte_sched_subport_config(port, SUBPORT, subport_param); TEST_ASSERT_SUCCESS(err, "Error config sched, err=%d\n", err); - for (pipe = 0; pipe < port_param.n_pipes_per_subport; pipe ++) { + for (pipe = 0; pipe < subport_param[0].n_pipes_per_subport; pipe++) { err = rte_sched_pipe_config(port, SUBPORT, pipe, 0); TEST_ASSERT_SUCCESS(err, "Error config sched pipe %u, err=%d\n", pipe, err); } -- 2.21.0
Modify softnic traffic management function to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- drivers/net/softnic/rte_eth_softnic_tm.c | 51 ++++++++++++------------ 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/drivers/net/softnic/rte_eth_softnic_tm.c b/drivers/net/softnic/rte_eth_softnic_tm.c index 61c3adc82..8fb728d7d 100644 --- a/drivers/net/softnic/rte_eth_softnic_tm.c +++ b/drivers/net/softnic/rte_eth_softnic_tm.c @@ -85,7 +85,8 @@ softnic_tmgr_port_create(struct pmd_internals *p, /* Subport */ n_subports = t->port_params.n_subports_per_port; for (subport_id = 0; subport_id < n_subports; subport_id++) { - uint32_t n_pipes_per_subport = t->port_params.n_pipes_per_subport; + uint32_t n_pipes_per_subport = + t->subport_params[subport_id].n_pipes_per_subport; uint32_t pipe_id; int status; @@ -2211,10 +2212,11 @@ tm_tc_wred_profile_get(struct rte_eth_dev *dev, uint32_t tc_id) #ifdef RTE_SCHED_RED static void -wred_profiles_set(struct rte_eth_dev *dev) +wred_profiles_set(struct rte_eth_dev *dev, uint32_t subport_id) { struct pmd_internals *p = dev->data->dev_private; - struct rte_sched_port_params *pp = &p->soft.tm.params.port_params; + struct rte_sched_subport_params *pp = + &p->soft.tm.params.subport_params[subport_id]; uint32_t tc_id; enum rte_color color; @@ -2234,7 +2236,7 @@ wred_profiles_set(struct rte_eth_dev *dev) #else -#define wred_profiles_set(dev) +#define wred_profiles_set(dev, subport_id) #endif @@ -2526,29 +2528,10 @@ hierarchy_blueprints_create(struct rte_eth_dev *dev) .frame_overhead = root->shaper_profile->params.pkt_length_adjust, .n_subports_per_port = root->n_children, - .n_pipes_per_subport = h->n_tm_nodes[TM_NODE_LEVEL_PIPE] / - h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT], - .qsize = {p->params.tm.qsize[0], - p->params.tm.qsize[1], - p->params.tm.qsize[2], - p->params.tm.qsize[3], - p->params.tm.qsize[4], - p->params.tm.qsize[5], - p->params.tm.qsize[6], - p->params.tm.qsize[7], - p->params.tm.qsize[8], - p->params.tm.qsize[9], - p->params.tm.qsize[10], - p->params.tm.qsize[11], - p->params.tm.qsize[12], - }, - .pipe_profiles = t->pipe_profiles, - .n_pipe_profiles = t->n_pipe_profiles, + .n_max_pipes_per_subport = TM_MAX_PIPES_PER_SUBPORT, .n_max_pipe_profiles = TM_MAX_PIPE_PROFILE, }; - wred_profiles_set(dev); - subport_id = 0; TAILQ_FOREACH(n, nl, node) { uint64_t tc_rate[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; @@ -2588,8 +2571,26 @@ hierarchy_blueprints_create(struct rte_eth_dev *dev) tc_rate[12], }, .tc_period = SUBPORT_TC_PERIOD, + .n_pipes_per_subport = h->n_tm_nodes[TM_NODE_LEVEL_PIPE] / + h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT], + .qsize = {p->params.tm.qsize[0], + p->params.tm.qsize[1], + p->params.tm.qsize[2], + p->params.tm.qsize[3], + p->params.tm.qsize[4], + p->params.tm.qsize[5], + p->params.tm.qsize[6], + p->params.tm.qsize[7], + p->params.tm.qsize[8], + p->params.tm.qsize[9], + p->params.tm.qsize[10], + p->params.tm.qsize[11], + p->params.tm.qsize[12], + }, + .pipe_profiles = t->pipe_profiles, + .n_pipe_profiles = t->n_pipe_profiles, }; - + wred_profiles_set(dev, subport_id); subport_id++; } } -- 2.21.0
Modify ip pipeline traffic management function to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- examples/ip_pipeline/cli.c | 71 ++++++++++++++++++------------------- examples/ip_pipeline/tmgr.c | 23 ++++++------ examples/ip_pipeline/tmgr.h | 7 ++-- 3 files changed, 49 insertions(+), 52 deletions(-) diff --git a/examples/ip_pipeline/cli.c b/examples/ip_pipeline/cli.c index c6cf4204e..1e8dc95b4 100644 --- a/examples/ip_pipeline/cli.c +++ b/examples/ip_pipeline/cli.c @@ -380,7 +380,12 @@ static const char cmd_tmgr_subport_profile_help[] = " <tc0_rate> <tc1_rate> <tc2_rate> <tc3_rate> <tc4_rate>" " <tc5_rate> <tc6_rate> <tc7_rate> <tc8_rate>" " <tc9_rate> <tc10_rate> <tc11_rate> <tc12_rate>\n" -" <tc_period>\n"; +" <tc_period>\n" +" pps <n_pipes_per_subport>\n" +" qsize <qsize_tc0> <qsize_tc1> <qsize_tc2>" +" <qsize_tc3> <qsize_tc4> <qsize_tc5> <qsize_tc6>" +" <qsize_tc7> <qsize_tc8> <qsize_tc9> <qsize_tc10>" +" <qsize_tc11> <qsize_tc12>"; static void cmd_tmgr_subport_profile(char **tokens, @@ -391,7 +396,7 @@ cmd_tmgr_subport_profile(char **tokens, struct rte_sched_subport_params p; int status, i; - if (n_tokens != 19) { + if (n_tokens != 35) { snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); return; } @@ -417,6 +422,27 @@ cmd_tmgr_subport_profile(char **tokens, return; } + if (strcmp(tokens[19], "pps") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps"); + return; + } + + if (parser_read_uint32(&p.n_pipes_per_subport, tokens[20]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "n_pipes_per_subport"); + return; + } + + if (strcmp(tokens[21], "qsize") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "qsize"); + return; + } + + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) + if (parser_read_uint16(&p.qsize[i], tokens[22 + i]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "qsize"); + return; + } + status = tmgr_subport_profile_add(&p); if (status != 0) { snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); @@ -491,11 +517,6 @@ static const char cmd_tmgr_help[] = "tmgr <tmgr_name>\n" " rate <rate>\n" " spp <n_subports_per_port>\n" -" pps <n_pipes_per_subport>\n" -" qsize <qsize_tc0> <qsize_tc1> <qsize_tc2>" -" <qsize_tc3> <qsize_tc4> <qsize_tc5> <qsize_tc6>" -" <qsize_tc7> <qsize_tc8> <qsize_tc9> <qsize_tc10>" -" <qsize_tc11> <qsize_tc12>\n" " fo <frame_overhead>\n" " mtu <mtu>\n" " cpu <cpu_id>\n"; @@ -509,9 +530,8 @@ cmd_tmgr(char **tokens, struct tmgr_port_params p; char *name; struct tmgr_port *tmgr_port; - int i; - if (n_tokens != 28) { + if (n_tokens != 12) { snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); return; } @@ -538,53 +558,32 @@ cmd_tmgr(char **tokens, return; } - if (strcmp(tokens[6], "pps") != 0) { - snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps"); - return; - } - - if (parser_read_uint32(&p.n_pipes_per_subport, tokens[7]) != 0) { - snprintf(out, out_size, MSG_ARG_INVALID, "n_pipes_per_subport"); - return; - } - - if (strcmp(tokens[8], "qsize") != 0) { - snprintf(out, out_size, MSG_ARG_NOT_FOUND, "qsize"); - return; - } - - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - if (parser_read_uint16(&p.qsize[i], tokens[9 + i]) != 0) { - snprintf(out, out_size, MSG_ARG_INVALID, "qsize"); - return; - } - - if (strcmp(tokens[22], "fo") != 0) { + if (strcmp(tokens[6], "fo") != 0) { snprintf(out, out_size, MSG_ARG_NOT_FOUND, "fo"); return; } - if (parser_read_uint32(&p.frame_overhead, tokens[23]) != 0) { + if (parser_read_uint32(&p.frame_overhead, tokens[7]) != 0) { snprintf(out, out_size, MSG_ARG_INVALID, "frame_overhead"); return; } - if (strcmp(tokens[24], "mtu") != 0) { + if (strcmp(tokens[8], "mtu") != 0) { snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mtu"); return; } - if (parser_read_uint32(&p.mtu, tokens[25]) != 0) { + if (parser_read_uint32(&p.mtu, tokens[9]) != 0) { snprintf(out, out_size, MSG_ARG_INVALID, "mtu"); return; } - if (strcmp(tokens[26], "cpu") != 0) { + if (strcmp(tokens[10], "cpu") != 0) { snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu"); return; } - if (parser_read_uint32(&p.cpu_id, tokens[27]) != 0) { + if (parser_read_uint32(&p.cpu_id, tokens[11]) != 0) { snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id"); return; } diff --git a/examples/ip_pipeline/tmgr.c b/examples/ip_pipeline/tmgr.c index 40cbf1d0a..cafb9cdcc 100644 --- a/examples/ip_pipeline/tmgr.c +++ b/examples/ip_pipeline/tmgr.c @@ -47,7 +47,8 @@ int tmgr_subport_profile_add(struct rte_sched_subport_params *p) { /* Check input params */ - if (p == NULL) + if (p == NULL || + p->n_pipes_per_subport == 0) return -1; /* Save profile */ @@ -90,7 +91,6 @@ tmgr_port_create(const char *name, struct tmgr_port_params *params) tmgr_port_find(name) || (params == NULL) || (params->n_subports_per_port == 0) || - (params->n_pipes_per_subport == 0) || (params->cpu_id >= RTE_MAX_NUMA_NODES) || (n_subport_profiles == 0) || (n_pipe_profiles == 0)) @@ -103,18 +103,16 @@ tmgr_port_create(const char *name, struct tmgr_port_params *params) p.mtu = params->mtu; p.frame_overhead = params->frame_overhead; p.n_subports_per_port = params->n_subports_per_port; - p.n_pipes_per_subport = params->n_pipes_per_subport; - - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - p.qsize[i] = params->qsize[i]; - - p.pipe_profiles = pipe_profile; - p.n_pipe_profiles = n_pipe_profiles; + p.n_max_pipes_per_subport = TMGR_PIPE_SUBPORT_MAX; + p.n_max_pipe_profiles = TMGR_PIPE_PROFILE_MAX; s = rte_sched_port_config(&p); if (s == NULL) return NULL; + subport_profile[0].pipe_profiles = pipe_profile; + subport_profile[0].n_pipe_profiles = n_pipe_profiles; + for (i = 0; i < params->n_subports_per_port; i++) { int status; @@ -128,7 +126,7 @@ tmgr_port_create(const char *name, struct tmgr_port_params *params) return NULL; } - for (j = 0; j < params->n_pipes_per_subport; j++) { + for (j = 0; j < subport_profile[0].n_pipes_per_subport; j++) { status = rte_sched_pipe_config( s, i, @@ -153,7 +151,6 @@ tmgr_port_create(const char *name, struct tmgr_port_params *params) strlcpy(tmgr_port->name, name, sizeof(tmgr_port->name)); tmgr_port->s = s; tmgr_port->n_subports_per_port = params->n_subports_per_port; - tmgr_port->n_pipes_per_subport = params->n_pipes_per_subport; /* Node add to list */ TAILQ_INSERT_TAIL(&tmgr_port_list, tmgr_port, node); @@ -205,8 +202,8 @@ tmgr_pipe_config(const char *port_name, port = tmgr_port_find(port_name); if ((port == NULL) || (subport_id >= port->n_subports_per_port) || - (pipe_id_first >= port->n_pipes_per_subport) || - (pipe_id_last >= port->n_pipes_per_subport) || + (pipe_id_first >= subport_profile[subport_id].n_pipes_per_subport) || + (pipe_id_last >= subport_profile[subport_id].n_pipes_per_subport) || (pipe_id_first > pipe_id_last) || (pipe_profile_id >= n_pipe_profiles)) return -1; diff --git a/examples/ip_pipeline/tmgr.h b/examples/ip_pipeline/tmgr.h index 8703a2e00..1fcf66ee1 100644 --- a/examples/ip_pipeline/tmgr.h +++ b/examples/ip_pipeline/tmgr.h @@ -12,6 +12,10 @@ #include "common.h" +#ifndef TMGR_PIPE_SUBPORT_MAX +#define TMGR_PIPE_SUBPORT_MAX 4096 +#endif + #ifndef TMGR_SUBPORT_PROFILE_MAX #define TMGR_SUBPORT_PROFILE_MAX 256 #endif @@ -25,7 +29,6 @@ struct tmgr_port { char name[NAME_SIZE]; struct rte_sched_port *s; uint32_t n_subports_per_port; - uint32_t n_pipes_per_subport; }; TAILQ_HEAD(tmgr_port_list, tmgr_port); @@ -42,8 +45,6 @@ struct tmgr_port_params { uint32_t frame_overhead; uint32_t mtu; uint32_t cpu_id; - uint32_t n_pipes_per_subport; - uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; }; int -- 2.21.0
Modify qos sample app to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- examples/qos_sched/app_thread.c | 4 +- examples/qos_sched/cfg_file.c | 226 ++++++++++++++++-------------- examples/qos_sched/init.c | 54 +++---- examples/qos_sched/main.h | 1 + examples/qos_sched/profile.cfg | 5 +- examples/qos_sched/profile_ov.cfg | 5 +- examples/qos_sched/stats.c | 36 ++--- 7 files changed, 179 insertions(+), 152 deletions(-) diff --git a/examples/qos_sched/app_thread.c b/examples/qos_sched/app_thread.c index 18b734a14..e07cc7452 100644 --- a/examples/qos_sched/app_thread.c +++ b/examples/qos_sched/app_thread.c @@ -36,9 +36,9 @@ get_pkt_sched(struct rte_mbuf *m, uint32_t *subport, uint32_t *pipe, uint16_t pipe_queue; *subport = (rte_be_to_cpu_16(pdata[SUBPORT_OFFSET]) & 0x0FFF) & - (port_params.n_subports_per_port - 1); /* Outer VLAN ID*/ + (port_params.n_subports_per_port - 1); /* Outer VLAN ID*/ *pipe = (rte_be_to_cpu_16(pdata[PIPE_OFFSET]) & 0x0FFF) & - (port_params.n_pipes_per_subport - 1); /* Inner VLAN ID */ + (subport_params[*subport].n_pipes_per_subport - 1); /* Inner VLAN ID */ pipe_queue = active_queues[(pdata[QUEUE_OFFSET] >> 8) % n_active_queues]; *traffic_class = pipe_queue > RTE_SCHED_TRAFFIC_CLASS_BE ? RTE_SCHED_TRAFFIC_CLASS_BE : pipe_queue; /* Destination IP */ diff --git a/examples/qos_sched/cfg_file.c b/examples/qos_sched/cfg_file.c index 45bf599e4..aaf7ca8f4 100644 --- a/examples/qos_sched/cfg_file.c +++ b/examples/qos_sched/cfg_file.c @@ -24,14 +24,10 @@ int cfg_load_port(struct rte_cfgfile *cfg, struct rte_sched_port_params *port_params) { const char *entry; - int j; if (!cfg || !port_params) return -1; - memset(active_queues, 0, sizeof(active_queues)); - n_active_queues = 0; - entry = rte_cfgfile_get_entry(cfg, "port", "frame overhead"); if (entry) port_params->frame_overhead = (uint32_t)atoi(entry); @@ -40,106 +36,6 @@ cfg_load_port(struct rte_cfgfile *cfg, struct rte_sched_port_params *port_params if (entry) port_params->n_subports_per_port = (uint32_t)atoi(entry); - entry = rte_cfgfile_get_entry(cfg, "port", "number of pipes per subport"); - if (entry) - port_params->n_pipes_per_subport = (uint32_t)atoi(entry); - - entry = rte_cfgfile_get_entry(cfg, "port", "queue sizes"); - if (entry) { - char *next; - - for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { - port_params->qsize[j] = (uint16_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - - for (j = 0; j < RTE_SCHED_TRAFFIC_CLASS_BE; j++) - if (port_params->qsize[j]) { - active_queues[n_active_queues] = j; - n_active_queues++; - } - - if (port_params->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]) - for (j = 0; j < RTE_SCHED_BE_QUEUES_PER_PIPE; j++) { - active_queues[n_active_queues] = - RTE_SCHED_TRAFFIC_CLASS_BE + j; - n_active_queues++; - } - } - -#ifdef RTE_SCHED_RED - for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { - char str[32]; - - /* Parse WRED min thresholds */ - snprintf(str, sizeof(str), "tc %d wred min", j); - entry = rte_cfgfile_get_entry(cfg, "red", str); - if (entry) { - char *next; - int k; - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < RTE_COLORS; k++) { - port_params->red_params[j][k].min_th - = (uint16_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - } - - /* Parse WRED max thresholds */ - snprintf(str, sizeof(str), "tc %d wred max", j); - entry = rte_cfgfile_get_entry(cfg, "red", str); - if (entry) { - char *next; - int k; - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < RTE_COLORS; k++) { - port_params->red_params[j][k].max_th - = (uint16_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - } - - /* Parse WRED inverse mark probabilities */ - snprintf(str, sizeof(str), "tc %d wred inv prob", j); - entry = rte_cfgfile_get_entry(cfg, "red", str); - if (entry) { - char *next; - int k; - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < RTE_COLORS; k++) { - port_params->red_params[j][k].maxp_inv - = (uint8_t)strtol(entry, &next, 10); - - if (next == NULL) - break; - entry = next; - } - } - - /* Parse WRED EWMA filter weights */ - snprintf(str, sizeof(str), "tc %d wred weight", j); - entry = rte_cfgfile_get_entry(cfg, "red", str); - if (entry) { - char *next; - int k; - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < RTE_COLORS; k++) { - port_params->red_params[j][k].wq_log2 - = (uint8_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - } - } -#endif /* RTE_SCHED_RED */ - return 0; } @@ -155,7 +51,7 @@ cfg_load_pipe(struct rte_cfgfile *cfg, struct rte_sched_pipe_params *pipe_params return -1; profiles = rte_cfgfile_num_sections(cfg, "pipe profile", sizeof("pipe profile") - 1); - port_params.n_pipe_profiles = profiles; + subport_params[0].n_pipe_profiles = profiles; for (j = 0; j < profiles; j++) { char pipe_name[32]; @@ -253,12 +149,118 @@ cfg_load_subport(struct rte_cfgfile *cfg, struct rte_sched_subport_params *subpo return -1; memset(app_pipe_to_profile, -1, sizeof(app_pipe_to_profile)); + memset(active_queues, 0, sizeof(active_queues)); + n_active_queues = 0; + +#ifdef RTE_SCHED_RED + char sec_name[CFG_NAME_LEN]; + struct rte_red_params red_params[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; + + snprintf(sec_name, sizeof(sec_name), "red"); + + if (rte_cfgfile_has_section(cfg, sec_name)) { + + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + char str[32]; + + /* Parse WRED min thresholds */ + snprintf(str, sizeof(str), "tc %d wred min", i); + entry = rte_cfgfile_get_entry(cfg, sec_name, str); + if (entry) { + char *next; + /* for each packet colour (green, yellow, red) */ + for (j = 0; j < RTE_COLORS; j++) { + red_params[i][j].min_th + = (uint16_t)strtol(entry, &next, 10); + if (next == NULL) + break; + entry = next; + } + } + + /* Parse WRED max thresholds */ + snprintf(str, sizeof(str), "tc %d wred max", i); + entry = rte_cfgfile_get_entry(cfg, "red", str); + if (entry) { + char *next; + /* for each packet colour (green, yellow, red) */ + for (j = 0; j < RTE_COLORS; j++) { + red_params[i][j].max_th + = (uint16_t)strtol(entry, &next, 10); + if (next == NULL) + break; + entry = next; + } + } + + /* Parse WRED inverse mark probabilities */ + snprintf(str, sizeof(str), "tc %d wred inv prob", i); + entry = rte_cfgfile_get_entry(cfg, "red", str); + if (entry) { + char *next; + /* for each packet colour (green, yellow, red) */ + for (j = 0; j < RTE_COLORS; j++) { + red_params[i][j].maxp_inv + = (uint8_t)strtol(entry, &next, 10); + + if (next == NULL) + break; + entry = next; + } + } + + /* Parse WRED EWMA filter weights */ + snprintf(str, sizeof(str), "tc %d wred weight", i); + entry = rte_cfgfile_get_entry(cfg, "red", str); + if (entry) { + char *next; + /* for each packet colour (green, yellow, red) */ + for (j = 0; j < RTE_COLORS; j++) { + red_params[i][j].wq_log2 + = (uint8_t)strtol(entry, &next, 10); + if (next == NULL) + break; + entry = next; + } + } + } + } +#endif /* RTE_SCHED_RED */ for (i = 0; i < MAX_SCHED_SUBPORTS; i++) { char sec_name[CFG_NAME_LEN]; snprintf(sec_name, sizeof(sec_name), "subport %d", i); if (rte_cfgfile_has_section(cfg, sec_name)) { + entry = rte_cfgfile_get_entry(cfg, sec_name, + "number of pipes per subport"); + if (entry) + subport_params[i].n_pipes_per_subport = + (uint32_t)atoi(entry); + + entry = rte_cfgfile_get_entry(cfg, sec_name, "queue sizes"); + if (entry) { + char *next; + + for (j = 0; j < RTE_SCHED_TRAFFIC_CLASS_BE; j++) { + subport_params[i].qsize[j] = + (uint16_t)strtol(entry, &next, 10); + if (subport_params[i].qsize[j] != 0) { + active_queues[n_active_queues] = j; + n_active_queues++; + } + if (next == NULL) + break; + entry = next; + } + + for (j = 0; j < RTE_SCHED_BE_QUEUES_PER_PIPE; j++) { + active_queues[n_active_queues] = + RTE_SCHED_TRAFFIC_CLASS_BE + j; + n_active_queues++; + } + } + entry = rte_cfgfile_get_entry(cfg, sec_name, "tb rate"); if (entry) subport_params[i].tb_rate = (uint32_t)atoi(entry); @@ -362,6 +364,20 @@ cfg_load_subport(struct rte_cfgfile *cfg, struct rte_sched_subport_params *subpo } } } +#ifdef RTE_SCHED_RED + for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { + for (k = 0; k < RTE_COLORS; k++) { + subport_params[i].red_params[j][k].min_th = + red_params[j][k].min_th; + subport_params[i].red_params[j][k].max_th = + red_params[j][k].max_th; + subport_params[i].red_params[j][k].maxp_inv = + red_params[j][k].maxp_inv; + subport_params[i].red_params[j][k].wq_log2 = + red_params[j][k].wq_log2; + } + } +#endif } } diff --git a/examples/qos_sched/init.c b/examples/qos_sched/init.c index b05206d5a..c18eea98c 100644 --- a/examples/qos_sched/init.c +++ b/examples/qos_sched/init.c @@ -165,18 +165,6 @@ app_init_port(uint16_t portid, struct rte_mempool *mp) return 0; } -static struct rte_sched_subport_params subport_params[MAX_SCHED_SUBPORTS] = { - { - .tb_rate = 1250000000, - .tb_size = 1000000, - - .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000, - 1250000000, 1250000000, 1250000000, 1250000000, 1250000000, - 1250000000, 1250000000, 1250000000, 1250000000}, - .tc_period = 10, - }, -}; - static struct rte_sched_pipe_params pipe_profiles[MAX_SCHED_PIPE_PROFILES] = { { /* Profile #0 */ .tb_rate = 305175, @@ -193,19 +181,20 @@ static struct rte_sched_pipe_params pipe_profiles[MAX_SCHED_PIPE_PROFILES] = { }, }; -struct rte_sched_port_params port_params = { - .name = "port_scheduler_0", - .socket = 0, /* computed */ - .rate = 0, /* computed */ - .mtu = 6 + 6 + 4 + 4 + 2 + 1500, - .frame_overhead = RTE_SCHED_FRAME_OVERHEAD_DEFAULT, - .n_subports_per_port = 1, - .n_pipes_per_subport = 4096, - .qsize = {64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}, - .pipe_profiles = pipe_profiles, - .n_pipe_profiles = sizeof(pipe_profiles) / sizeof(struct rte_sched_pipe_params), - .n_max_pipe_profiles = MAX_SCHED_PIPE_PROFILES, +struct rte_sched_subport_params subport_params[MAX_SCHED_SUBPORTS] = { + { + .tb_rate = 1250000000, + .tb_size = 1000000, + .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000, + 1250000000, 1250000000, 1250000000, 1250000000, 1250000000, + 1250000000, 1250000000, 1250000000, 1250000000}, + .tc_period = 10, + .n_pipes_per_subport = 4096, + .qsize = {64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}, + .pipe_profiles = pipe_profiles, + .n_pipe_profiles = sizeof(pipe_profiles) / + sizeof(struct rte_sched_pipe_params), #ifdef RTE_SCHED_RED .red_params = { /* Traffic Class 0 Colors Green / Yellow / Red */ @@ -274,6 +263,18 @@ struct rte_sched_port_params port_params = { [12][2] = {.min_th = 32, .max_th = 64, .maxp_inv = 10, .wq_log2 = 9}, }, #endif /* RTE_SCHED_RED */ + }, +}; + +struct rte_sched_port_params port_params = { + .name = "port_scheduler_0", + .socket = 0, /* computed */ + .rate = 0, /* computed */ + .mtu = 6 + 6 + 4 + 4 + 2 + 1500, + .frame_overhead = RTE_SCHED_FRAME_OVERHEAD_DEFAULT, + .n_subports_per_port = 1, + .n_max_pipes_per_subport = MAX_SCHED_PIPES, + .n_max_pipe_profiles = MAX_SCHED_PIPE_PROFILES, }; static struct rte_sched_port * @@ -304,7 +305,10 @@ app_init_sched_port(uint32_t portid, uint32_t socketid) subport, err); } - for (pipe = 0; pipe < port_params.n_pipes_per_subport; pipe++) { + uint32_t n_pipes_per_subport = + subport_params[subport].n_pipes_per_subport; + + for (pipe = 0; pipe < n_pipes_per_subport; pipe++) { if (app_pipe_to_profile[subport][pipe] != -1) { err = rte_sched_pipe_config(port, subport, pipe, app_pipe_to_profile[subport][pipe]); diff --git a/examples/qos_sched/main.h b/examples/qos_sched/main.h index d8f890b64..baa2b3ead 100644 --- a/examples/qos_sched/main.h +++ b/examples/qos_sched/main.h @@ -152,6 +152,7 @@ uint32_t active_queues[RTE_SCHED_QUEUES_PER_PIPE]; uint32_t n_active_queues; extern struct rte_sched_port_params port_params; +extern struct rte_sched_subport_params subport_params[MAX_SCHED_SUBPORTS]; int app_parse_args(int argc, char **argv); int app_init(void); diff --git a/examples/qos_sched/profile.cfg b/examples/qos_sched/profile.cfg index 335561370..61b8b7071 100644 --- a/examples/qos_sched/profile.cfg +++ b/examples/qos_sched/profile.cfg @@ -20,11 +20,12 @@ [port] frame overhead = 24 number of subports per port = 1 -number of pipes per subport = 4096 -queue sizes = 64 64 64 64 64 64 64 64 64 64 64 64 64 ; Subport configuration [subport 0] +number of pipes per subport = 4096 +queue sizes = 64 64 64 64 64 64 64 64 64 64 64 64 64 + tb rate = 1250000000 ; Bytes per second tb size = 1000000 ; Bytes diff --git a/examples/qos_sched/profile_ov.cfg b/examples/qos_sched/profile_ov.cfg index 394987399..ab509d28d 100644 --- a/examples/qos_sched/profile_ov.cfg +++ b/examples/qos_sched/profile_ov.cfg @@ -5,11 +5,12 @@ [port] frame overhead = 24 number of subports per port = 1 -number of pipes per subport = 32 -queue sizes = 64 64 64 64 64 64 64 64 64 64 64 64 64 ; Subport configuration [subport 0] +number of pipes per subport = 32 +queue sizes = 64 64 64 64 64 64 64 64 64 64 64 64 64 + tb rate = 8400000 ; Bytes per second tb size = 100000 ; Bytes diff --git a/examples/qos_sched/stats.c b/examples/qos_sched/stats.c index e62e4a2f6..0626cf6e6 100644 --- a/examples/qos_sched/stats.c +++ b/examples/qos_sched/stats.c @@ -24,7 +24,7 @@ qavg_q(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id, uint8_t tc, if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || - pipe_id >= port_params.n_pipes_per_subport || + pipe_id >= subport_params[subport_id].n_pipes_per_subport || tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE || q >= RTE_SCHED_BE_QUEUES_PER_PIPE || (tc < RTE_SCHED_TRAFFIC_CLASS_BE && q > 0)) @@ -32,7 +32,7 @@ qavg_q(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id, uint8_t tc, port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - queue_id += port_params.n_pipes_per_subport * + queue_id += subport_params[i].n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; if (tc < RTE_SCHED_TRAFFIC_CLASS_BE) queue_id += pipe_id * RTE_SCHED_QUEUES_PER_PIPE + tc; @@ -69,14 +69,15 @@ qavg_tcpipe(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id, } if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || - pipe_id >= port_params.n_pipes_per_subport || + pipe_id >= subport_params[subport_id].n_pipes_per_subport || tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE) return -1; port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - queue_id += port_params.n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; + queue_id += + subport_params[i].n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; queue_id += pipe_id * RTE_SCHED_QUEUES_PER_PIPE + tc; @@ -123,13 +124,13 @@ qavg_pipe(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id) if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || - pipe_id >= port_params.n_pipes_per_subport) + pipe_id >= subport_params[subport_id].n_pipes_per_subport) return -1; port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - queue_id += port_params.n_pipes_per_subport * + queue_id += subport_params[i].n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; queue_id += pipe_id * RTE_SCHED_QUEUES_PER_PIPE; @@ -177,13 +178,13 @@ qavg_tcsubport(uint16_t port_id, uint32_t subport_id, uint8_t tc) for (i = 0; i < subport_id; i++) subport_queue_id += - port_params.n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; + subport_params[i].n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; average = 0; for (count = 0; count < qavg_ntimes; count++) { part_average = 0; - for (i = 0; i < port_params.n_pipes_per_subport; i++) { + for (i = 0; i < subport_params[subport_id].n_pipes_per_subport; i++) { if (tc < RTE_SCHED_TRAFFIC_CLASS_BE) { queue_id = subport_queue_id + i * RTE_SCHED_QUEUES_PER_PIPE + tc; @@ -203,10 +204,11 @@ qavg_tcsubport(uint16_t port_id, uint32_t subport_id, uint8_t tc) } if (tc < RTE_SCHED_TRAFFIC_CLASS_BE) - average += part_average / (port_params.n_pipes_per_subport); + average += part_average / + (subport_params[subport_id].n_pipes_per_subport); else - average += - part_average / (port_params.n_pipes_per_subport) * + average += part_average / + (subport_params[subport_id].n_pipes_per_subport) * RTE_SCHED_BE_QUEUES_PER_PIPE; usleep(qavg_period); @@ -240,14 +242,14 @@ qavg_subport(uint16_t port_id, uint32_t subport_id) port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - subport_queue_id += port_params.n_pipes_per_subport * + subport_queue_id += subport_params[i].n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; average = 0; for (count = 0; count < qavg_ntimes; count++) { part_average = 0; - for (i = 0; i < port_params.n_pipes_per_subport; i++) { + for (i = 0; i < subport_params[subport_id].n_pipes_per_subport; i++) { queue_id = subport_queue_id + i * RTE_SCHED_QUEUES_PER_PIPE; for (j = 0; j < RTE_SCHED_QUEUES_PER_PIPE; j++) { @@ -258,7 +260,8 @@ qavg_subport(uint16_t port_id, uint32_t subport_id) } average += part_average / - (port_params.n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE); + (subport_params[subport_id].n_pipes_per_subport * + RTE_SCHED_QUEUES_PER_PIPE); usleep(qavg_period); } @@ -322,12 +325,13 @@ pipe_stat(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id) if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || - pipe_id >= port_params.n_pipes_per_subport) + pipe_id >= subport_params[subport_id].n_pipes_per_subport) return -1; port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - queue_id += port_params.n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; + queue_id += subport_params[i].n_pipes_per_subport * + RTE_SCHED_QUEUES_PER_PIPE; queue_id += pipe_id * RTE_SCHED_QUEUES_PER_PIPE; -- 2.21.0
Remove redundant data structure fields from port level data structures and update release notes. --- doc/guides/rel_notes/release_19_11.rst | 6 +++- lib/librte_sched/rte_sched.c | 43 +------------------------- lib/librte_sched/rte_sched.h | 22 ------------- 3 files changed, 6 insertions(+), 65 deletions(-) diff --git a/doc/guides/rel_notes/release_19_11.rst b/doc/guides/rel_notes/release_19_11.rst index 8490d897c..746aeb0ea 100644 --- a/doc/guides/rel_notes/release_19_11.rst +++ b/doc/guides/rel_notes/release_19_11.rst @@ -85,6 +85,10 @@ API Changes Also, make sure to start the actual text at the margin. ========================================================= +* sched: The pipe nodes configuration parameters such as number of pipes, + pipe queue sizes, pipe profiles, etc., are moved from port level structure + to subport level. This allows different subports of the same port to + have different configuration for the pipe nodes. ABI Changes ----------- @@ -172,7 +176,7 @@ The libraries prepended with a plus sign were incremented in this version. librte_rcu.so.1 librte_reorder.so.1 librte_ring.so.2 - librte_sched.so.3 + + librte_sched.so.4 librte_security.so.2 librte_stack.so.1 librte_table.so.3 diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 8a7727286..ba504da1e 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -207,10 +207,8 @@ struct rte_sched_subport { struct rte_sched_port { /* User parameters */ uint32_t n_subports_per_port; - uint32_t n_pipes_per_subport; uint32_t n_max_pipes_per_subport; uint32_t n_max_pipes_per_subport_log2; - uint32_t n_pipes_per_subport_log2; 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]; @@ -218,13 +216,7 @@ struct rte_sched_port { uint32_t mtu; uint32_t frame_overhead; int socket; - uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - uint32_t n_pipe_profiles; uint32_t n_max_pipe_profiles; - uint32_t pipe_tc_be_rate_max; -#ifdef RTE_SCHED_RED - struct rte_red_config red_config[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; -#endif /* Timing */ uint64_t time_cpu_cycles; /* Current CPU time measured in CPU cyles */ @@ -232,48 +224,15 @@ struct rte_sched_port { uint64_t time; /* Current NIC TX time measured in bytes */ struct rte_reciprocal inv_cycles_per_byte; /* CPU cycles per byte */ - /* Scheduling loop detection */ - uint32_t pipe_loop; - uint32_t pipe_exhaustion; - - /* Bitmap */ - struct rte_bitmap *bmp; - uint32_t grinder_base_bmp_pos[RTE_SCHED_PORT_N_GRINDERS] __rte_aligned_16; - /* Grinders */ - struct rte_sched_grinder grinder[RTE_SCHED_PORT_N_GRINDERS]; - uint32_t busy_grinders; struct rte_mbuf **pkts_out; uint32_t n_pkts_out; uint32_t subport_id; - /* Queue base calculation */ - uint32_t qsize_add[RTE_SCHED_QUEUES_PER_PIPE]; - uint32_t qsize_sum; - /* Large data structures */ - struct rte_sched_subport *subports[0]; - struct rte_sched_subport *subport; - struct rte_sched_pipe *pipe; - struct rte_sched_queue *queue; - struct rte_sched_queue_extra *queue_extra; - struct rte_sched_pipe_profile *pipe_profiles; - uint8_t *bmp_array; - struct rte_mbuf **queue_array; - uint8_t memory[0] __rte_cache_aligned; + struct rte_sched_subport *subports[0] __rte_cache_aligned; } __rte_cache_aligned; -enum rte_sched_port_array { - e_RTE_SCHED_PORT_ARRAY_SUBPORT = 0, - e_RTE_SCHED_PORT_ARRAY_PIPE, - e_RTE_SCHED_PORT_ARRAY_QUEUE, - e_RTE_SCHED_PORT_ARRAY_QUEUE_EXTRA, - e_RTE_SCHED_PORT_ARRAY_PIPE_PROFILES, - e_RTE_SCHED_PORT_ARRAY_BMP_ARRAY, - e_RTE_SCHED_PORT_ARRAY_QUEUE_ARRAY, - e_RTE_SCHED_PORT_ARRAY_TOTAL, -}; - enum rte_sched_subport_array { e_RTE_SCHED_SUBPORT_ARRAY_PIPE = 0, e_RTE_SCHED_SUBPORT_ARRAY_QUEUE, diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index ea2b07448..db1b0232f 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -246,33 +246,11 @@ struct rte_sched_port_params { /** Number of subports */ uint32_t n_subports_per_port; - /** Number of subport_pipes */ - uint32_t n_pipes_per_subport; - /** Maximum number of subport_pipes */ uint32_t n_max_pipes_per_subport; - /** Packet queue size for each traffic class. - * All the pipes within the same subport share the similar - * configuration for the queues. - */ - uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - - /** Pipe profile table. - * Every pipe is configured using one of the profiles from this table. - */ - struct rte_sched_pipe_params *pipe_profiles; - - /** Profiles in the pipe profile table */ - uint32_t n_pipe_profiles; - /** Max profiles allowed in the pipe profile table */ uint32_t n_max_pipe_profiles; - -#ifdef RTE_SCHED_RED - /** RED parameters */ - struct rte_red_params red_params[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; -#endif }; /* -- 2.21.0
This patchset refactors the dpdk qos sched library to allow subport level configuration flexibility of the pipe nodes. Currently, all parameters for the pipe nodes (subscribers) configuration are part of the port level structure which forces all groups of subscribers (pipes) in different subports to have similar configurations in terms of their number, queue sizes, traffic-classes, etc. The new implementation moves pipe nodes configuration parameters from port level to subport level structure. This allows different subports of the same port to have different configuration for the pipe nodes, for examples- number of pipes, queue sizes, pipe profiles, etc. In order to keep the implementation complexity under control, all pipes within the same subport share the same configuration for queue sizes. v2: - fix qsize parsing in sample application - fix checkpatch warnings Jasvinder Singh (15): sched: add pipe config params to subport struct sched: modify internal structs for config flexibility sched: remove pipe params config from port level shced: add pipe config to subport level sched: modify pipe functions for config flexibility sched: modify pkt enqueue for config flexibility sched: update memory compute to support flexiblity sched: update grinder functions for config flexibility sched: update pkt dequeue for flexible config sched: update queue stats read for config flexibility test/sched: modify tests for subport config flexibility net/softnic: add subport config flexibility to TM ip_pipeline: add subport config flexibility to TM examples/qos_sched: add subport configuration flexibility sched: remove redundant code app/test/test_sched.c | 35 +- doc/guides/rel_notes/release_19_11.rst | 6 +- drivers/net/softnic/rte_eth_softnic_tm.c | 51 +- examples/ip_pipeline/cli.c | 71 +- examples/ip_pipeline/tmgr.c | 23 +- examples/ip_pipeline/tmgr.h | 7 +- examples/qos_sched/app_thread.c | 4 +- examples/qos_sched/cfg_file.c | 229 ++-- examples/qos_sched/init.c | 54 +- examples/qos_sched/main.h | 1 + examples/qos_sched/profile.cfg | 5 +- examples/qos_sched/profile_ov.cfg | 5 +- examples/qos_sched/stats.c | 36 +- lib/librte_sched/Makefile | 2 +- lib/librte_sched/meson.build | 2 +- lib/librte_sched/rte_sched.c | 1400 +++++++++++++--------- lib/librte_sched/rte_sched.h | 114 +- 17 files changed, 1183 insertions(+), 862 deletions(-) -- 2.21.0
Add pipe configuration parameters to subport level structure to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/Makefile | 2 +- lib/librte_sched/meson.build | 2 +- lib/librte_sched/rte_sched.h | 81 +++++++++++++++++++++++------------- 3 files changed, 55 insertions(+), 30 deletions(-) diff --git a/lib/librte_sched/Makefile b/lib/librte_sched/Makefile index 3d7f410e1..6e4a72d89 100644 --- a/lib/librte_sched/Makefile +++ b/lib/librte_sched/Makefile @@ -18,7 +18,7 @@ LDLIBS += -lrte_timer EXPORT_MAP := rte_sched_version.map -LIBABIVER := 3 +LIBABIVER := 4 # # all source are stored in SRCS-y diff --git a/lib/librte_sched/meson.build b/lib/librte_sched/meson.build index 59d43c6d8..9f40a2368 100644 --- a/lib/librte_sched/meson.build +++ b/lib/librte_sched/meson.build @@ -1,7 +1,7 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2017 Intel Corporation -version = 3 +version = 4 sources = files('rte_sched.c', 'rte_red.c', 'rte_approx.c') headers = files('rte_sched.h', 'rte_sched_common.h', 'rte_red.h', 'rte_approx.h') diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index eac6db274..48be702bc 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -111,7 +111,7 @@ extern "C" { #endif /* - * Subport configuration parameters. The period and credits_per_period + * Pipe configuration parameters. The period and credits_per_period * parameters are measured in bytes, with one byte meaning the time * duration associated with the transmission of one byte on the * physical medium of the output port, with pipe or pipe traffic class @@ -119,7 +119,7 @@ extern "C" { * credits_per_period divided by period. One credit represents one * byte. */ -struct rte_sched_subport_params { +struct rte_sched_pipe_params { /** Token bucket rate (measured in bytes per second) */ uint32_t tb_rate; @@ -129,32 +129,18 @@ struct rte_sched_subport_params { /** Traffic class rates (measured in bytes per second) */ uint32_t tc_rate[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - /** Enforcement period for rates (measured in milliseconds) */ + /** Enforcement period (measured in milliseconds) */ uint32_t tc_period; -}; - -/** Subport statistics */ -struct rte_sched_subport_stats { - /** Number of packets successfully written */ - uint32_t n_pkts_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - - /** Number of packets dropped */ - uint32_t n_pkts_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - /** Number of bytes successfully written for each traffic class */ - uint32_t n_bytes_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - - /** Number of bytes dropped for each traffic class */ - uint32_t n_bytes_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + /** Best-effort traffic class oversubscription weight */ + uint8_t tc_ov_weight; -#ifdef RTE_SCHED_RED - /** Number of packets dropped by red */ - uint32_t n_pkts_red_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; -#endif + /** WRR weights of best-effort traffic class queues */ + uint8_t wrr_weights[RTE_SCHED_BE_QUEUES_PER_PIPE]; }; /* - * Pipe configuration parameters. The period and credits_per_period + * Subport configuration parameters. The period and credits_per_period * parameters are measured in bytes, with one byte meaning the time * duration associated with the transmission of one byte on the * physical medium of the output port, with pipe or pipe traffic class @@ -162,7 +148,7 @@ struct rte_sched_subport_stats { * credits_per_period divided by period. One credit represents one * byte. */ -struct rte_sched_pipe_params { +struct rte_sched_subport_params { /** Token bucket rate (measured in bytes per second) */ uint32_t tb_rate; @@ -172,14 +158,50 @@ struct rte_sched_pipe_params { /** Traffic class rates (measured in bytes per second) */ uint32_t tc_rate[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - /** Enforcement period (measured in milliseconds) */ + /** Enforcement period for rates (measured in milliseconds) */ uint32_t tc_period; - /** Best-effort traffic class oversubscription weight */ - uint8_t tc_ov_weight; + /** Number of subport_pipes */ + uint32_t n_pipes_per_subport; - /** WRR weights of best-effort traffic class queues */ - uint8_t wrr_weights[RTE_SCHED_BE_QUEUES_PER_PIPE]; + /** Packet queue size for each traffic class. + * All the pipes within the same subport share the similar + * configuration for the queues. + */ + uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + + /** Pipe profile table. + * Every pipe is configured using one of the profiles from this table. + */ + struct rte_sched_pipe_params *pipe_profiles; + + /** Profiles in the pipe profile table */ + uint32_t n_pipe_profiles; + +#ifdef RTE_SCHED_RED + /** RED parameters */ + struct rte_red_params red_params[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; +#endif +}; + +/** Subport statistics */ +struct rte_sched_subport_stats { + /** Number of packets successfully written */ + uint32_t n_pkts_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + + /** Number of packets dropped */ + uint32_t n_pkts_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + + /** Number of bytes successfully written for each traffic class */ + uint32_t n_bytes_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + + /** Number of bytes dropped for each traffic class */ + uint32_t n_bytes_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + +#ifdef RTE_SCHED_RED + /** Number of packets dropped by red */ + uint32_t n_pkts_red_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; +#endif }; /** Queue statistics */ @@ -227,6 +249,9 @@ struct rte_sched_port_params { /** Number of subport_pipes */ uint32_t n_pipes_per_subport; + /** Maximum number of subport_pipes */ + uint32_t n_max_pipes_per_subport; + /** Packet queue size for each traffic class. * All the pipes within the same subport share the similar * configuration for the queues. -- 2.21.0
Update internal structures related to port and subport to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 106 ++++++++++++++++++++++++++--------- 1 file changed, 79 insertions(+), 27 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index d8ab21d64..6a9990e5e 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -47,33 +47,6 @@ */ #define RTE_SCHED_TIME_SHIFT 8 -struct rte_sched_subport { - /* Token bucket (TB) */ - uint64_t tb_time; /* time of last update */ - uint32_t tb_period; - uint32_t tb_credits_per_period; - uint32_t tb_size; - uint32_t tb_credits; - - /* Traffic classes (TCs) */ - uint64_t tc_time; /* time of next update */ - uint32_t tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - uint32_t tc_credits[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - uint32_t tc_period; - - /* TC oversubscription */ - uint32_t tc_ov_wm; - uint32_t tc_ov_wm_min; - uint32_t tc_ov_wm_max; - uint8_t tc_ov_period_id; - uint8_t tc_ov; - uint32_t tc_ov_n; - double tc_ov_rate; - - /* Statistics */ - struct rte_sched_subport_stats stats; -}; - struct rte_sched_pipe_profile { /* Token bucket (TB) */ uint32_t tb_period; @@ -166,10 +139,77 @@ struct rte_sched_grinder { uint8_t wrr_cost[RTE_SCHED_BE_QUEUES_PER_PIPE]; }; +struct rte_sched_subport { + /* Token bucket (TB) */ + uint64_t tb_time; /* time of last update */ + uint32_t tb_period; + uint32_t tb_credits_per_period; + uint32_t tb_size; + uint32_t tb_credits; + + /* Traffic classes (TCs) */ + uint64_t tc_time; /* time of next update */ + uint32_t tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + uint32_t tc_credits[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + uint32_t tc_period; + + /* TC oversubscription */ + uint32_t tc_ov_wm; + uint32_t tc_ov_wm_min; + uint32_t tc_ov_wm_max; + uint8_t tc_ov_period_id; + uint8_t tc_ov; + uint32_t tc_ov_n; + double tc_ov_rate; + + /* Statistics */ + struct rte_sched_subport_stats stats; + + /* Subport pipes */ + uint32_t n_pipes_per_subport; + uint32_t n_pipe_profiles; + + /* Pipe best-effort TC rate */ + uint32_t pipe_tc_be_rate_max; + + /* Pipe queues size */ + uint16_t qsize[RTE_SCHED_QUEUES_PER_PIPE]; + +#ifdef RTE_SCHED_RED + struct rte_red_config red_config[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; +#endif + + /* Scheduling loop detection */ + uint32_t pipe_loop; + uint32_t pipe_exhaustion; + + /* Bitmap */ + struct rte_bitmap *bmp; + uint32_t grinder_base_bmp_pos[RTE_SCHED_PORT_N_GRINDERS] __rte_aligned_16; + + /* Grinders */ + struct rte_sched_grinder grinder[RTE_SCHED_PORT_N_GRINDERS]; + uint32_t busy_grinders; + + /* Queue base calculation */ + uint32_t qsize_add[RTE_SCHED_QUEUES_PER_PIPE]; + uint32_t qsize_sum; + + struct rte_sched_pipe *pipe; + struct rte_sched_queue *queue; + struct rte_sched_queue_extra *queue_extra; + struct rte_sched_pipe_profile *pipe_profiles; + uint8_t *bmp_array; + struct rte_mbuf **queue_array; + uint8_t memory[0] __rte_cache_aligned; +} __rte_cache_aligned; + struct rte_sched_port { /* User parameters */ uint32_t n_subports_per_port; uint32_t n_pipes_per_subport; + uint32_t n_max_pipes_per_subport; + uint32_t n_max_pipes_per_subport_log2; uint32_t n_pipes_per_subport_log2; uint16_t pipe_queue[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; uint8_t pipe_tc[RTE_SCHED_QUEUES_PER_PIPE]; @@ -177,6 +217,7 @@ struct rte_sched_port { uint32_t rate; uint32_t mtu; uint32_t frame_overhead; + int socket; uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; uint32_t n_pipe_profiles; uint32_t n_max_pipe_profiles; @@ -210,6 +251,7 @@ struct rte_sched_port { uint32_t qsize_sum; /* Large data structures */ + struct rte_sched_subport *subports[0]; struct rte_sched_subport *subport; struct rte_sched_pipe *pipe; struct rte_sched_queue *queue; @@ -231,6 +273,16 @@ enum rte_sched_port_array { e_RTE_SCHED_PORT_ARRAY_TOTAL, }; +enum rte_sched_subport_array { + e_RTE_SCHED_SUBPORT_ARRAY_PIPE = 0, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_EXTRA, + e_RTE_SCHED_SUBPORT_ARRAY_PIPE_PROFILES, + e_RTE_SCHED_SUBPORT_ARRAY_BMP_ARRAY, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_ARRAY, + e_RTE_SCHED_SUBPORT_ARRAY_TOTAL, +}; + #ifdef RTE_SCHED_COLLECT_STATS static inline uint32_t -- 2.21.0
Remove pipes configuration from the port level to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 266 +++++++++++------------------------ 1 file changed, 81 insertions(+), 185 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 6a9990e5e..db8b0485a 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -293,6 +293,31 @@ rte_sched_port_queues_per_subport(struct rte_sched_port *port) #endif +static inline uint32_t +rte_sched_subport_pipe_queues(struct rte_sched_subport *subport) +{ + return RTE_SCHED_QUEUES_PER_PIPE * subport->n_pipes_per_subport; +} + +static inline struct rte_mbuf ** +rte_sched_subport_pipe_qbase(struct rte_sched_subport *subport, uint32_t qindex) +{ + uint32_t pindex = qindex >> 4; + uint32_t qpos = qindex & (RTE_SCHED_QUEUES_PER_PIPE - 1); + + return (subport->queue_array + pindex * + subport->qsize_sum + subport->qsize_add[qpos]); +} + +static inline uint16_t +rte_sched_subport_pipe_qsize(struct rte_sched_port *port, +struct rte_sched_subport *subport, uint32_t qindex) +{ + uint32_t tc = port->pipe_tc[qindex & (RTE_SCHED_QUEUES_PER_PIPE - 1)]; + + return subport->qsize[tc]; +} + static inline uint32_t rte_sched_port_queues_per_port(struct rte_sched_port *port) { @@ -416,8 +441,6 @@ pipe_profile_check(struct rte_sched_pipe_params *params, 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__); @@ -454,49 +477,21 @@ rte_sched_port_check_params(struct rte_sched_port_params *params) 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)) { + /* n_max_pipes_per_subport: non-zero, power of 2 */ + if (params->n_max_pipes_per_subport == 0 || + !rte_is_power_of_2(params->n_max_pipes_per_subport)) { RTE_LOG(ERR, SCHED, - "%s: Incorrect value for pipes number\n", __func__); + "%s: Incorrect value for maximum pipes number\n", __func__); return -EINVAL; } - /* qsize: if non-zero, power of 2, - * no bigger than 32K (due to 16-bit read/write pointers) - */ - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - uint16_t qsize = params->qsize[i]; - - if ((qsize != 0 && !rte_is_power_of_2(qsize)) || - ((i == RTE_SCHED_TRAFFIC_CLASS_BE) && (qsize == 0))) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tc rate\n", __func__); - return -EINVAL; - } - } - - /* pipe_profiles and n_pipe_profiles */ - if (params->pipe_profiles == NULL || - params->n_pipe_profiles == 0 || - params->n_pipe_profiles > params->n_max_pipe_profiles) { + /* n_max_pipe_profiles: non-zero */ + if (params->n_max_pipe_profiles == 0) { RTE_LOG(ERR, SCHED, - "%s: Incorrect value for number of pipe profiles\n", __func__); + "%s: Incorrect value for maximum pipe profiles\n", __func__); return -EINVAL; } - for (i = 0; i < params->n_pipe_profiles; i++) { - struct rte_sched_pipe_params *p = params->pipe_profiles + i; - int status; - - status = pipe_profile_check(p, params->rate, ¶ms->qsize[0]); - if (status != 0) { - RTE_LOG(ERR, SCHED, - "%s: Pipe profile check failed(%d)\n", __func__, status); - return -EINVAL; - } - } - return 0; } @@ -584,32 +579,6 @@ rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params) return size0 + size1; } -static void -rte_sched_port_config_qsize(struct rte_sched_port *port) -{ - uint32_t i; - - port->qsize_add[0] = 0; - - /* Strict prority traffic class */ - for (i = 1; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - port->qsize_add[i] = port->qsize_add[i-1] + port->qsize[i-1]; - - /* Best-effort traffic class */ - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 1] = - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE] + - port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 2] = - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 1] + - port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 3] = - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 2] + - port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; - - port->qsize_sum = port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 3] + - port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; -} - static void rte_sched_port_log_pipe_profile(struct rte_sched_port *port, uint32_t i) { @@ -719,56 +688,42 @@ rte_sched_pipe_profile_convert(struct rte_sched_port *port, dst->wrr_cost[3] = (uint8_t) wrr_cost[3]; } -static void -rte_sched_port_config_pipe_profile_table(struct rte_sched_port *port, - struct rte_sched_port_params *params) -{ - uint32_t i; - - for (i = 0; i < port->n_pipe_profiles; i++) { - struct rte_sched_pipe_params *src = params->pipe_profiles + i; - struct rte_sched_pipe_profile *dst = port->pipe_profiles + i; - - rte_sched_pipe_profile_convert(port, src, dst, params->rate); - rte_sched_port_log_pipe_profile(port, i); - } - - port->pipe_tc_be_rate_max = 0; - for (i = 0; i < port->n_pipe_profiles; i++) { - struct rte_sched_pipe_params *src = params->pipe_profiles + i; - uint32_t pipe_tc_be_rate = src->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; - - if (port->pipe_tc_be_rate_max < pipe_tc_be_rate) - port->pipe_tc_be_rate_max = pipe_tc_be_rate; - } -} - struct rte_sched_port * rte_sched_port_config(struct rte_sched_port_params *params) { struct rte_sched_port *port = NULL; - uint32_t mem_size, bmp_mem_size, n_queues_per_port, i, j, cycles_per_byte; + uint32_t size0, size1; + uint32_t cycles_per_byte; + uint32_t i, j; + int status; - /* Check user parameters. Determine the amount of memory to allocate */ - mem_size = rte_sched_port_get_memory_footprint(params); - if (mem_size == 0) + status = rte_sched_port_check_params(params); + if (status != 0) { + RTE_LOG(ERR, SCHED, + "%s: Port scheduler params check failed (%d)\n", + __func__, status); return NULL; + } + + size0 = sizeof(struct rte_sched_port); + size1 = params->n_subports_per_port * sizeof(struct rte_sched_subport *); /* Allocate memory to store the data structures */ - port = rte_zmalloc_socket("qos_params", mem_size, RTE_CACHE_LINE_SIZE, + port = rte_zmalloc_socket("qos_params", size0 + size1, RTE_CACHE_LINE_SIZE, params->socket); - if (port == NULL) - return NULL; + if (port == NULL) { + RTE_LOG(ERR, SCHED, "%s: Memory allocation fails\n", __func__); - /* compile time checks */ - RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS == 0); - RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS & (RTE_SCHED_PORT_N_GRINDERS - 1)); + return NULL; + } /* User parameters */ port->n_subports_per_port = params->n_subports_per_port; - port->n_pipes_per_subport = params->n_pipes_per_subport; - port->n_pipes_per_subport_log2 = - __builtin_ctz(params->n_pipes_per_subport); + port->n_max_pipes_per_subport = params->n_max_pipes_per_subport; + port->n_max_pipes_per_subport_log2 = + __builtin_ctz(params->n_max_pipes_per_subport); + port->n_max_pipe_profiles = params->n_max_pipe_profiles; + port->socket = params->socket; for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) port->pipe_queue[i] = i; @@ -789,32 +744,6 @@ rte_sched_port_config(struct rte_sched_port_params *params) port->rate = params->rate; port->mtu = params->mtu + params->frame_overhead; port->frame_overhead = params->frame_overhead; - memcpy(port->qsize, params->qsize, sizeof(params->qsize)); - port->n_pipe_profiles = params->n_pipe_profiles; - port->n_max_pipe_profiles = params->n_max_pipe_profiles; - -#ifdef RTE_SCHED_RED - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - uint32_t j; - - for (j = 0; j < RTE_COLORS; j++) { - /* if min/max are both zero, then RED is disabled */ - if ((params->red_params[i][j].min_th | - params->red_params[i][j].max_th) == 0) { - continue; - } - - if (rte_red_config_init(&port->red_config[i][j], - params->red_params[i][j].wq_log2, - params->red_params[i][j].min_th, - params->red_params[i][j].max_th, - params->red_params[i][j].maxp_inv) != 0) { - rte_free(port); - return NULL; - } - } - } -#endif /* Timing */ port->time_cpu_cycles = rte_get_tsc_cycles(); @@ -825,79 +754,32 @@ rte_sched_port_config(struct rte_sched_port_params *params) / params->rate; port->inv_cycles_per_byte = rte_reciprocal_value(cycles_per_byte); - /* Scheduling loop detection */ - port->pipe_loop = RTE_SCHED_PIPE_INVALID; - port->pipe_exhaustion = 0; - /* Grinders */ - port->busy_grinders = 0; port->pkts_out = NULL; port->n_pkts_out = 0; - /* Queue base calculation */ - rte_sched_port_config_qsize(port); - - /* Large data structures */ - port->subport = (struct rte_sched_subport *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_SUBPORT)); - port->pipe = (struct rte_sched_pipe *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_PIPE)); - port->queue = (struct rte_sched_queue *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_QUEUE)); - port->queue_extra = (struct rte_sched_queue_extra *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_QUEUE_EXTRA)); - port->pipe_profiles = (struct rte_sched_pipe_profile *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_PIPE_PROFILES)); - port->bmp_array = port->memory - + rte_sched_port_get_array_base(params, e_RTE_SCHED_PORT_ARRAY_BMP_ARRAY); - port->queue_array = (struct rte_mbuf **) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_QUEUE_ARRAY)); - - /* Pipe profile table */ - rte_sched_port_config_pipe_profile_table(port, params); - - /* Bitmap */ - n_queues_per_port = rte_sched_port_queues_per_port(port); - bmp_mem_size = rte_bitmap_get_memory_footprint(n_queues_per_port); - port->bmp = rte_bitmap_init(n_queues_per_port, port->bmp_array, - bmp_mem_size); - if (port->bmp == NULL) { - RTE_LOG(ERR, SCHED, "Bitmap init error\n"); - rte_free(port); - return NULL; - } - - for (i = 0; i < RTE_SCHED_PORT_N_GRINDERS; i++) - port->grinder_base_bmp_pos[i] = RTE_SCHED_PIPE_INVALID; - - return port; } -void -rte_sched_port_free(struct rte_sched_port *port) +static inline void +rte_sched_subport_free(struct rte_sched_port *port, + struct rte_sched_subport *subport) { + uint32_t n_subport_pipe_queues; uint32_t qindex; - uint32_t n_queues_per_port; - /* Check user parameters */ - if (port == NULL) + if (subport == NULL) return; - n_queues_per_port = rte_sched_port_queues_per_port(port); + n_subport_pipe_queues = rte_sched_subport_pipe_queues(subport); /* Free enqueued mbufs */ - for (qindex = 0; qindex < n_queues_per_port; qindex++) { - struct rte_mbuf **mbufs = rte_sched_port_qbase(port, qindex); - uint16_t qsize = rte_sched_port_qsize(port, qindex); + for (qindex = 0; qindex < n_subport_pipe_queues; qindex++) { + struct rte_mbuf **mbufs = + rte_sched_subport_pipe_qbase(subport, qindex); + uint16_t qsize = rte_sched_subport_pipe_qsize(port, subport, qindex); if (qsize != 0) { - struct rte_sched_queue *queue = port->queue + qindex; + struct rte_sched_queue *queue = subport->queue + qindex; uint16_t qr = queue->qr & (qsize - 1); uint16_t qw = queue->qw & (qsize - 1); @@ -906,7 +788,21 @@ rte_sched_port_free(struct rte_sched_port *port) } } - rte_bitmap_free(port->bmp); + rte_bitmap_free(subport->bmp); +} + +void +rte_sched_port_free(struct rte_sched_port *port) +{ + uint32_t i; + + /* Check user parameters */ + if (port == NULL) + return; + + for (i = 0; i < port->n_subports_per_port; i++) + rte_sched_subport_free(port, port->subports[i]); + rte_free(port); } -- 2.21.0
Add pipes configuration from the port level to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 390 ++++++++++++++++++++++++++++++----- 1 file changed, 334 insertions(+), 56 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index db8b0485a..1491cb695 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -559,24 +559,92 @@ rte_sched_port_get_array_base(struct rte_sched_port_params *params, enum rte_sch return base; } -uint32_t -rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params) +static uint32_t +rte_sched_subport_get_array_base(struct rte_sched_subport_params *params, + uint32_t n_max_pipe_profiles, + enum rte_sched_subport_array array) { - uint32_t size0, size1; - int status; + uint32_t n_pipes_per_subport = params->n_pipes_per_subport; + uint32_t n_subport_pipe_queues = + RTE_SCHED_QUEUES_PER_PIPE * n_pipes_per_subport; - status = rte_sched_port_check_params(params); - if (status != 0) { - RTE_LOG(NOTICE, SCHED, - "Port scheduler params check failed (%d)\n", status); + uint32_t size_pipe = n_pipes_per_subport * sizeof(struct rte_sched_pipe); + uint32_t size_queue = + n_subport_pipe_queues * sizeof(struct rte_sched_queue); + uint32_t size_queue_extra + = n_subport_pipe_queues * sizeof(struct rte_sched_queue_extra); + uint32_t size_pipe_profiles = n_max_pipe_profiles * + sizeof(struct rte_sched_pipe_profile); + uint32_t size_bmp_array = + rte_bitmap_get_memory_footprint(n_subport_pipe_queues); + uint32_t size_per_pipe_queue_array, size_queue_array; - return 0; + uint32_t base, i; + + size_per_pipe_queue_array = 0; + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + if (i < RTE_SCHED_TRAFFIC_CLASS_BE) + size_per_pipe_queue_array += + params->qsize[i] * sizeof(struct rte_mbuf *); + else + size_per_pipe_queue_array += RTE_SCHED_MAX_QUEUES_PER_TC * + params->qsize[i] * sizeof(struct rte_mbuf *); } + size_queue_array = n_pipes_per_subport * size_per_pipe_queue_array; - size0 = sizeof(struct rte_sched_port); - size1 = rte_sched_port_get_array_base(params, e_RTE_SCHED_PORT_ARRAY_TOTAL); + base = 0; - return size0 + size1; + if (array == e_RTE_SCHED_SUBPORT_ARRAY_PIPE) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_pipe); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_QUEUE) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_queue); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_EXTRA) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_queue_extra); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_PIPE_PROFILES) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_pipe_profiles); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_BMP_ARRAY) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_bmp_array); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_ARRAY) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_queue_array); + + return base; +} + +static void +rte_sched_subport_config_qsize(struct rte_sched_subport *subport) +{ + uint32_t i; + + subport->qsize_add[0] = 0; + + /* Strict prority traffic class */ + for (i = 1; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) + subport->qsize_add[i] = subport->qsize_add[i-1] + subport->qsize[i-1]; + + /* Best-effort traffic class */ + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 1] = + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE] + + subport->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 2] = + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 1] + + subport->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 3] = + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 2] + + subport->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; + + subport->qsize_sum = subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 3] + + subport->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; } static void @@ -688,6 +756,126 @@ rte_sched_pipe_profile_convert(struct rte_sched_port *port, dst->wrr_cost[3] = (uint8_t) wrr_cost[3]; } +static int +rte_sched_subport_check_params(struct rte_sched_subport_params *params, + uint32_t n_max_pipes_per_subport, + uint32_t n_max_pipe_profiles, + uint32_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; + } + + /* qsize: if non-zero, power of 2, + * no bigger than 32K (due to 16-bit read/write pointers) + */ + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + uint16_t qsize = params->qsize[i]; + + if (qsize != 0 && !rte_is_power_of_2(qsize)) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for qsize\n", __func__); + return -EINVAL; + } + } + + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + uint32_t tc_rate = params->tc_rate[i]; + uint16_t qsize = params->qsize[i]; + + if ((qsize == 0 && tc_rate != 0) || + (qsize != 0 && tc_rate == 0) || + (tc_rate > params->tb_rate)) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for tc rate\n", __func__); + return -EINVAL; + } + } + + if (params->qsize[RTE_SCHED_TRAFFIC_CLASS_BE] == 0 || + params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE] == 0) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect qsize or 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; + } + + /* n_pipes_per_subport: non-zero, power of 2 */ + if (params->n_pipes_per_subport == 0 || + params->n_pipes_per_subport > n_max_pipes_per_subport || + !rte_is_power_of_2(params->n_pipes_per_subport)) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for pipes number\n", __func__); + return -EINVAL; + } + + /* pipe_profiles and n_pipe_profiles */ + if (params->pipe_profiles == NULL || + params->n_pipe_profiles == 0 || + params->n_pipe_profiles > n_max_pipe_profiles) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for pipe profiles\n", __func__); + return -EINVAL; + } + + for (i = 0; i < params->n_pipe_profiles; i++) { + struct rte_sched_pipe_params *p = params->pipe_profiles + i; + int status; + + status = pipe_profile_check(p, rate, ¶ms->qsize[0]); + if (status != 0) { + RTE_LOG(ERR, SCHED, + "%s: Pipe profile check failed(%d)\n", __func__, status); + return -EINVAL; + } + } + + return 0; +} + +uint32_t +rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params) +{ + uint32_t size0, size1; + int status; + + status = rte_sched_port_check_params(params); + if (status != 0) { + RTE_LOG(NOTICE, SCHED, + "Port scheduler params check failed (%d)\n", status); + + return 0; + } + + size0 = sizeof(struct rte_sched_port); + size1 = rte_sched_port_get_array_base(params, + e_RTE_SCHED_PORT_ARRAY_TOTAL); + + return size0 + size1; +} + struct rte_sched_port * rte_sched_port_config(struct rte_sched_port_params *params) { @@ -809,7 +997,7 @@ rte_sched_port_free(struct rte_sched_port *port) static void rte_sched_port_log_subport_config(struct rte_sched_port *port, uint32_t i) { - struct rte_sched_subport *s = port->subport + i; + struct rte_sched_subport *s = port->subports[i]; RTE_LOG(DEBUG, SCHED, "Low level config for subport %u:\n" " Token bucket: period = %u, credits per period = %u, size = %u\n" @@ -844,72 +1032,80 @@ rte_sched_port_log_subport_config(struct rte_sched_port *port, uint32_t i) s->tc_ov_wm_max); } +static void +rte_sched_free_memory(struct rte_sched_port *port, uint32_t n_subports) +{ + uint32_t i; + + for (i = 0; i < n_subports; i++) { + struct rte_sched_subport *subport = port->subports[i]; + + rte_sched_subport_free(port, subport); + } + + rte_free(port); +} + int rte_sched_subport_config(struct rte_sched_port *port, uint32_t subport_id, struct rte_sched_subport_params *params) { - struct rte_sched_subport *s; - uint32_t i; + struct rte_sched_subport *s = NULL; + uint32_t n_subports = subport_id; + uint32_t n_subport_pipe_queues, i; + uint32_t size0, size1, bmp_mem_size; + int status; /* Check user parameters */ if (port == NULL) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for parameter port\n", __func__); - return -EINVAL; + return 0; } if (subport_id >= port->n_subports_per_port) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for subport id\n", __func__); - return -EINVAL; - } - if (params == NULL) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for parameter params\n", __func__); + rte_sched_free_memory(port, n_subports); return -EINVAL; } - if (params->tb_rate == 0 || params->tb_rate > port->rate) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tb rate\n", __func__); - return -EINVAL; - } + status = rte_sched_subport_check_params(params, + port->n_max_pipes_per_subport, + port->n_max_pipe_profiles, + port->rate); + if (status != 0) { + RTE_LOG(NOTICE, SCHED, + "%s: Port scheduler params check failed (%d)\n", + __func__, status); - if (params->tb_size == 0) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tb size\n", __func__); + rte_sched_free_memory(port, n_subports); return -EINVAL; } - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - uint32_t tc_rate = params->tc_rate[i]; - uint16_t qsize = port->qsize[i]; + /* Determine the amount of memory to allocate */ + size0 = sizeof(struct rte_sched_subport); + size1 = rte_sched_subport_get_array_base(params, + port->n_max_pipe_profiles, + e_RTE_SCHED_SUBPORT_ARRAY_TOTAL); - if ((qsize == 0 && tc_rate != 0) || - (qsize != 0 && tc_rate == 0) || - (tc_rate > params->tb_rate)) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tc rate\n", __func__); - return -EINVAL; - } - } - - if (port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE] == 0 || - params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE] == 0) { + /* Allocate memory to store the data structures */ + s = rte_zmalloc_socket("subport_params", size0 + size1, + RTE_CACHE_LINE_SIZE, port->socket); + if (s == NULL) { RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tc rate(best effort)\n", __func__); - return -EINVAL; - } + "%s: Memory allocation fails\n", __func__); - if (params->tc_period == 0) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tc period\n", __func__); - return -EINVAL; + rte_sched_free_memory(port, n_subports); + return -ENOMEM; } - s = port->subport + subport_id; + n_subports++; + + /* Port */ + port->subports[subport_id] = s; /* Token Bucket (TB) */ if (params->tb_rate == port->rate) { @@ -929,26 +1125,108 @@ rte_sched_subport_config(struct rte_sched_port *port, /* Traffic Classes (TCs) */ s->tc_period = rte_sched_time_ms_to_bytes(params->tc_period, port->rate); for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - if (port->qsize[i]) + if (params->qsize[i]) s->tc_credits_per_period[i] = rte_sched_time_ms_to_bytes(params->tc_period, - params->tc_rate[i]); - + params->tc_rate[i]); } s->tc_time = port->time + s->tc_period; for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - if (port->qsize[i]) + if (params->qsize[i]) s->tc_credits[i] = s->tc_credits_per_period[i]; + /* compile time checks */ + RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS == 0); + RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS & + (RTE_SCHED_PORT_N_GRINDERS - 1)); + + /* User parameters */ + s->n_pipes_per_subport = params->n_pipes_per_subport; + memcpy(s->qsize, params->qsize, sizeof(params->qsize)); + s->n_pipe_profiles = params->n_pipe_profiles; + +#ifdef RTE_SCHED_RED + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + uint32_t j; + + for (j = 0; j < RTE_COLORS; j++) { + /* if min/max are both zero, then RED is disabled */ + if ((params->red_params[i][j].min_th | + params->red_params[i][j].max_th) == 0) { + continue; + } + + if (rte_red_config_init(&s->red_config[i][j], + params->red_params[i][j].wq_log2, + params->red_params[i][j].min_th, + params->red_params[i][j].max_th, + params->red_params[i][j].maxp_inv) != 0) { + rte_sched_free_memory(port, n_subports); + + RTE_LOG(NOTICE, SCHED, + "%s: RED configuration init fails\n", __func__); + return -EINVAL; + } + } + } +#endif + + /* Scheduling loop detection */ + s->pipe_loop = RTE_SCHED_PIPE_INVALID; + s->pipe_exhaustion = 0; + + /* Grinders */ + s->busy_grinders = 0; + + /* Queue base calculation */ + rte_sched_subport_config_qsize(s); + + /* Large data structures */ + s->pipe = (struct rte_sched_pipe *) + (s->memory + rte_sched_subport_get_array_base(params, + port->n_max_pipe_profiles, e_RTE_SCHED_SUBPORT_ARRAY_PIPE)); + s->queue = (struct rte_sched_queue *) + (s->memory + rte_sched_subport_get_array_base(params, + port->n_max_pipe_profiles, e_RTE_SCHED_SUBPORT_ARRAY_QUEUE)); + s->queue_extra = (struct rte_sched_queue_extra *) + (s->memory + rte_sched_subport_get_array_base(params, + port->n_max_pipe_profiles, e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_EXTRA)); + s->pipe_profiles = (struct rte_sched_pipe_profile *) + (s->memory + rte_sched_subport_get_array_base(params, + port->n_max_pipe_profiles, e_RTE_SCHED_SUBPORT_ARRAY_PIPE_PROFILES)); + s->bmp_array = s->memory + rte_sched_subport_get_array_base(params, + port->n_max_pipe_profiles, e_RTE_SCHED_SUBPORT_ARRAY_BMP_ARRAY); + s->queue_array = (struct rte_mbuf **) + (s->memory + rte_sched_subport_get_array_base(params, + port->n_max_pipe_profiles, e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_ARRAY)); + + /* Bitmap */ + n_subport_pipe_queues = rte_sched_subport_pipe_queues(s); + bmp_mem_size = rte_bitmap_get_memory_footprint(n_subport_pipe_queues); + s->bmp = rte_bitmap_init(n_subport_pipe_queues, s->bmp_array, + bmp_mem_size); + if (s->bmp == NULL) { + RTE_LOG(ERR, SCHED, + "%s: Subport bitmap init error\n", __func__); + + rte_sched_free_memory(port, n_subports); + return -EINVAL; + } + + for (i = 0; i < RTE_SCHED_PORT_N_GRINDERS; i++) + s->grinder_base_bmp_pos[i] = RTE_SCHED_PIPE_INVALID; + +#ifdef RTE_SCHED_SUBPORT_TC_OV /* TC oversubscription */ s->tc_ov_wm_min = port->mtu; s->tc_ov_wm_max = rte_sched_time_ms_to_bytes(params->tc_period, - port->pipe_tc_be_rate_max); + s->pipe_tc_be_rate_max); s->tc_ov_wm = s->tc_ov_wm_max; s->tc_ov_period_id = 0; s->tc_ov = 0; s->tc_ov_n = 0; s->tc_ov_rate = 0; +#endif rte_sched_port_log_subport_config(port, subport_id); -- 2.21.0
Modify pipe level functions to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 95 +++++++++++++++++++++++++----------- lib/librte_sched/rte_sched.h | 5 +- 2 files changed, 70 insertions(+), 30 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 1491cb695..6bafbd8fe 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -648,9 +648,9 @@ rte_sched_subport_config_qsize(struct rte_sched_subport *subport) } static void -rte_sched_port_log_pipe_profile(struct rte_sched_port *port, uint32_t i) +rte_sched_port_log_pipe_profile(struct rte_sched_subport *subport, uint32_t i) { - struct rte_sched_pipe_profile *p = port->pipe_profiles + i; + struct rte_sched_pipe_profile *p = subport->pipe_profiles + i; RTE_LOG(DEBUG, SCHED, "Low level config for pipe profile %u:\n" " Token bucket: period = %u, credits per period = %u, size = %u\n" @@ -699,7 +699,7 @@ rte_sched_time_ms_to_bytes(uint32_t time_ms, uint32_t rate) } static void -rte_sched_pipe_profile_convert(struct rte_sched_port *port, +rte_sched_pipe_profile_convert(struct rte_sched_subport *subport, struct rte_sched_pipe_params *src, struct rte_sched_pipe_profile *dst, uint32_t rate) @@ -728,7 +728,7 @@ rte_sched_pipe_profile_convert(struct rte_sched_port *port, rate); for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - if (port->qsize[i]) + if (subport->qsize[i]) dst->tc_credits_per_period[i] = rte_sched_time_ms_to_bytes(src->tc_period, src->tc_rate[i]); @@ -756,6 +756,30 @@ rte_sched_pipe_profile_convert(struct rte_sched_port *port, dst->wrr_cost[3] = (uint8_t) wrr_cost[3]; } +static void +rte_sched_subport_config_pipe_profile_table(struct rte_sched_subport *subport, + struct rte_sched_subport_params *params, uint32_t rate) +{ + uint32_t i; + + for (i = 0; i < subport->n_pipe_profiles; i++) { + struct rte_sched_pipe_params *src = params->pipe_profiles + i; + struct rte_sched_pipe_profile *dst = subport->pipe_profiles + i; + + rte_sched_pipe_profile_convert(subport, src, dst, rate); + rte_sched_port_log_pipe_profile(subport, i); + } + + subport->pipe_tc_be_rate_max = 0; + for (i = 0; i < subport->n_pipe_profiles; i++) { + struct rte_sched_pipe_params *src = params->pipe_profiles + i; + uint32_t pipe_tc_be_rate = src->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; + + if (subport->pipe_tc_be_rate_max < pipe_tc_be_rate) + subport->pipe_tc_be_rate_max = pipe_tc_be_rate; + } +} + static int rte_sched_subport_check_params(struct rte_sched_subport_params *params, uint32_t n_max_pipes_per_subport, @@ -1200,6 +1224,9 @@ rte_sched_subport_config(struct rte_sched_port *port, (s->memory + rte_sched_subport_get_array_base(params, port->n_max_pipe_profiles, e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_ARRAY)); + /* Pipe profile table */ + rte_sched_subport_config_pipe_profile_table(s, params, port->rate); + /* Bitmap */ n_subport_pipe_queues = rte_sched_subport_pipe_queues(s); bmp_mem_size = rte_bitmap_get_memory_footprint(n_subport_pipe_queues); @@ -1242,6 +1269,7 @@ rte_sched_pipe_config(struct rte_sched_port *port, struct rte_sched_subport *s; struct rte_sched_pipe *p; struct rte_sched_pipe_profile *params; + uint32_t n_subports = subport_id + 1; uint32_t deactivate, profile, i; /* Check user parameters */ @@ -1257,34 +1285,32 @@ rte_sched_pipe_config(struct rte_sched_port *port, if (subport_id >= port->n_subports_per_port) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for parameter subport id\n", __func__); + + rte_sched_free_memory(port, n_subports); return -EINVAL; } - if (pipe_id >= port->n_pipes_per_subport) { + s = port->subports[subport_id]; + if (pipe_id >= s->n_pipes_per_subport) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for parameter pipe id\n", __func__); + + rte_sched_free_memory(port, n_subports); return -EINVAL; } - if (!deactivate && profile >= port->n_pipe_profiles) { + if (!deactivate && profile >= s->n_pipe_profiles) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for parameter pipe profile\n", __func__); - return -EINVAL; - } - /* Check that subport configuration is valid */ - s = port->subport + subport_id; - if (s->tb_period == 0) { - RTE_LOG(ERR, SCHED, - "%s: Subport configuration invalid\n", __func__); + rte_sched_free_memory(port, n_subports); return -EINVAL; } - p = port->pipe + (subport_id * port->n_pipes_per_subport + pipe_id); - /* Handle the case when pipe already has a valid configuration */ + p = s->pipe + pipe_id; if (p->tb_time) { - params = port->pipe_profiles + p->profile; + params = s->pipe_profiles + p->profile; double subport_tc_be_rate = (double) s->tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASS_BE] @@ -1314,7 +1340,7 @@ rte_sched_pipe_config(struct rte_sched_port *port, /* Apply the new pipe configuration */ p->profile = profile; - params = port->pipe_profiles + p->profile; + params = s->pipe_profiles + p->profile; /* Token Bucket (TB) */ p->tb_time = port->time; @@ -1324,7 +1350,7 @@ rte_sched_pipe_config(struct rte_sched_port *port, p->tc_time = port->time + params->tc_period; for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - if (port->qsize[i]) + if (s->qsize[i]) p->tc_credits[i] = params->tc_credits_per_period[i]; { @@ -1355,9 +1381,11 @@ rte_sched_pipe_config(struct rte_sched_port *port, int rte_sched_port_pipe_profile_add(struct rte_sched_port *port, + uint32_t subport_id, struct rte_sched_pipe_params *params, uint32_t *pipe_profile_id) { + struct rte_sched_subport *s; struct rte_sched_pipe_profile *pp; uint32_t i; int status; @@ -1369,40 +1397,49 @@ rte_sched_port_pipe_profile_add(struct rte_sched_port *port, return -EINVAL; } + /* Subport id not exceeds the max limit */ + if (subport_id > port->n_subports_per_port) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for subport id\n", __func__); + return -EINVAL; + } + + s = port->subports[subport_id]; + /* Pipe profiles not exceeds the max limit */ - if (port->n_pipe_profiles >= port->n_max_pipe_profiles) { + if (s->n_pipe_profiles >= port->n_max_pipe_profiles) { RTE_LOG(ERR, SCHED, "%s: Number of pipe profiles exceeds the max limit\n", __func__); return -EINVAL; } /* Pipe params */ - status = pipe_profile_check(params, port->rate, &port->qsize[0]); + status = pipe_profile_check(params, port->rate, &s->qsize[0]); if (status != 0) { RTE_LOG(ERR, SCHED, "%s: Pipe profile check failed(%d)\n", __func__, status); return -EINVAL; } - pp = &port->pipe_profiles[port->n_pipe_profiles]; - rte_sched_pipe_profile_convert(port, params, pp, port->rate); + pp = &s->pipe_profiles[s->n_pipe_profiles]; + rte_sched_pipe_profile_convert(s, params, pp, port->rate); /* Pipe profile not exists */ - for (i = 0; i < port->n_pipe_profiles; i++) - if (memcmp(port->pipe_profiles + i, pp, sizeof(*pp)) == 0) { + for (i = 0; i < s->n_pipe_profiles; i++) + if (memcmp(s->pipe_profiles + i, pp, sizeof(*pp)) == 0) { RTE_LOG(ERR, SCHED, "%s: Pipe profile doesn't exist\n", __func__); return -EINVAL; } /* Pipe profile commit */ - *pipe_profile_id = port->n_pipe_profiles; - port->n_pipe_profiles++; + *pipe_profile_id = s->n_pipe_profiles; + s->n_pipe_profiles++; - if (port->pipe_tc_be_rate_max < params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]) - port->pipe_tc_be_rate_max = params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; + if (s->pipe_tc_be_rate_max < params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]) + s->pipe_tc_be_rate_max = params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; - rte_sched_port_log_pipe_profile(port, *pipe_profile_id); + rte_sched_port_log_pipe_profile(s, *pipe_profile_id); return 0; } diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index 48be702bc..56e9fbfa7 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -308,6 +308,8 @@ rte_sched_port_free(struct rte_sched_port *port); * * @param port * Handle to port scheduler instance + * @param subport_id + * Subport ID * @param params * Pipe profile parameters * @param pipe_profile_id @@ -318,6 +320,7 @@ rte_sched_port_free(struct rte_sched_port *port); __rte_experimental int rte_sched_port_pipe_profile_add(struct rte_sched_port *port, + uint32_t subport_id, struct rte_sched_pipe_params *params, uint32_t *pipe_profile_id); @@ -348,7 +351,7 @@ rte_sched_subport_config(struct rte_sched_port *port, * @param pipe_id * Pipe ID within subport * @param pipe_profile - * ID of port-level pre-configured pipe profile + * ID of subport-level pre-configured pipe profile * @return * 0 upon success, error code otherwise */ -- 2.21.0
Modify scheduler packet enqueue operation of the scheduler to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 278 ++++++++++++++++++++++------------- 1 file changed, 178 insertions(+), 100 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 6bafbd8fe..a5e4c45b4 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -1452,10 +1452,10 @@ rte_sched_port_qindex(struct rte_sched_port *port, 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) | - ((rte_sched_port_pipe_queue(port, traffic_class) + queue) & - (RTE_SCHED_QUEUES_PER_PIPE - 1)); + (port->n_max_pipes_per_subport_log2 + 4)) | + ((pipe & (port->subports[subport]->n_pipes_per_subport - 1)) << 4) | + ((rte_sched_port_pipe_queue(port, traffic_class) + queue) & + (RTE_SCHED_QUEUES_PER_PIPE - 1)); } void @@ -1479,8 +1479,9 @@ rte_sched_port_pkt_read_tree_path(struct rte_sched_port *port, { uint32_t queue_id = rte_mbuf_sched_queue_get(pkt); - *subport = queue_id >> (port->n_pipes_per_subport_log2 + 4); - *pipe = (queue_id >> 4) & (port->n_pipes_per_subport - 1); + *subport = queue_id >> (port->n_max_pipes_per_subport_log2 + 4); + *pipe = (queue_id >> 4) & + (port->subports[*subport]->n_pipes_per_subport - 1); *traffic_class = rte_sched_port_pipe_tc(port, queue_id); *queue = rte_sched_port_tc_queue(port, queue_id); } @@ -1524,7 +1525,7 @@ rte_sched_subport_read_stats(struct rte_sched_port *port, return -EINVAL; } - s = port->subport + subport_id; + s = port->subports[subport_id]; /* Copy subport stats and clear */ memcpy(stats, &s->stats, sizeof(struct rte_sched_subport_stats)); @@ -1597,43 +1598,50 @@ rte_sched_port_queue_is_empty(struct rte_sched_port *port, uint32_t qindex) #ifdef RTE_SCHED_COLLECT_STATS static inline void -rte_sched_port_update_subport_stats(struct rte_sched_port *port, uint32_t qindex, struct rte_mbuf *pkt) +rte_sched_port_update_subport_stats(struct rte_sched_port *port, + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt) { - struct rte_sched_subport *s = port->subport + (qindex / rte_sched_port_queues_per_subport(port)); uint32_t tc_index = rte_sched_port_pipe_tc(port, qindex); uint32_t pkt_len = pkt->pkt_len; - s->stats.n_pkts_tc[tc_index] += 1; - s->stats.n_bytes_tc[tc_index] += pkt_len; + subport->stats.n_pkts_tc[tc_index] += 1; + subport->stats.n_bytes_tc[tc_index] += pkt_len; } #ifdef RTE_SCHED_RED static inline void rte_sched_port_update_subport_stats_on_drop(struct rte_sched_port *port, - uint32_t qindex, - struct rte_mbuf *pkt, uint32_t red) + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt, + uint32_t red) #else static inline void rte_sched_port_update_subport_stats_on_drop(struct rte_sched_port *port, - uint32_t qindex, - struct rte_mbuf *pkt, __rte_unused uint32_t red) + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt, + __rte_unused uint32_t red) #endif { - struct rte_sched_subport *s = port->subport + (qindex / rte_sched_port_queues_per_subport(port)); uint32_t tc_index = rte_sched_port_pipe_tc(port, qindex); uint32_t pkt_len = pkt->pkt_len; - s->stats.n_pkts_tc_dropped[tc_index] += 1; - s->stats.n_bytes_tc_dropped[tc_index] += pkt_len; + subport->stats.n_pkts_tc_dropped[tc_index] += 1; + subport->stats.n_bytes_tc_dropped[tc_index] += pkt_len; #ifdef RTE_SCHED_RED - s->stats.n_pkts_red_dropped[tc_index] += red; + subport->stats.n_pkts_red_dropped[tc_index] += red; #endif } static inline void -rte_sched_port_update_queue_stats(struct rte_sched_port *port, uint32_t qindex, struct rte_mbuf *pkt) +rte_sched_port_update_queue_stats(struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt) { - struct rte_sched_queue_extra *qe = port->queue_extra + qindex; + struct rte_sched_queue_extra *qe = subport->queue_extra + qindex; uint32_t pkt_len = pkt->pkt_len; qe->stats.n_pkts += 1; @@ -1642,17 +1650,19 @@ rte_sched_port_update_queue_stats(struct rte_sched_port *port, uint32_t qindex, #ifdef RTE_SCHED_RED static inline void -rte_sched_port_update_queue_stats_on_drop(struct rte_sched_port *port, - uint32_t qindex, - struct rte_mbuf *pkt, uint32_t red) +rte_sched_port_update_queue_stats_on_drop(struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt, + uint32_t red) #else static inline void -rte_sched_port_update_queue_stats_on_drop(struct rte_sched_port *port, - uint32_t qindex, - struct rte_mbuf *pkt, __rte_unused uint32_t red) +rte_sched_port_update_queue_stats_on_drop(struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt, + __rte_unused uint32_t red) #endif { - struct rte_sched_queue_extra *qe = port->queue_extra + qindex; + struct rte_sched_queue_extra *qe = subport->queue_extra + qindex; uint32_t pkt_len = pkt->pkt_len; qe->stats.n_pkts_dropped += 1; @@ -1667,7 +1677,11 @@ rte_sched_port_update_queue_stats_on_drop(struct rte_sched_port *port, #ifdef RTE_SCHED_RED static inline int -rte_sched_port_red_drop(struct rte_sched_port *port, struct rte_mbuf *pkt, uint32_t qindex, uint16_t qlen) +rte_sched_port_red_drop(struct rte_sched_port *port, + struct rte_sched_subport *subport, + struct rte_mbuf *pkt, + uint32_t qindex, + uint16_t qlen) { struct rte_sched_queue_extra *qe; struct rte_red_config *red_cfg; @@ -1677,12 +1691,12 @@ rte_sched_port_red_drop(struct rte_sched_port *port, struct rte_mbuf *pkt, uint3 tc_index = rte_sched_port_pipe_tc(port, qindex); color = rte_sched_port_pkt_read_color(pkt); - red_cfg = &port->red_config[tc_index][color]; + red_cfg = &subport->red_config[tc_index][color]; if ((red_cfg->min_th | red_cfg->max_th) == 0) return 0; - qe = port->queue_extra + qindex; + qe = subport->queue_extra + qindex; red = &qe->red; return rte_red_enqueue(red_cfg, red, qlen, port->time); @@ -1699,7 +1713,14 @@ rte_sched_port_set_queue_empty_timestamp(struct rte_sched_port *port, uint32_t q #else -#define rte_sched_port_red_drop(port, pkt, qindex, qlen) 0 +static inline int rte_sched_port_red_drop(struct rte_sched_port *port __rte_unused, + struct rte_sched_subport *subport __rte_unused, + struct rte_mbuf *pkt __rte_unused, + uint32_t qindex __rte_unused, + uint16_t qlen __rte_unused) +{ + return 0; +} #define rte_sched_port_set_queue_empty_timestamp(port, qindex) @@ -1734,63 +1755,79 @@ debug_check_queue_slab(struct rte_sched_port *port, uint32_t bmp_pos, #endif /* RTE_SCHED_DEBUG */ +static inline struct rte_sched_subport * +rte_sched_port_subport(struct rte_sched_port *port, + struct rte_mbuf *pkt) +{ + uint32_t queue_id = rte_mbuf_sched_queue_get(pkt); + uint32_t subport_id = queue_id >> (port->n_max_pipes_per_subport_log2 + 4); + + return port->subports[subport_id]; +} + static inline uint32_t -rte_sched_port_enqueue_qptrs_prefetch0(struct rte_sched_port *port, - struct rte_mbuf *pkt) +rte_sched_port_enqueue_qptrs_prefetch0(struct rte_sched_subport *subport, + struct rte_mbuf *pkt, uint32_t subport_qmask) { struct rte_sched_queue *q; #ifdef RTE_SCHED_COLLECT_STATS struct rte_sched_queue_extra *qe; #endif uint32_t qindex = rte_mbuf_sched_queue_get(pkt); + uint32_t subport_queue_id = subport_qmask & qindex; - q = port->queue + qindex; + q = subport->queue + subport_queue_id; rte_prefetch0(q); #ifdef RTE_SCHED_COLLECT_STATS - qe = port->queue_extra + qindex; + qe = subport->queue_extra + subport_queue_id; rte_prefetch0(qe); #endif - return qindex; + return subport_queue_id; } static inline void rte_sched_port_enqueue_qwa_prefetch0(struct rte_sched_port *port, - uint32_t qindex, struct rte_mbuf **qbase) + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf **qbase) { struct rte_sched_queue *q; struct rte_mbuf **q_qw; uint16_t qsize; - q = port->queue + qindex; - qsize = rte_sched_port_qsize(port, qindex); + q = subport->queue + qindex; + qsize = rte_sched_subport_pipe_qsize(port, subport, qindex); q_qw = qbase + (q->qw & (qsize - 1)); rte_prefetch0(q_qw); - rte_bitmap_prefetch0(port->bmp, qindex); + rte_bitmap_prefetch0(subport->bmp, qindex); } static inline int -rte_sched_port_enqueue_qwa(struct rte_sched_port *port, uint32_t qindex, - struct rte_mbuf **qbase, struct rte_mbuf *pkt) +rte_sched_port_enqueue_qwa(struct rte_sched_port *port, + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf **qbase, + struct rte_mbuf *pkt) { struct rte_sched_queue *q; uint16_t qsize; uint16_t qlen; - q = port->queue + qindex; - qsize = rte_sched_port_qsize(port, qindex); + q = subport->queue + qindex; + qsize = rte_sched_subport_pipe_qsize(port, subport, qindex); qlen = q->qw - q->qr; /* Drop the packet (and update drop stats) when queue is full */ - if (unlikely(rte_sched_port_red_drop(port, pkt, qindex, qlen) || + if (unlikely(rte_sched_port_red_drop(port, subport, pkt, qindex, qlen) || (qlen >= qsize))) { rte_pktmbuf_free(pkt); #ifdef RTE_SCHED_COLLECT_STATS - rte_sched_port_update_subport_stats_on_drop(port, qindex, pkt, - qlen < qsize); - rte_sched_port_update_queue_stats_on_drop(port, qindex, pkt, - qlen < qsize); + rte_sched_port_update_subport_stats_on_drop(port, subport, + qindex, pkt, qlen < qsize); + rte_sched_port_update_queue_stats_on_drop(subport, qindex, pkt, + qlen < qsize); #endif return 0; } @@ -1799,13 +1836,13 @@ rte_sched_port_enqueue_qwa(struct rte_sched_port *port, uint32_t qindex, qbase[q->qw & (qsize - 1)] = pkt; q->qw++; - /* Activate queue in the port bitmap */ - rte_bitmap_set(port->bmp, qindex); + /* Activate queue in the subport bitmap */ + rte_bitmap_set(subport->bmp, qindex); /* Statistics */ #ifdef RTE_SCHED_COLLECT_STATS - rte_sched_port_update_subport_stats(port, qindex, pkt); - rte_sched_port_update_queue_stats(port, qindex, pkt); + rte_sched_port_update_subport_stats(port, subport, qindex, pkt); + rte_sched_port_update_queue_stats(subport, qindex, pkt); #endif return 1; @@ -1833,17 +1870,22 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, *pkt30, *pkt31, *pkt_last; struct rte_mbuf **q00_base, **q01_base, **q10_base, **q11_base, **q20_base, **q21_base, **q30_base, **q31_base, **q_last_base; + struct rte_sched_subport *subport00, *subport01, *subport10, *subport11, + *subport20, *subport21, *subport30, *subport31, *subport_last; uint32_t q00, q01, q10, q11, q20, q21, q30, q31, q_last; uint32_t r00, r01, r10, r11, r20, r21, r30, r31, r_last; + uint32_t subport_qmask; uint32_t result, i; result = 0; + subport_qmask = (1 << (port->n_max_pipes_per_subport_log2 + 4)) - 1; /* * Less then 6 input packets available, which is not enough to * feed the pipeline */ if (unlikely(n_pkts < 6)) { + struct rte_sched_subport *subports[5]; struct rte_mbuf **q_base[5]; uint32_t q[5]; @@ -1851,22 +1893,26 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, for (i = 0; i < n_pkts; i++) rte_prefetch0(pkts[i]); + /* Prefetch the subport structure for each packet */ + for (i = 0; i < n_pkts; i++) + subports[i] = rte_sched_port_subport(port, pkts[i]); + /* Prefetch the queue structure for each queue */ for (i = 0; i < n_pkts; i++) - q[i] = rte_sched_port_enqueue_qptrs_prefetch0(port, - pkts[i]); + q[i] = rte_sched_port_enqueue_qptrs_prefetch0(subports[i], + pkts[i], subport_qmask); /* Prefetch the write pointer location of each queue */ for (i = 0; i < n_pkts; i++) { - q_base[i] = rte_sched_port_qbase(port, q[i]); - rte_sched_port_enqueue_qwa_prefetch0(port, q[i], - q_base[i]); + q_base[i] = rte_sched_subport_pipe_qbase(subports[i], q[i]); + rte_sched_port_enqueue_qwa_prefetch0(port, subports[i], + q[i], q_base[i]); } /* Write each packet to its queue */ for (i = 0; i < n_pkts; i++) - result += rte_sched_port_enqueue_qwa(port, q[i], - q_base[i], pkts[i]); + result += rte_sched_port_enqueue_qwa(port, subports[i], + q[i], q_base[i], pkts[i]); return result; } @@ -1882,21 +1928,29 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, rte_prefetch0(pkt10); rte_prefetch0(pkt11); - q20 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt20); - q21 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt21); + subport20 = rte_sched_port_subport(port, pkt20); + subport21 = rte_sched_port_subport(port, pkt21); + q20 = rte_sched_port_enqueue_qptrs_prefetch0(subport20, + pkt20, subport_qmask); + q21 = rte_sched_port_enqueue_qptrs_prefetch0(subport21, + pkt21, subport_qmask); pkt00 = pkts[4]; pkt01 = pkts[5]; rte_prefetch0(pkt00); rte_prefetch0(pkt01); - q10 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt10); - q11 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt11); + subport10 = rte_sched_port_subport(port, pkt10); + subport11 = rte_sched_port_subport(port, pkt11); + q10 = rte_sched_port_enqueue_qptrs_prefetch0(subport10, + pkt10, subport_qmask); + q11 = rte_sched_port_enqueue_qptrs_prefetch0(subport11, + pkt11, subport_qmask); - q20_base = rte_sched_port_qbase(port, q20); - q21_base = rte_sched_port_qbase(port, q21); - rte_sched_port_enqueue_qwa_prefetch0(port, q20, q20_base); - rte_sched_port_enqueue_qwa_prefetch0(port, q21, q21_base); + q20_base = rte_sched_subport_pipe_qbase(subport20, q20); + q21_base = rte_sched_subport_pipe_qbase(subport21, q21); + rte_sched_port_enqueue_qwa_prefetch0(port, subport20, q20, q20_base); + rte_sched_port_enqueue_qwa_prefetch0(port, subport21, q21, q21_base); /* Run the pipeline */ for (i = 6; i < (n_pkts & (~1)); i += 2) { @@ -1911,6 +1965,10 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, q31 = q21; q20 = q10; q21 = q11; + subport30 = subport20; + subport31 = subport21; + subport20 = subport10; + subport21 = subport11; q30_base = q20_base; q31_base = q21_base; @@ -1920,19 +1978,25 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, rte_prefetch0(pkt00); rte_prefetch0(pkt01); - /* Stage 1: Prefetch queue structure storing queue pointers */ - q10 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt10); - q11 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt11); + /* Stage 1: Prefetch subport and queue structure storing queue pointers */ + subport10 = rte_sched_port_subport(port, pkt10); + subport11 = rte_sched_port_subport(port, pkt11); + q10 = rte_sched_port_enqueue_qptrs_prefetch0(subport10, + pkt10, subport_qmask); + q11 = rte_sched_port_enqueue_qptrs_prefetch0(subport11, + pkt11, subport_qmask); /* Stage 2: Prefetch queue write location */ - q20_base = rte_sched_port_qbase(port, q20); - q21_base = rte_sched_port_qbase(port, q21); - rte_sched_port_enqueue_qwa_prefetch0(port, q20, q20_base); - rte_sched_port_enqueue_qwa_prefetch0(port, q21, q21_base); + q20_base = rte_sched_subport_pipe_qbase(subport20, q20); + q21_base = rte_sched_subport_pipe_qbase(subport21, q21); + rte_sched_port_enqueue_qwa_prefetch0(port, subport20, q20, q20_base); + rte_sched_port_enqueue_qwa_prefetch0(port, subport21, q21, q21_base); /* Stage 3: Write packet to queue and activate queue */ - r30 = rte_sched_port_enqueue_qwa(port, q30, q30_base, pkt30); - r31 = rte_sched_port_enqueue_qwa(port, q31, q31_base, pkt31); + r30 = rte_sched_port_enqueue_qwa(port, subport30, + q30, q30_base, pkt30); + r31 = rte_sched_port_enqueue_qwa(port, subport31, + q31, q31_base, pkt31); result += r30 + r31; } @@ -1944,38 +2008,52 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, pkt_last = pkts[n_pkts - 1]; rte_prefetch0(pkt_last); - q00 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt00); - q01 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt01); - - q10_base = rte_sched_port_qbase(port, q10); - q11_base = rte_sched_port_qbase(port, q11); - rte_sched_port_enqueue_qwa_prefetch0(port, q10, q10_base); - rte_sched_port_enqueue_qwa_prefetch0(port, q11, q11_base); - - r20 = rte_sched_port_enqueue_qwa(port, q20, q20_base, pkt20); - r21 = rte_sched_port_enqueue_qwa(port, q21, q21_base, pkt21); + subport00 = rte_sched_port_subport(port, pkt00); + subport01 = rte_sched_port_subport(port, pkt01); + q00 = rte_sched_port_enqueue_qptrs_prefetch0(subport00, + pkt00, subport_qmask); + q01 = rte_sched_port_enqueue_qptrs_prefetch0(subport01, + pkt01, subport_qmask); + + q10_base = rte_sched_subport_pipe_qbase(subport10, q10); + q11_base = rte_sched_subport_pipe_qbase(subport11, q11); + rte_sched_port_enqueue_qwa_prefetch0(port, subport10, q10, q10_base); + rte_sched_port_enqueue_qwa_prefetch0(port, subport11, q11, q11_base); + + r20 = rte_sched_port_enqueue_qwa(port, subport20, + q20, q20_base, pkt20); + r21 = rte_sched_port_enqueue_qwa(port, subport21, + q21, q21_base, pkt21); result += r20 + r21; - q_last = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt_last); + subport_last = rte_sched_port_subport(port, pkt_last); + q_last = rte_sched_port_enqueue_qptrs_prefetch0(subport_last, + pkt_last, subport_qmask); - q00_base = rte_sched_port_qbase(port, q00); - q01_base = rte_sched_port_qbase(port, q01); - rte_sched_port_enqueue_qwa_prefetch0(port, q00, q00_base); - rte_sched_port_enqueue_qwa_prefetch0(port, q01, q01_base); + q00_base = rte_sched_subport_pipe_qbase(subport00, q00); + q01_base = rte_sched_subport_pipe_qbase(subport01, q01); + rte_sched_port_enqueue_qwa_prefetch0(port, subport00, q00, q00_base); + rte_sched_port_enqueue_qwa_prefetch0(port, subport01, q01, q01_base); - r10 = rte_sched_port_enqueue_qwa(port, q10, q10_base, pkt10); - r11 = rte_sched_port_enqueue_qwa(port, q11, q11_base, pkt11); + r10 = rte_sched_port_enqueue_qwa(port, subport10, q10, + q10_base, pkt10); + r11 = rte_sched_port_enqueue_qwa(port, subport11, q11, + q11_base, pkt11); result += r10 + r11; - q_last_base = rte_sched_port_qbase(port, q_last); - rte_sched_port_enqueue_qwa_prefetch0(port, q_last, q_last_base); + q_last_base = rte_sched_subport_pipe_qbase(subport_last, q_last); + rte_sched_port_enqueue_qwa_prefetch0(port, subport_last, + q_last, q_last_base); - r00 = rte_sched_port_enqueue_qwa(port, q00, q00_base, pkt00); - r01 = rte_sched_port_enqueue_qwa(port, q01, q01_base, pkt01); + r00 = rte_sched_port_enqueue_qwa(port, subport00, q00, + q00_base, pkt00); + r01 = rte_sched_port_enqueue_qwa(port, subport01, q01, + q01_base, pkt01); result += r00 + r01; if (n_pkts & 1) { - r_last = rte_sched_port_enqueue_qwa(port, q_last, q_last_base, pkt_last); + r_last = rte_sched_port_enqueue_qwa(port, subport_last, + q_last, q_last_base, pkt_last); result += r_last; } -- 2.21.0
Update memory footprint compute function for allowing subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 102 +++++++++++------------------------ lib/librte_sched/rte_sched.h | 8 +-- 2 files changed, 36 insertions(+), 74 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index a5e4c45b4..f8d13c66d 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -495,70 +495,6 @@ rte_sched_port_check_params(struct rte_sched_port_params *params) return 0; } -static uint32_t -rte_sched_port_get_array_base(struct rte_sched_port_params *params, enum rte_sched_port_array array) -{ - uint32_t n_subports_per_port = params->n_subports_per_port; - uint32_t n_pipes_per_subport = params->n_pipes_per_subport; - uint32_t n_pipes_per_port = n_pipes_per_subport * n_subports_per_port; - uint32_t n_queues_per_port = RTE_SCHED_QUEUES_PER_PIPE * n_pipes_per_subport * n_subports_per_port; - - uint32_t size_subport = n_subports_per_port * sizeof(struct rte_sched_subport); - uint32_t size_pipe = n_pipes_per_port * sizeof(struct rte_sched_pipe); - uint32_t size_queue = n_queues_per_port * sizeof(struct rte_sched_queue); - uint32_t size_queue_extra - = n_queues_per_port * sizeof(struct rte_sched_queue_extra); - uint32_t size_pipe_profiles - = params->n_max_pipe_profiles * sizeof(struct rte_sched_pipe_profile); - uint32_t size_bmp_array = rte_bitmap_get_memory_footprint(n_queues_per_port); - uint32_t size_per_pipe_queue_array, size_queue_array; - - uint32_t base, i; - - size_per_pipe_queue_array = 0; - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - if (i < RTE_SCHED_TRAFFIC_CLASS_BE) - size_per_pipe_queue_array += - params->qsize[i] * sizeof(struct rte_mbuf *); - else - size_per_pipe_queue_array += RTE_SCHED_MAX_QUEUES_PER_TC * - params->qsize[i] * sizeof(struct rte_mbuf *); - } - size_queue_array = n_pipes_per_port * size_per_pipe_queue_array; - - base = 0; - - if (array == e_RTE_SCHED_PORT_ARRAY_SUBPORT) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_subport); - - if (array == e_RTE_SCHED_PORT_ARRAY_PIPE) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_pipe); - - if (array == e_RTE_SCHED_PORT_ARRAY_QUEUE) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_queue); - - if (array == e_RTE_SCHED_PORT_ARRAY_QUEUE_EXTRA) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_queue_extra); - - if (array == e_RTE_SCHED_PORT_ARRAY_PIPE_PROFILES) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_pipe_profiles); - - if (array == e_RTE_SCHED_PORT_ARRAY_BMP_ARRAY) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_bmp_array); - - if (array == e_RTE_SCHED_PORT_ARRAY_QUEUE_ARRAY) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_queue_array); - - return base; -} - static uint32_t rte_sched_subport_get_array_base(struct rte_sched_subport_params *params, uint32_t n_max_pipe_profiles, @@ -880,22 +816,46 @@ rte_sched_subport_check_params(struct rte_sched_subport_params *params, } uint32_t -rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params) +rte_sched_port_get_memory_footprint(struct rte_sched_port_params *port_params, + struct rte_sched_subport_params **subport_params) { - uint32_t size0, size1; + uint32_t size0 = 0, size1 = 0, i; int status; - status = rte_sched_port_check_params(params); + status = rte_sched_port_check_params(port_params); if (status != 0) { - RTE_LOG(NOTICE, SCHED, - "Port scheduler params check failed (%d)\n", status); + RTE_LOG(ERR, SCHED, + "%s: Port scheduler port params check failed (%d)\n", + __func__, status); return 0; } + for (i = 0; i < port_params->n_subports_per_port; i++) { + struct rte_sched_subport_params *sp = subport_params[i]; + + status = rte_sched_subport_check_params(sp, + port_params->n_max_pipes_per_subport, + port_params->n_max_pipe_profiles, + port_params->rate); + if (status != 0) { + RTE_LOG(ERR, SCHED, + "%s: Port scheduler subport params check failed (%d)\n", + __func__, status); + + return 0; + } + } + size0 = sizeof(struct rte_sched_port); - size1 = rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_TOTAL); + + for (i = 0; i < port_params->n_subports_per_port; i++) { + struct rte_sched_subport_params *sp = subport_params[i]; + + size1 += rte_sched_subport_get_array_base(sp, + port_params->n_max_pipe_profiles, + e_RTE_SCHED_SUBPORT_ARRAY_TOTAL); + } return size0 + size1; } diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index 56e9fbfa7..ea2b07448 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -364,14 +364,16 @@ rte_sched_pipe_config(struct rte_sched_port *port, /** * Hierarchical scheduler memory footprint size per port * - * @param params + * @param port_params * Port scheduler configuration parameter structure + * @param subport_params + * Array of subport parameter structures * @return * Memory footprint size in bytes upon success, 0 otherwise */ uint32_t -rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params); - +rte_sched_port_get_memory_footprint(struct rte_sched_port_params *port_params, + struct rte_sched_subport_params **subport_params); /* * Statistics * -- 2.21.0
Modify packet grinder functions of the schedule to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 223 +++++++++++++++++------------------ 1 file changed, 106 insertions(+), 117 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index f8d13c66d..0451e10ea 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -324,24 +324,6 @@ rte_sched_port_queues_per_port(struct rte_sched_port *port) return RTE_SCHED_QUEUES_PER_PIPE * port->n_pipes_per_subport * port->n_subports_per_port; } -static inline struct rte_mbuf ** -rte_sched_port_qbase(struct rte_sched_port *port, uint32_t qindex) -{ - uint32_t pindex = qindex >> 4; - uint32_t qpos = qindex & 0xF; - - return (port->queue_array + pindex * - port->qsize_sum + port->qsize_add[qpos]); -} - -static inline uint16_t -rte_sched_port_qsize(struct rte_sched_port *port, uint32_t qindex) -{ - uint32_t tc = port->pipe_tc[qindex & (RTE_SCHED_QUEUES_PER_PIPE - 1)]; - - return port->qsize[tc]; -} - static inline uint16_t rte_sched_port_pipe_queue(struct rte_sched_port *port, uint32_t traffic_class) { @@ -1546,9 +1528,10 @@ rte_sched_queue_read_stats(struct rte_sched_port *port, #ifdef RTE_SCHED_DEBUG static inline int -rte_sched_port_queue_is_empty(struct rte_sched_port *port, uint32_t qindex) +rte_sched_port_queue_is_empty(struct rte_sched_subport *subport, + uint32_t qindex) { - struct rte_sched_queue *queue = port->queue + qindex; + struct rte_sched_queue *queue = subport->queue + qindex; return queue->qr == queue->qw; } @@ -1663,9 +1646,10 @@ rte_sched_port_red_drop(struct rte_sched_port *port, } static inline void -rte_sched_port_set_queue_empty_timestamp(struct rte_sched_port *port, uint32_t qindex) +rte_sched_port_set_queue_empty_timestamp(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t qindex) { - struct rte_sched_queue_extra *qe = port->queue_extra + qindex; + struct rte_sched_queue_extra *qe = subport->queue_extra + qindex; struct rte_red *red = &qe->red; rte_red_mark_queue_empty(red, port->time); @@ -1682,14 +1666,14 @@ static inline int rte_sched_port_red_drop(struct rte_sched_port *port __rte_unus return 0; } -#define rte_sched_port_set_queue_empty_timestamp(port, qindex) +#define rte_sched_port_set_queue_empty_timestamp(port, subport, qindex) #endif /* RTE_SCHED_RED */ #ifdef RTE_SCHED_DEBUG static inline void -debug_check_queue_slab(struct rte_sched_port *port, uint32_t bmp_pos, +debug_check_queue_slab(struct rte_sched_subport *subport, uint32_t bmp_pos, uint64_t bmp_slab) { uint64_t mask; @@ -1701,7 +1685,7 @@ debug_check_queue_slab(struct rte_sched_port *port, uint32_t bmp_pos, panic = 0; for (i = 0, mask = 1; i < 64; i++, mask <<= 1) { if (mask & bmp_slab) { - if (rte_sched_port_queue_is_empty(port, bmp_pos + i)) { + if (rte_sched_port_queue_is_empty(subport, bmp_pos + i)) { printf("Queue %u (slab offset %u) is empty\n", bmp_pos + i, i); panic = 1; } @@ -2023,10 +2007,10 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, #ifndef RTE_SCHED_SUBPORT_TC_OV static inline void -grinder_credits_update(struct rte_sched_port *port, uint32_t pos) +grinder_credits_update(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; struct rte_sched_pipe_profile *params = grinder->pipe_params; uint64_t n_periods; @@ -2064,10 +2048,9 @@ grinder_credits_update(struct rte_sched_port *port, uint32_t pos) #else static inline uint32_t -grinder_tc_ov_credits_update(struct rte_sched_port *port, uint32_t pos) +grinder_tc_ov_credits_update(struct rte_sched_port *port, + struct rte_sched_subport *subport) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; uint32_t tc_ov_consumption[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; uint32_t tc_consumption = 0, tc_ov_consumption_max; uint32_t tc_ov_wm = subport->tc_ov_wm; @@ -2107,10 +2090,10 @@ grinder_tc_ov_credits_update(struct rte_sched_port *port, uint32_t pos) } static inline void -grinder_credits_update(struct rte_sched_port *port, uint32_t pos) +grinder_credits_update(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; struct rte_sched_pipe_profile *params = grinder->pipe_params; uint64_t n_periods; @@ -2130,7 +2113,7 @@ grinder_credits_update(struct rte_sched_port *port, uint32_t pos) /* Subport TCs */ if (unlikely(port->time >= subport->tc_time)) { - subport->tc_ov_wm = grinder_tc_ov_credits_update(port, pos); + subport->tc_ov_wm = grinder_tc_ov_credits_update(port, subport); for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) subport->tc_credits[i] = subport->tc_credits_per_period[i]; @@ -2160,10 +2143,10 @@ grinder_credits_update(struct rte_sched_port *port, uint32_t pos) #ifndef RTE_SCHED_SUBPORT_TC_OV static inline int -grinder_credits_check(struct rte_sched_port *port, uint32_t pos) +grinder_credits_check(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; + 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; @@ -2195,10 +2178,10 @@ grinder_credits_check(struct rte_sched_port *port, uint32_t pos) #else static inline int -grinder_credits_check(struct rte_sched_port *port, uint32_t pos) +grinder_credits_check(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; + 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; @@ -2243,15 +2226,16 @@ grinder_credits_check(struct rte_sched_port *port, uint32_t pos) static inline int -grinder_schedule(struct rte_sched_port *port, uint32_t pos) +grinder_schedule(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_queue *queue = grinder->queue[grinder->qpos]; struct rte_mbuf *pkt = grinder->pkt; uint32_t pkt_len = pkt->pkt_len + port->frame_overhead; uint32_t be_tc_active; - if (!grinder_credits_check(port, pos)) + if (!grinder_credits_check(port, subport, pos)) return 0; /* Advance port time */ @@ -2268,15 +2252,15 @@ grinder_schedule(struct rte_sched_port *port, uint32_t pos) if (queue->qr == queue->qw) { uint32_t qindex = grinder->qindex[grinder->qpos]; - rte_bitmap_clear(port->bmp, qindex); + rte_bitmap_clear(subport->bmp, qindex); grinder->qmask &= ~(1 << grinder->qpos); if (be_tc_active) grinder->wrr_mask[grinder->qpos] = 0; - rte_sched_port_set_queue_empty_timestamp(port, qindex); + rte_sched_port_set_queue_empty_timestamp(port, subport, qindex); } /* Reset pipe loop detection */ - port->pipe_loop = RTE_SCHED_PIPE_INVALID; + subport->pipe_loop = RTE_SCHED_PIPE_INVALID; grinder->productive = 1; return 1; @@ -2285,13 +2269,13 @@ grinder_schedule(struct rte_sched_port *port, uint32_t pos) #ifdef SCHED_VECTOR_SSE4 static inline int -grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) +grinder_pipe_exists(struct rte_sched_subport *subport, uint32_t base_pipe) { __m128i index = _mm_set1_epi32(base_pipe); - __m128i pipes = _mm_load_si128((__m128i *)port->grinder_base_bmp_pos); + __m128i pipes = _mm_load_si128((__m128i *)subport->grinder_base_bmp_pos); __m128i res = _mm_cmpeq_epi32(pipes, index); - pipes = _mm_load_si128((__m128i *)(port->grinder_base_bmp_pos + 4)); + pipes = _mm_load_si128((__m128i *)(subport->grinder_base_bmp_pos + 4)); pipes = _mm_cmpeq_epi32(pipes, index); res = _mm_or_si128(res, pipes); @@ -2304,10 +2288,10 @@ grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) #elif defined(SCHED_VECTOR_NEON) static inline int -grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) +grinder_pipe_exists(struct rte_sched_subport *subport, uint32_t base_pipe) { uint32x4_t index, pipes; - uint32_t *pos = (uint32_t *)port->grinder_base_bmp_pos; + uint32_t *pos = (uint32_t *)subport->grinder_base_bmp_pos; index = vmovq_n_u32(base_pipe); pipes = vld1q_u32(pos); @@ -2324,12 +2308,12 @@ grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) #else static inline int -grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) +grinder_pipe_exists(struct rte_sched_subport *subport, uint32_t base_pipe) { uint32_t i; for (i = 0; i < RTE_SCHED_PORT_N_GRINDERS; i++) { - if (port->grinder_base_bmp_pos[i] == base_pipe) + if (subport->grinder_base_bmp_pos[i] == base_pipe) return 1; } @@ -2339,9 +2323,10 @@ grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) #endif /* RTE_SCHED_OPTIMIZATIONS */ static inline void -grinder_pcache_populate(struct rte_sched_port *port, uint32_t pos, uint32_t bmp_pos, uint64_t bmp_slab) +grinder_pcache_populate(struct rte_sched_subport *subport, + uint32_t pos, uint32_t bmp_pos, uint64_t bmp_slab) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint16_t w[4]; grinder->pcache_w = 0; @@ -2370,9 +2355,10 @@ grinder_pcache_populate(struct rte_sched_port *port, uint32_t pos, uint32_t bmp_ } static inline void -grinder_tccache_populate(struct rte_sched_port *port, uint32_t pos, uint32_t qindex, uint16_t qmask) +grinder_tccache_populate(struct rte_sched_subport *subport, + uint32_t pos, uint32_t qindex, uint16_t qmask) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint8_t b, i; grinder->tccache_w = 0; @@ -2393,9 +2379,10 @@ grinder_tccache_populate(struct rte_sched_port *port, uint32_t pos, uint32_t qin } static inline int -grinder_next_tc(struct rte_sched_port *port, uint32_t pos) +grinder_next_tc(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_mbuf **qbase; uint32_t qindex; uint16_t qsize; @@ -2404,15 +2391,15 @@ grinder_next_tc(struct rte_sched_port *port, uint32_t pos) return 0; qindex = grinder->tccache_qindex[grinder->tccache_r]; - qbase = rte_sched_port_qbase(port, qindex); - qsize = rte_sched_port_qsize(port, qindex); + qbase = rte_sched_subport_pipe_qbase(subport, qindex); + qsize = rte_sched_subport_pipe_qsize(port, subport, qindex); grinder->tc_index = rte_sched_port_pipe_tc(port, qindex); grinder->qmask = grinder->tccache_qmask[grinder->tccache_r]; grinder->qsize = qsize; if (grinder->tc_index < RTE_SCHED_TRAFFIC_CLASS_BE) { - grinder->queue[0] = port->queue + qindex; + grinder->queue[0] = subport->queue + qindex; grinder->qbase[0] = qbase; grinder->qindex[0] = qindex; grinder->tccache_r++; @@ -2420,10 +2407,10 @@ grinder_next_tc(struct rte_sched_port *port, uint32_t pos) return 1; } - grinder->queue[0] = port->queue + qindex; - grinder->queue[1] = port->queue + qindex + 1; - grinder->queue[2] = port->queue + qindex + 2; - grinder->queue[3] = port->queue + qindex + 3; + grinder->queue[0] = subport->queue + qindex; + grinder->queue[1] = subport->queue + qindex + 1; + grinder->queue[2] = subport->queue + qindex + 2; + grinder->queue[3] = subport->queue + qindex + 3; grinder->qbase[0] = qbase; grinder->qbase[1] = qbase + qsize; @@ -2440,9 +2427,10 @@ grinder_next_tc(struct rte_sched_port *port, uint32_t pos) } static inline int -grinder_next_pipe(struct rte_sched_port *port, uint32_t pos) +grinder_next_pipe(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint32_t pipe_qindex; uint16_t pipe_qmask; @@ -2455,22 +2443,22 @@ grinder_next_pipe(struct rte_sched_port *port, uint32_t pos) uint32_t bmp_pos = 0; /* Get another non-empty pipe group */ - if (unlikely(rte_bitmap_scan(port->bmp, &bmp_pos, &bmp_slab) <= 0)) + if (unlikely(rte_bitmap_scan(subport->bmp, &bmp_pos, &bmp_slab) <= 0)) return 0; #ifdef RTE_SCHED_DEBUG - debug_check_queue_slab(port, bmp_pos, bmp_slab); + debug_check_queue_slab(subport, bmp_pos, bmp_slab); #endif /* Return if pipe group already in one of the other grinders */ - port->grinder_base_bmp_pos[pos] = RTE_SCHED_BMP_POS_INVALID; - if (unlikely(grinder_pipe_exists(port, bmp_pos))) + subport->grinder_base_bmp_pos[pos] = RTE_SCHED_BMP_POS_INVALID; + if (unlikely(grinder_pipe_exists(subport, bmp_pos))) return 0; - port->grinder_base_bmp_pos[pos] = bmp_pos; + subport->grinder_base_bmp_pos[pos] = bmp_pos; /* Install new pipe group into grinder's pipe cache */ - grinder_pcache_populate(port, pos, bmp_pos, bmp_slab); + grinder_pcache_populate(subport, pos, bmp_pos, bmp_slab); pipe_qmask = grinder->pcache_qmask[0]; pipe_qindex = grinder->pcache_qindex[0]; @@ -2479,18 +2467,18 @@ grinder_next_pipe(struct rte_sched_port *port, uint32_t pos) /* Install new pipe in the grinder */ grinder->pindex = pipe_qindex >> 4; - grinder->subport = port->subport + (grinder->pindex / port->n_pipes_per_subport); - grinder->pipe = port->pipe + grinder->pindex; + grinder->subport = subport; + grinder->pipe = subport->pipe + grinder->pindex; grinder->pipe_params = NULL; /* to be set after the pipe structure is prefetched */ grinder->productive = 0; - grinder_tccache_populate(port, pos, pipe_qindex, pipe_qmask); - grinder_next_tc(port, pos); + grinder_tccache_populate(subport, pos, pipe_qindex, pipe_qmask); + grinder_next_tc(port, subport, pos); /* Check for pipe exhaustion */ - if (grinder->pindex == port->pipe_loop) { - port->pipe_exhaustion = 1; - port->pipe_loop = RTE_SCHED_PIPE_INVALID; + if (grinder->pindex == subport->pipe_loop) { + subport->pipe_exhaustion = 1; + subport->pipe_loop = RTE_SCHED_PIPE_INVALID; } return 1; @@ -2498,9 +2486,9 @@ grinder_next_pipe(struct rte_sched_port *port, uint32_t pos) static inline void -grinder_wrr_load(struct rte_sched_port *port, uint32_t pos) +grinder_wrr_load(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; struct rte_sched_pipe_profile *pipe_params = grinder->pipe_params; uint32_t qmask = grinder->qmask; @@ -2526,9 +2514,9 @@ grinder_wrr_load(struct rte_sched_port *port, uint32_t pos) } static inline void -grinder_wrr_store(struct rte_sched_port *port, uint32_t pos) +grinder_wrr_store(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; pipe->wrr_tokens[0] = @@ -2546,9 +2534,9 @@ grinder_wrr_store(struct rte_sched_port *port, uint32_t pos) } static inline void -grinder_wrr(struct rte_sched_port *port, uint32_t pos) +grinder_wrr(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint16_t wrr_tokens_min; grinder->wrr_tokens[0] |= ~grinder->wrr_mask[0]; @@ -2566,21 +2554,21 @@ grinder_wrr(struct rte_sched_port *port, uint32_t pos) } -#define grinder_evict(port, pos) +#define grinder_evict(subport, pos) static inline void -grinder_prefetch_pipe(struct rte_sched_port *port, uint32_t pos) +grinder_prefetch_pipe(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; rte_prefetch0(grinder->pipe); rte_prefetch0(grinder->queue[0]); } static inline void -grinder_prefetch_tc_queue_arrays(struct rte_sched_port *port, uint32_t pos) +grinder_prefetch_tc_queue_arrays(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint16_t qsize, qr[RTE_SCHED_MAX_QUEUES_PER_TC]; qsize = grinder->qsize; @@ -2601,17 +2589,17 @@ grinder_prefetch_tc_queue_arrays(struct rte_sched_port *port, uint32_t pos) rte_prefetch0(grinder->qbase[0] + qr[0]); rte_prefetch0(grinder->qbase[1] + qr[1]); - grinder_wrr_load(port, pos); - grinder_wrr(port, pos); + grinder_wrr_load(subport, pos); + grinder_wrr(subport, pos); rte_prefetch0(grinder->qbase[2] + qr[2]); rte_prefetch0(grinder->qbase[3] + qr[3]); } static inline void -grinder_prefetch_mbuf(struct rte_sched_port *port, uint32_t pos) +grinder_prefetch_mbuf(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint32_t qpos = grinder->qpos; struct rte_mbuf **qbase = grinder->qbase[qpos]; uint16_t qsize = grinder->qsize; @@ -2630,14 +2618,15 @@ grinder_prefetch_mbuf(struct rte_sched_port *port, uint32_t pos) static inline uint32_t grinder_handle(struct rte_sched_port *port, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_subport *subport = port->subport; + struct rte_sched_grinder *grinder = subport->grinder + pos; switch (grinder->state) { case e_GRINDER_PREFETCH_PIPE: { - if (grinder_next_pipe(port, pos)) { - grinder_prefetch_pipe(port, pos); - port->busy_grinders++; + if (grinder_next_pipe(port, subport, pos)) { + grinder_prefetch_pipe(subport, pos); + subport->busy_grinders++; grinder->state = e_GRINDER_PREFETCH_TC_QUEUE_ARRAYS; return 0; @@ -2650,9 +2639,9 @@ grinder_handle(struct rte_sched_port *port, uint32_t pos) { struct rte_sched_pipe *pipe = grinder->pipe; - grinder->pipe_params = port->pipe_profiles + pipe->profile; - grinder_prefetch_tc_queue_arrays(port, pos); - grinder_credits_update(port, pos); + grinder->pipe_params = subport->pipe_profiles + pipe->profile; + grinder_prefetch_tc_queue_arrays(subport, pos); + grinder_credits_update(port, subport, pos); grinder->state = e_GRINDER_PREFETCH_MBUF; return 0; @@ -2660,7 +2649,7 @@ grinder_handle(struct rte_sched_port *port, uint32_t pos) case e_GRINDER_PREFETCH_MBUF: { - grinder_prefetch_mbuf(port, pos); + grinder_prefetch_mbuf(subport, pos); grinder->state = e_GRINDER_READ_MBUF; return 0; @@ -2670,47 +2659,47 @@ grinder_handle(struct rte_sched_port *port, uint32_t pos) { uint32_t wrr_active, result = 0; - result = grinder_schedule(port, pos); + result = grinder_schedule(port, subport, pos); wrr_active = (grinder->tc_index == RTE_SCHED_TRAFFIC_CLASS_BE); /* Look for next packet within the same TC */ if (result && grinder->qmask) { if (wrr_active) - grinder_wrr(port, pos); + grinder_wrr(subport, pos); - grinder_prefetch_mbuf(port, pos); + grinder_prefetch_mbuf(subport, pos); return 1; } if (wrr_active) - grinder_wrr_store(port, pos); + grinder_wrr_store(subport, pos); /* Look for another active TC within same pipe */ - if (grinder_next_tc(port, pos)) { - grinder_prefetch_tc_queue_arrays(port, pos); + if (grinder_next_tc(port, subport, pos)) { + grinder_prefetch_tc_queue_arrays(subport, pos); grinder->state = e_GRINDER_PREFETCH_MBUF; return result; } if (grinder->productive == 0 && - port->pipe_loop == RTE_SCHED_PIPE_INVALID) - port->pipe_loop = grinder->pindex; + subport->pipe_loop == RTE_SCHED_PIPE_INVALID) + subport->pipe_loop = grinder->pindex; - grinder_evict(port, pos); + grinder_evict(subport, pos); /* Look for another active pipe */ - if (grinder_next_pipe(port, pos)) { - grinder_prefetch_pipe(port, pos); + if (grinder_next_pipe(port, subport, pos)) { + grinder_prefetch_pipe(subport, pos); grinder->state = e_GRINDER_PREFETCH_TC_QUEUE_ARRAYS; return result; } /* No active pipe found */ - port->busy_grinders--; + subport->busy_grinders--; grinder->state = e_GRINDER_PREFETCH_PIPE; return result; -- 2.21.0
Modify scheduler packet dequeue operation to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 51 ++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 0451e10ea..e0ef86f40 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -245,6 +245,7 @@ struct rte_sched_port { uint32_t busy_grinders; struct rte_mbuf **pkts_out; uint32_t n_pkts_out; + uint32_t subport_id; /* Queue base calculation */ uint32_t qsize_add[RTE_SCHED_QUEUES_PER_PIPE]; @@ -911,6 +912,7 @@ rte_sched_port_config(struct rte_sched_port_params *params) /* Grinders */ port->pkts_out = NULL; port->n_pkts_out = 0; + port->subport_id = 0; return port; } @@ -2616,9 +2618,9 @@ grinder_prefetch_mbuf(struct rte_sched_subport *subport, uint32_t pos) } static inline uint32_t -grinder_handle(struct rte_sched_port *port, uint32_t pos) +grinder_handle(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_subport *subport = port->subport; struct rte_sched_grinder *grinder = subport->grinder + pos; switch (grinder->state) { @@ -2717,6 +2719,7 @@ rte_sched_port_time_resync(struct rte_sched_port *port) uint64_t cycles = rte_get_tsc_cycles(); uint64_t cycles_diff = cycles - port->time_cpu_cycles; uint64_t bytes_diff; + uint32_t i; /* Compute elapsed time in bytes */ bytes_diff = rte_reciprocal_divide(cycles_diff << RTE_SCHED_TIME_SHIFT, @@ -2729,20 +2732,21 @@ rte_sched_port_time_resync(struct rte_sched_port *port) port->time = port->time_cpu_bytes; /* Reset pipe loop detection */ - port->pipe_loop = RTE_SCHED_PIPE_INVALID; + for (i = 0; i < port->n_subports_per_port; i++) + port->subports[i]->pipe_loop = RTE_SCHED_PIPE_INVALID; } static inline int -rte_sched_port_exceptions(struct rte_sched_port *port, int second_pass) +rte_sched_port_exceptions(struct rte_sched_subport *subport, int second_pass) { int exceptions; /* Check if any exception flag is set */ - exceptions = (second_pass && port->busy_grinders == 0) || - (port->pipe_exhaustion == 1); + exceptions = (second_pass && subport->busy_grinders == 0) || + (subport->pipe_exhaustion == 1); /* Clear exception flags */ - port->pipe_exhaustion = 0; + subport->pipe_exhaustion = 0; return exceptions; } @@ -2750,7 +2754,9 @@ rte_sched_port_exceptions(struct rte_sched_port *port, int second_pass) int rte_sched_port_dequeue(struct rte_sched_port *port, struct rte_mbuf **pkts, uint32_t n_pkts) { - uint32_t i, count; + struct rte_sched_subport *subport; + uint32_t subport_id = port->subport_id; + uint32_t i, n_subports = 0, count; port->pkts_out = pkts; port->n_pkts_out = 0; @@ -2759,9 +2765,32 @@ rte_sched_port_dequeue(struct rte_sched_port *port, struct rte_mbuf **pkts, uint /* Take each queue in the grinder one step further */ for (i = 0, count = 0; ; i++) { - count += grinder_handle(port, i & (RTE_SCHED_PORT_N_GRINDERS - 1)); - if ((count == n_pkts) || - rte_sched_port_exceptions(port, i >= RTE_SCHED_PORT_N_GRINDERS)) { + subport = port->subports[subport_id]; + + count += grinder_handle(port, subport, + i & (RTE_SCHED_PORT_N_GRINDERS - 1)); + + if (count == n_pkts) { + subport_id++; + + if (subport_id == port->n_subports_per_port) + subport_id = 0; + + port->subport_id = subport_id; + break; + } + + if (rte_sched_port_exceptions(subport, i >= RTE_SCHED_PORT_N_GRINDERS)) { + i = 0; + subport_id++; + n_subports++; + } + + if (subport_id == port->n_subports_per_port) + subport_id = 0; + + if (n_subports == port->n_subports_per_port) { + port->subport_id = subport_id; break; } } -- 2.21.0
Modify pipe queue stats read function to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index e0ef86f40..8a7727286 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -284,16 +284,6 @@ enum rte_sched_subport_array { e_RTE_SCHED_SUBPORT_ARRAY_TOTAL, }; -#ifdef RTE_SCHED_COLLECT_STATS - -static inline uint32_t -rte_sched_port_queues_per_subport(struct rte_sched_port *port) -{ - return RTE_SCHED_QUEUES_PER_PIPE * port->n_pipes_per_subport; -} - -#endif - static inline uint32_t rte_sched_subport_pipe_queues(struct rte_sched_subport *subport) { @@ -322,7 +312,12 @@ struct rte_sched_subport *subport, uint32_t qindex) static inline uint32_t rte_sched_port_queues_per_port(struct rte_sched_port *port) { - return RTE_SCHED_QUEUES_PER_PIPE * port->n_pipes_per_subport * port->n_subports_per_port; + uint32_t n_queues = 0, i; + + for (i = 0; i < port->n_subports_per_port; i++) + n_queues += rte_sched_subport_pipe_queues(port->subports[i]); + + return n_queues; } static inline uint16_t @@ -1487,8 +1482,10 @@ rte_sched_queue_read_stats(struct rte_sched_port *port, struct rte_sched_queue_stats *stats, uint16_t *qlen) { + struct rte_sched_subport *s; struct rte_sched_queue *q; struct rte_sched_queue_extra *qe; + uint32_t subport_id, subport_qmask, subport_qindex; /* Check user parameters */ if (port == NULL) { @@ -1514,8 +1511,13 @@ rte_sched_queue_read_stats(struct rte_sched_port *port, "%s: Incorrect value for parameter qlen\n", __func__); return -EINVAL; } - q = port->queue + queue_id; - qe = port->queue_extra + queue_id; + subport_qmask = port->n_max_pipes_per_subport_log2 + 4; + subport_id = (queue_id >> subport_qmask) & (port->n_subports_per_port - 1); + + s = port->subports[subport_id]; + subport_qindex = ((1 << subport_qmask) - 1) & queue_id; + q = s->queue + subport_qindex; + qe = s->queue_extra + subport_qindex; /* Copy queue stats and clear */ memcpy(stats, &qe->stats, sizeof(struct rte_sched_queue_stats)); -- 2.21.0
Modify tests function to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- app/test/test_sched.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/app/test/test_sched.c b/app/test/test_sched.c index afe0b0765..6a2896234 100644 --- a/app/test/test_sched.c +++ b/app/test/test_sched.c @@ -22,18 +22,6 @@ #define TC 2 #define QUEUE 0 -static struct rte_sched_subport_params subport_param[] = { - { - .tb_rate = 1250000000, - .tb_size = 1000000, - - .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000, - 1250000000, 1250000000, 1250000000, 1250000000, 1250000000, - 1250000000, 1250000000, 1250000000, 1250000000}, - .tc_period = 10, - }, -}; - static struct rte_sched_pipe_params pipe_profile[] = { { /* Profile #0 */ .tb_rate = 305175, @@ -48,16 +36,29 @@ static struct rte_sched_pipe_params pipe_profile[] = { }, }; +static struct rte_sched_subport_params subport_param[] = { + { + .tb_rate = 1250000000, + .tb_size = 1000000, + + .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000, + 1250000000, 1250000000, 1250000000, 1250000000, 1250000000, + 1250000000, 1250000000, 1250000000, 1250000000}, + .tc_period = 10, + .n_pipes_per_subport = 1024, + .qsize = {32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}, + .pipe_profiles = pipe_profile, + .n_pipe_profiles = 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, 32, 32, 32, 32, 32, 32, 32, 32, 32}, - .pipe_profiles = pipe_profile, - .n_pipe_profiles = 1, + .n_max_pipes_per_subport = 1024, .n_max_pipe_profiles = 1, }; @@ -140,7 +141,7 @@ test_sched(void) err = rte_sched_subport_config(port, SUBPORT, subport_param); TEST_ASSERT_SUCCESS(err, "Error config sched, err=%d\n", err); - for (pipe = 0; pipe < port_param.n_pipes_per_subport; pipe ++) { + for (pipe = 0; pipe < subport_param[0].n_pipes_per_subport; pipe++) { err = rte_sched_pipe_config(port, SUBPORT, pipe, 0); TEST_ASSERT_SUCCESS(err, "Error config sched pipe %u, err=%d\n", pipe, err); } -- 2.21.0
Modify softnic traffic management function to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- drivers/net/softnic/rte_eth_softnic_tm.c | 51 ++++++++++++------------ 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/drivers/net/softnic/rte_eth_softnic_tm.c b/drivers/net/softnic/rte_eth_softnic_tm.c index 61c3adc82..8fb728d7d 100644 --- a/drivers/net/softnic/rte_eth_softnic_tm.c +++ b/drivers/net/softnic/rte_eth_softnic_tm.c @@ -85,7 +85,8 @@ softnic_tmgr_port_create(struct pmd_internals *p, /* Subport */ n_subports = t->port_params.n_subports_per_port; for (subport_id = 0; subport_id < n_subports; subport_id++) { - uint32_t n_pipes_per_subport = t->port_params.n_pipes_per_subport; + uint32_t n_pipes_per_subport = + t->subport_params[subport_id].n_pipes_per_subport; uint32_t pipe_id; int status; @@ -2211,10 +2212,11 @@ tm_tc_wred_profile_get(struct rte_eth_dev *dev, uint32_t tc_id) #ifdef RTE_SCHED_RED static void -wred_profiles_set(struct rte_eth_dev *dev) +wred_profiles_set(struct rte_eth_dev *dev, uint32_t subport_id) { struct pmd_internals *p = dev->data->dev_private; - struct rte_sched_port_params *pp = &p->soft.tm.params.port_params; + struct rte_sched_subport_params *pp = + &p->soft.tm.params.subport_params[subport_id]; uint32_t tc_id; enum rte_color color; @@ -2234,7 +2236,7 @@ wred_profiles_set(struct rte_eth_dev *dev) #else -#define wred_profiles_set(dev) +#define wred_profiles_set(dev, subport_id) #endif @@ -2526,29 +2528,10 @@ hierarchy_blueprints_create(struct rte_eth_dev *dev) .frame_overhead = root->shaper_profile->params.pkt_length_adjust, .n_subports_per_port = root->n_children, - .n_pipes_per_subport = h->n_tm_nodes[TM_NODE_LEVEL_PIPE] / - h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT], - .qsize = {p->params.tm.qsize[0], - p->params.tm.qsize[1], - p->params.tm.qsize[2], - p->params.tm.qsize[3], - p->params.tm.qsize[4], - p->params.tm.qsize[5], - p->params.tm.qsize[6], - p->params.tm.qsize[7], - p->params.tm.qsize[8], - p->params.tm.qsize[9], - p->params.tm.qsize[10], - p->params.tm.qsize[11], - p->params.tm.qsize[12], - }, - .pipe_profiles = t->pipe_profiles, - .n_pipe_profiles = t->n_pipe_profiles, + .n_max_pipes_per_subport = TM_MAX_PIPES_PER_SUBPORT, .n_max_pipe_profiles = TM_MAX_PIPE_PROFILE, }; - wred_profiles_set(dev); - subport_id = 0; TAILQ_FOREACH(n, nl, node) { uint64_t tc_rate[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; @@ -2588,8 +2571,26 @@ hierarchy_blueprints_create(struct rte_eth_dev *dev) tc_rate[12], }, .tc_period = SUBPORT_TC_PERIOD, + .n_pipes_per_subport = h->n_tm_nodes[TM_NODE_LEVEL_PIPE] / + h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT], + .qsize = {p->params.tm.qsize[0], + p->params.tm.qsize[1], + p->params.tm.qsize[2], + p->params.tm.qsize[3], + p->params.tm.qsize[4], + p->params.tm.qsize[5], + p->params.tm.qsize[6], + p->params.tm.qsize[7], + p->params.tm.qsize[8], + p->params.tm.qsize[9], + p->params.tm.qsize[10], + p->params.tm.qsize[11], + p->params.tm.qsize[12], + }, + .pipe_profiles = t->pipe_profiles, + .n_pipe_profiles = t->n_pipe_profiles, }; - + wred_profiles_set(dev, subport_id); subport_id++; } } -- 2.21.0
Modify ip pipeline traffic management function to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- examples/ip_pipeline/cli.c | 71 ++++++++++++++++++------------------- examples/ip_pipeline/tmgr.c | 23 ++++++------ examples/ip_pipeline/tmgr.h | 7 ++-- 3 files changed, 49 insertions(+), 52 deletions(-) diff --git a/examples/ip_pipeline/cli.c b/examples/ip_pipeline/cli.c index c6cf4204e..1e8dc95b4 100644 --- a/examples/ip_pipeline/cli.c +++ b/examples/ip_pipeline/cli.c @@ -380,7 +380,12 @@ static const char cmd_tmgr_subport_profile_help[] = " <tc0_rate> <tc1_rate> <tc2_rate> <tc3_rate> <tc4_rate>" " <tc5_rate> <tc6_rate> <tc7_rate> <tc8_rate>" " <tc9_rate> <tc10_rate> <tc11_rate> <tc12_rate>\n" -" <tc_period>\n"; +" <tc_period>\n" +" pps <n_pipes_per_subport>\n" +" qsize <qsize_tc0> <qsize_tc1> <qsize_tc2>" +" <qsize_tc3> <qsize_tc4> <qsize_tc5> <qsize_tc6>" +" <qsize_tc7> <qsize_tc8> <qsize_tc9> <qsize_tc10>" +" <qsize_tc11> <qsize_tc12>"; static void cmd_tmgr_subport_profile(char **tokens, @@ -391,7 +396,7 @@ cmd_tmgr_subport_profile(char **tokens, struct rte_sched_subport_params p; int status, i; - if (n_tokens != 19) { + if (n_tokens != 35) { snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); return; } @@ -417,6 +422,27 @@ cmd_tmgr_subport_profile(char **tokens, return; } + if (strcmp(tokens[19], "pps") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps"); + return; + } + + if (parser_read_uint32(&p.n_pipes_per_subport, tokens[20]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "n_pipes_per_subport"); + return; + } + + if (strcmp(tokens[21], "qsize") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "qsize"); + return; + } + + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) + if (parser_read_uint16(&p.qsize[i], tokens[22 + i]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "qsize"); + return; + } + status = tmgr_subport_profile_add(&p); if (status != 0) { snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); @@ -491,11 +517,6 @@ static const char cmd_tmgr_help[] = "tmgr <tmgr_name>\n" " rate <rate>\n" " spp <n_subports_per_port>\n" -" pps <n_pipes_per_subport>\n" -" qsize <qsize_tc0> <qsize_tc1> <qsize_tc2>" -" <qsize_tc3> <qsize_tc4> <qsize_tc5> <qsize_tc6>" -" <qsize_tc7> <qsize_tc8> <qsize_tc9> <qsize_tc10>" -" <qsize_tc11> <qsize_tc12>\n" " fo <frame_overhead>\n" " mtu <mtu>\n" " cpu <cpu_id>\n"; @@ -509,9 +530,8 @@ cmd_tmgr(char **tokens, struct tmgr_port_params p; char *name; struct tmgr_port *tmgr_port; - int i; - if (n_tokens != 28) { + if (n_tokens != 12) { snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); return; } @@ -538,53 +558,32 @@ cmd_tmgr(char **tokens, return; } - if (strcmp(tokens[6], "pps") != 0) { - snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps"); - return; - } - - if (parser_read_uint32(&p.n_pipes_per_subport, tokens[7]) != 0) { - snprintf(out, out_size, MSG_ARG_INVALID, "n_pipes_per_subport"); - return; - } - - if (strcmp(tokens[8], "qsize") != 0) { - snprintf(out, out_size, MSG_ARG_NOT_FOUND, "qsize"); - return; - } - - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - if (parser_read_uint16(&p.qsize[i], tokens[9 + i]) != 0) { - snprintf(out, out_size, MSG_ARG_INVALID, "qsize"); - return; - } - - if (strcmp(tokens[22], "fo") != 0) { + if (strcmp(tokens[6], "fo") != 0) { snprintf(out, out_size, MSG_ARG_NOT_FOUND, "fo"); return; } - if (parser_read_uint32(&p.frame_overhead, tokens[23]) != 0) { + if (parser_read_uint32(&p.frame_overhead, tokens[7]) != 0) { snprintf(out, out_size, MSG_ARG_INVALID, "frame_overhead"); return; } - if (strcmp(tokens[24], "mtu") != 0) { + if (strcmp(tokens[8], "mtu") != 0) { snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mtu"); return; } - if (parser_read_uint32(&p.mtu, tokens[25]) != 0) { + if (parser_read_uint32(&p.mtu, tokens[9]) != 0) { snprintf(out, out_size, MSG_ARG_INVALID, "mtu"); return; } - if (strcmp(tokens[26], "cpu") != 0) { + if (strcmp(tokens[10], "cpu") != 0) { snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu"); return; } - if (parser_read_uint32(&p.cpu_id, tokens[27]) != 0) { + if (parser_read_uint32(&p.cpu_id, tokens[11]) != 0) { snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id"); return; } diff --git a/examples/ip_pipeline/tmgr.c b/examples/ip_pipeline/tmgr.c index 40cbf1d0a..cafb9cdcc 100644 --- a/examples/ip_pipeline/tmgr.c +++ b/examples/ip_pipeline/tmgr.c @@ -47,7 +47,8 @@ int tmgr_subport_profile_add(struct rte_sched_subport_params *p) { /* Check input params */ - if (p == NULL) + if (p == NULL || + p->n_pipes_per_subport == 0) return -1; /* Save profile */ @@ -90,7 +91,6 @@ tmgr_port_create(const char *name, struct tmgr_port_params *params) tmgr_port_find(name) || (params == NULL) || (params->n_subports_per_port == 0) || - (params->n_pipes_per_subport == 0) || (params->cpu_id >= RTE_MAX_NUMA_NODES) || (n_subport_profiles == 0) || (n_pipe_profiles == 0)) @@ -103,18 +103,16 @@ tmgr_port_create(const char *name, struct tmgr_port_params *params) p.mtu = params->mtu; p.frame_overhead = params->frame_overhead; p.n_subports_per_port = params->n_subports_per_port; - p.n_pipes_per_subport = params->n_pipes_per_subport; - - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - p.qsize[i] = params->qsize[i]; - - p.pipe_profiles = pipe_profile; - p.n_pipe_profiles = n_pipe_profiles; + p.n_max_pipes_per_subport = TMGR_PIPE_SUBPORT_MAX; + p.n_max_pipe_profiles = TMGR_PIPE_PROFILE_MAX; s = rte_sched_port_config(&p); if (s == NULL) return NULL; + subport_profile[0].pipe_profiles = pipe_profile; + subport_profile[0].n_pipe_profiles = n_pipe_profiles; + for (i = 0; i < params->n_subports_per_port; i++) { int status; @@ -128,7 +126,7 @@ tmgr_port_create(const char *name, struct tmgr_port_params *params) return NULL; } - for (j = 0; j < params->n_pipes_per_subport; j++) { + for (j = 0; j < subport_profile[0].n_pipes_per_subport; j++) { status = rte_sched_pipe_config( s, i, @@ -153,7 +151,6 @@ tmgr_port_create(const char *name, struct tmgr_port_params *params) strlcpy(tmgr_port->name, name, sizeof(tmgr_port->name)); tmgr_port->s = s; tmgr_port->n_subports_per_port = params->n_subports_per_port; - tmgr_port->n_pipes_per_subport = params->n_pipes_per_subport; /* Node add to list */ TAILQ_INSERT_TAIL(&tmgr_port_list, tmgr_port, node); @@ -205,8 +202,8 @@ tmgr_pipe_config(const char *port_name, port = tmgr_port_find(port_name); if ((port == NULL) || (subport_id >= port->n_subports_per_port) || - (pipe_id_first >= port->n_pipes_per_subport) || - (pipe_id_last >= port->n_pipes_per_subport) || + (pipe_id_first >= subport_profile[subport_id].n_pipes_per_subport) || + (pipe_id_last >= subport_profile[subport_id].n_pipes_per_subport) || (pipe_id_first > pipe_id_last) || (pipe_profile_id >= n_pipe_profiles)) return -1; diff --git a/examples/ip_pipeline/tmgr.h b/examples/ip_pipeline/tmgr.h index 8703a2e00..1fcf66ee1 100644 --- a/examples/ip_pipeline/tmgr.h +++ b/examples/ip_pipeline/tmgr.h @@ -12,6 +12,10 @@ #include "common.h" +#ifndef TMGR_PIPE_SUBPORT_MAX +#define TMGR_PIPE_SUBPORT_MAX 4096 +#endif + #ifndef TMGR_SUBPORT_PROFILE_MAX #define TMGR_SUBPORT_PROFILE_MAX 256 #endif @@ -25,7 +29,6 @@ struct tmgr_port { char name[NAME_SIZE]; struct rte_sched_port *s; uint32_t n_subports_per_port; - uint32_t n_pipes_per_subport; }; TAILQ_HEAD(tmgr_port_list, tmgr_port); @@ -42,8 +45,6 @@ struct tmgr_port_params { uint32_t frame_overhead; uint32_t mtu; uint32_t cpu_id; - uint32_t n_pipes_per_subport; - uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; }; int -- 2.21.0
Modify qos sample app to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- examples/qos_sched/app_thread.c | 4 +- examples/qos_sched/cfg_file.c | 229 ++++++++++++++++-------------- examples/qos_sched/init.c | 54 +++---- examples/qos_sched/main.h | 1 + examples/qos_sched/profile.cfg | 5 +- examples/qos_sched/profile_ov.cfg | 5 +- examples/qos_sched/stats.c | 36 ++--- 7 files changed, 182 insertions(+), 152 deletions(-) diff --git a/examples/qos_sched/app_thread.c b/examples/qos_sched/app_thread.c index 18b734a14..e07cc7452 100644 --- a/examples/qos_sched/app_thread.c +++ b/examples/qos_sched/app_thread.c @@ -36,9 +36,9 @@ get_pkt_sched(struct rte_mbuf *m, uint32_t *subport, uint32_t *pipe, uint16_t pipe_queue; *subport = (rte_be_to_cpu_16(pdata[SUBPORT_OFFSET]) & 0x0FFF) & - (port_params.n_subports_per_port - 1); /* Outer VLAN ID*/ + (port_params.n_subports_per_port - 1); /* Outer VLAN ID*/ *pipe = (rte_be_to_cpu_16(pdata[PIPE_OFFSET]) & 0x0FFF) & - (port_params.n_pipes_per_subport - 1); /* Inner VLAN ID */ + (subport_params[*subport].n_pipes_per_subport - 1); /* Inner VLAN ID */ pipe_queue = active_queues[(pdata[QUEUE_OFFSET] >> 8) % n_active_queues]; *traffic_class = pipe_queue > RTE_SCHED_TRAFFIC_CLASS_BE ? RTE_SCHED_TRAFFIC_CLASS_BE : pipe_queue; /* Destination IP */ diff --git a/examples/qos_sched/cfg_file.c b/examples/qos_sched/cfg_file.c index 45bf599e4..f34615b4c 100644 --- a/examples/qos_sched/cfg_file.c +++ b/examples/qos_sched/cfg_file.c @@ -24,14 +24,10 @@ int cfg_load_port(struct rte_cfgfile *cfg, struct rte_sched_port_params *port_params) { const char *entry; - int j; if (!cfg || !port_params) return -1; - memset(active_queues, 0, sizeof(active_queues)); - n_active_queues = 0; - entry = rte_cfgfile_get_entry(cfg, "port", "frame overhead"); if (entry) port_params->frame_overhead = (uint32_t)atoi(entry); @@ -40,106 +36,6 @@ cfg_load_port(struct rte_cfgfile *cfg, struct rte_sched_port_params *port_params if (entry) port_params->n_subports_per_port = (uint32_t)atoi(entry); - entry = rte_cfgfile_get_entry(cfg, "port", "number of pipes per subport"); - if (entry) - port_params->n_pipes_per_subport = (uint32_t)atoi(entry); - - entry = rte_cfgfile_get_entry(cfg, "port", "queue sizes"); - if (entry) { - char *next; - - for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { - port_params->qsize[j] = (uint16_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - - for (j = 0; j < RTE_SCHED_TRAFFIC_CLASS_BE; j++) - if (port_params->qsize[j]) { - active_queues[n_active_queues] = j; - n_active_queues++; - } - - if (port_params->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]) - for (j = 0; j < RTE_SCHED_BE_QUEUES_PER_PIPE; j++) { - active_queues[n_active_queues] = - RTE_SCHED_TRAFFIC_CLASS_BE + j; - n_active_queues++; - } - } - -#ifdef RTE_SCHED_RED - for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { - char str[32]; - - /* Parse WRED min thresholds */ - snprintf(str, sizeof(str), "tc %d wred min", j); - entry = rte_cfgfile_get_entry(cfg, "red", str); - if (entry) { - char *next; - int k; - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < RTE_COLORS; k++) { - port_params->red_params[j][k].min_th - = (uint16_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - } - - /* Parse WRED max thresholds */ - snprintf(str, sizeof(str), "tc %d wred max", j); - entry = rte_cfgfile_get_entry(cfg, "red", str); - if (entry) { - char *next; - int k; - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < RTE_COLORS; k++) { - port_params->red_params[j][k].max_th - = (uint16_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - } - - /* Parse WRED inverse mark probabilities */ - snprintf(str, sizeof(str), "tc %d wred inv prob", j); - entry = rte_cfgfile_get_entry(cfg, "red", str); - if (entry) { - char *next; - int k; - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < RTE_COLORS; k++) { - port_params->red_params[j][k].maxp_inv - = (uint8_t)strtol(entry, &next, 10); - - if (next == NULL) - break; - entry = next; - } - } - - /* Parse WRED EWMA filter weights */ - snprintf(str, sizeof(str), "tc %d wred weight", j); - entry = rte_cfgfile_get_entry(cfg, "red", str); - if (entry) { - char *next; - int k; - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < RTE_COLORS; k++) { - port_params->red_params[j][k].wq_log2 - = (uint8_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - } - } -#endif /* RTE_SCHED_RED */ - return 0; } @@ -155,7 +51,7 @@ cfg_load_pipe(struct rte_cfgfile *cfg, struct rte_sched_pipe_params *pipe_params return -1; profiles = rte_cfgfile_num_sections(cfg, "pipe profile", sizeof("pipe profile") - 1); - port_params.n_pipe_profiles = profiles; + subport_params[0].n_pipe_profiles = profiles; for (j = 0; j < profiles; j++) { char pipe_name[32]; @@ -253,12 +149,121 @@ cfg_load_subport(struct rte_cfgfile *cfg, struct rte_sched_subport_params *subpo return -1; memset(app_pipe_to_profile, -1, sizeof(app_pipe_to_profile)); + memset(active_queues, 0, sizeof(active_queues)); + n_active_queues = 0; + +#ifdef RTE_SCHED_RED + char sec_name[CFG_NAME_LEN]; + struct rte_red_params red_params[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; + + snprintf(sec_name, sizeof(sec_name), "red"); + + if (rte_cfgfile_has_section(cfg, sec_name)) { + + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + char str[32]; + + /* Parse WRED min thresholds */ + snprintf(str, sizeof(str), "tc %d wred min", i); + entry = rte_cfgfile_get_entry(cfg, sec_name, str); + if (entry) { + char *next; + /* for each packet colour (green, yellow, red) */ + for (j = 0; j < RTE_COLORS; j++) { + red_params[i][j].min_th + = (uint16_t)strtol(entry, &next, 10); + if (next == NULL) + break; + entry = next; + } + } + + /* Parse WRED max thresholds */ + snprintf(str, sizeof(str), "tc %d wred max", i); + entry = rte_cfgfile_get_entry(cfg, "red", str); + if (entry) { + char *next; + /* for each packet colour (green, yellow, red) */ + for (j = 0; j < RTE_COLORS; j++) { + red_params[i][j].max_th + = (uint16_t)strtol(entry, &next, 10); + if (next == NULL) + break; + entry = next; + } + } + + /* Parse WRED inverse mark probabilities */ + snprintf(str, sizeof(str), "tc %d wred inv prob", i); + entry = rte_cfgfile_get_entry(cfg, "red", str); + if (entry) { + char *next; + /* for each packet colour (green, yellow, red) */ + for (j = 0; j < RTE_COLORS; j++) { + red_params[i][j].maxp_inv + = (uint8_t)strtol(entry, &next, 10); + + if (next == NULL) + break; + entry = next; + } + } + + /* Parse WRED EWMA filter weights */ + snprintf(str, sizeof(str), "tc %d wred weight", i); + entry = rte_cfgfile_get_entry(cfg, "red", str); + if (entry) { + char *next; + /* for each packet colour (green, yellow, red) */ + for (j = 0; j < RTE_COLORS; j++) { + red_params[i][j].wq_log2 + = (uint8_t)strtol(entry, &next, 10); + if (next == NULL) + break; + entry = next; + } + } + } + } +#endif /* RTE_SCHED_RED */ for (i = 0; i < MAX_SCHED_SUBPORTS; i++) { char sec_name[CFG_NAME_LEN]; snprintf(sec_name, sizeof(sec_name), "subport %d", i); if (rte_cfgfile_has_section(cfg, sec_name)) { + entry = rte_cfgfile_get_entry(cfg, sec_name, + "number of pipes per subport"); + if (entry) + subport_params[i].n_pipes_per_subport = + (uint32_t)atoi(entry); + + entry = rte_cfgfile_get_entry(cfg, sec_name, "queue sizes"); + if (entry) { + char *next; + + for (j = 0; j < RTE_SCHED_TRAFFIC_CLASS_BE; j++) { + subport_params[i].qsize[j] = + (uint16_t)strtol(entry, &next, 10); + if (subport_params[i].qsize[j] != 0) { + active_queues[n_active_queues] = j; + n_active_queues++; + } + if (next == NULL) + break; + entry = next; + } + + subport_params[i].qsize[RTE_SCHED_TRAFFIC_CLASS_BE]= + (uint16_t)strtol(entry, &next, 10); + + for (j = 0; j < RTE_SCHED_BE_QUEUES_PER_PIPE; j++) { + active_queues[n_active_queues] = + RTE_SCHED_TRAFFIC_CLASS_BE + j; + n_active_queues++; + } + } + entry = rte_cfgfile_get_entry(cfg, sec_name, "tb rate"); if (entry) subport_params[i].tb_rate = (uint32_t)atoi(entry); @@ -362,6 +367,20 @@ cfg_load_subport(struct rte_cfgfile *cfg, struct rte_sched_subport_params *subpo } } } +#ifdef RTE_SCHED_RED + for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { + for (k = 0; k < RTE_COLORS; k++) { + subport_params[i].red_params[j][k].min_th = + red_params[j][k].min_th; + subport_params[i].red_params[j][k].max_th = + red_params[j][k].max_th; + subport_params[i].red_params[j][k].maxp_inv = + red_params[j][k].maxp_inv; + subport_params[i].red_params[j][k].wq_log2 = + red_params[j][k].wq_log2; + } + } +#endif } } diff --git a/examples/qos_sched/init.c b/examples/qos_sched/init.c index b05206d5a..c18eea98c 100644 --- a/examples/qos_sched/init.c +++ b/examples/qos_sched/init.c @@ -165,18 +165,6 @@ app_init_port(uint16_t portid, struct rte_mempool *mp) return 0; } -static struct rte_sched_subport_params subport_params[MAX_SCHED_SUBPORTS] = { - { - .tb_rate = 1250000000, - .tb_size = 1000000, - - .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000, - 1250000000, 1250000000, 1250000000, 1250000000, 1250000000, - 1250000000, 1250000000, 1250000000, 1250000000}, - .tc_period = 10, - }, -}; - static struct rte_sched_pipe_params pipe_profiles[MAX_SCHED_PIPE_PROFILES] = { { /* Profile #0 */ .tb_rate = 305175, @@ -193,19 +181,20 @@ static struct rte_sched_pipe_params pipe_profiles[MAX_SCHED_PIPE_PROFILES] = { }, }; -struct rte_sched_port_params port_params = { - .name = "port_scheduler_0", - .socket = 0, /* computed */ - .rate = 0, /* computed */ - .mtu = 6 + 6 + 4 + 4 + 2 + 1500, - .frame_overhead = RTE_SCHED_FRAME_OVERHEAD_DEFAULT, - .n_subports_per_port = 1, - .n_pipes_per_subport = 4096, - .qsize = {64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}, - .pipe_profiles = pipe_profiles, - .n_pipe_profiles = sizeof(pipe_profiles) / sizeof(struct rte_sched_pipe_params), - .n_max_pipe_profiles = MAX_SCHED_PIPE_PROFILES, +struct rte_sched_subport_params subport_params[MAX_SCHED_SUBPORTS] = { + { + .tb_rate = 1250000000, + .tb_size = 1000000, + .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000, + 1250000000, 1250000000, 1250000000, 1250000000, 1250000000, + 1250000000, 1250000000, 1250000000, 1250000000}, + .tc_period = 10, + .n_pipes_per_subport = 4096, + .qsize = {64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}, + .pipe_profiles = pipe_profiles, + .n_pipe_profiles = sizeof(pipe_profiles) / + sizeof(struct rte_sched_pipe_params), #ifdef RTE_SCHED_RED .red_params = { /* Traffic Class 0 Colors Green / Yellow / Red */ @@ -274,6 +263,18 @@ struct rte_sched_port_params port_params = { [12][2] = {.min_th = 32, .max_th = 64, .maxp_inv = 10, .wq_log2 = 9}, }, #endif /* RTE_SCHED_RED */ + }, +}; + +struct rte_sched_port_params port_params = { + .name = "port_scheduler_0", + .socket = 0, /* computed */ + .rate = 0, /* computed */ + .mtu = 6 + 6 + 4 + 4 + 2 + 1500, + .frame_overhead = RTE_SCHED_FRAME_OVERHEAD_DEFAULT, + .n_subports_per_port = 1, + .n_max_pipes_per_subport = MAX_SCHED_PIPES, + .n_max_pipe_profiles = MAX_SCHED_PIPE_PROFILES, }; static struct rte_sched_port * @@ -304,7 +305,10 @@ app_init_sched_port(uint32_t portid, uint32_t socketid) subport, err); } - for (pipe = 0; pipe < port_params.n_pipes_per_subport; pipe++) { + uint32_t n_pipes_per_subport = + subport_params[subport].n_pipes_per_subport; + + for (pipe = 0; pipe < n_pipes_per_subport; pipe++) { if (app_pipe_to_profile[subport][pipe] != -1) { err = rte_sched_pipe_config(port, subport, pipe, app_pipe_to_profile[subport][pipe]); diff --git a/examples/qos_sched/main.h b/examples/qos_sched/main.h index d8f890b64..baa2b3ead 100644 --- a/examples/qos_sched/main.h +++ b/examples/qos_sched/main.h @@ -152,6 +152,7 @@ uint32_t active_queues[RTE_SCHED_QUEUES_PER_PIPE]; uint32_t n_active_queues; extern struct rte_sched_port_params port_params; +extern struct rte_sched_subport_params subport_params[MAX_SCHED_SUBPORTS]; int app_parse_args(int argc, char **argv); int app_init(void); diff --git a/examples/qos_sched/profile.cfg b/examples/qos_sched/profile.cfg index 335561370..61b8b7071 100644 --- a/examples/qos_sched/profile.cfg +++ b/examples/qos_sched/profile.cfg @@ -20,11 +20,12 @@ [port] frame overhead = 24 number of subports per port = 1 -number of pipes per subport = 4096 -queue sizes = 64 64 64 64 64 64 64 64 64 64 64 64 64 ; Subport configuration [subport 0] +number of pipes per subport = 4096 +queue sizes = 64 64 64 64 64 64 64 64 64 64 64 64 64 + tb rate = 1250000000 ; Bytes per second tb size = 1000000 ; Bytes diff --git a/examples/qos_sched/profile_ov.cfg b/examples/qos_sched/profile_ov.cfg index 394987399..ab509d28d 100644 --- a/examples/qos_sched/profile_ov.cfg +++ b/examples/qos_sched/profile_ov.cfg @@ -5,11 +5,12 @@ [port] frame overhead = 24 number of subports per port = 1 -number of pipes per subport = 32 -queue sizes = 64 64 64 64 64 64 64 64 64 64 64 64 64 ; Subport configuration [subport 0] +number of pipes per subport = 32 +queue sizes = 64 64 64 64 64 64 64 64 64 64 64 64 64 + tb rate = 8400000 ; Bytes per second tb size = 100000 ; Bytes diff --git a/examples/qos_sched/stats.c b/examples/qos_sched/stats.c index e62e4a2f6..0626cf6e6 100644 --- a/examples/qos_sched/stats.c +++ b/examples/qos_sched/stats.c @@ -24,7 +24,7 @@ qavg_q(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id, uint8_t tc, if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || - pipe_id >= port_params.n_pipes_per_subport || + pipe_id >= subport_params[subport_id].n_pipes_per_subport || tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE || q >= RTE_SCHED_BE_QUEUES_PER_PIPE || (tc < RTE_SCHED_TRAFFIC_CLASS_BE && q > 0)) @@ -32,7 +32,7 @@ qavg_q(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id, uint8_t tc, port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - queue_id += port_params.n_pipes_per_subport * + queue_id += subport_params[i].n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; if (tc < RTE_SCHED_TRAFFIC_CLASS_BE) queue_id += pipe_id * RTE_SCHED_QUEUES_PER_PIPE + tc; @@ -69,14 +69,15 @@ qavg_tcpipe(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id, } if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || - pipe_id >= port_params.n_pipes_per_subport || + pipe_id >= subport_params[subport_id].n_pipes_per_subport || tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE) return -1; port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - queue_id += port_params.n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; + queue_id += + subport_params[i].n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; queue_id += pipe_id * RTE_SCHED_QUEUES_PER_PIPE + tc; @@ -123,13 +124,13 @@ qavg_pipe(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id) if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || - pipe_id >= port_params.n_pipes_per_subport) + pipe_id >= subport_params[subport_id].n_pipes_per_subport) return -1; port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - queue_id += port_params.n_pipes_per_subport * + queue_id += subport_params[i].n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; queue_id += pipe_id * RTE_SCHED_QUEUES_PER_PIPE; @@ -177,13 +178,13 @@ qavg_tcsubport(uint16_t port_id, uint32_t subport_id, uint8_t tc) for (i = 0; i < subport_id; i++) subport_queue_id += - port_params.n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; + subport_params[i].n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; average = 0; for (count = 0; count < qavg_ntimes; count++) { part_average = 0; - for (i = 0; i < port_params.n_pipes_per_subport; i++) { + for (i = 0; i < subport_params[subport_id].n_pipes_per_subport; i++) { if (tc < RTE_SCHED_TRAFFIC_CLASS_BE) { queue_id = subport_queue_id + i * RTE_SCHED_QUEUES_PER_PIPE + tc; @@ -203,10 +204,11 @@ qavg_tcsubport(uint16_t port_id, uint32_t subport_id, uint8_t tc) } if (tc < RTE_SCHED_TRAFFIC_CLASS_BE) - average += part_average / (port_params.n_pipes_per_subport); + average += part_average / + (subport_params[subport_id].n_pipes_per_subport); else - average += - part_average / (port_params.n_pipes_per_subport) * + average += part_average / + (subport_params[subport_id].n_pipes_per_subport) * RTE_SCHED_BE_QUEUES_PER_PIPE; usleep(qavg_period); @@ -240,14 +242,14 @@ qavg_subport(uint16_t port_id, uint32_t subport_id) port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - subport_queue_id += port_params.n_pipes_per_subport * + subport_queue_id += subport_params[i].n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; average = 0; for (count = 0; count < qavg_ntimes; count++) { part_average = 0; - for (i = 0; i < port_params.n_pipes_per_subport; i++) { + for (i = 0; i < subport_params[subport_id].n_pipes_per_subport; i++) { queue_id = subport_queue_id + i * RTE_SCHED_QUEUES_PER_PIPE; for (j = 0; j < RTE_SCHED_QUEUES_PER_PIPE; j++) { @@ -258,7 +260,8 @@ qavg_subport(uint16_t port_id, uint32_t subport_id) } average += part_average / - (port_params.n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE); + (subport_params[subport_id].n_pipes_per_subport * + RTE_SCHED_QUEUES_PER_PIPE); usleep(qavg_period); } @@ -322,12 +325,13 @@ pipe_stat(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id) if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || - pipe_id >= port_params.n_pipes_per_subport) + pipe_id >= subport_params[subport_id].n_pipes_per_subport) return -1; port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - queue_id += port_params.n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; + queue_id += subport_params[i].n_pipes_per_subport * + RTE_SCHED_QUEUES_PER_PIPE; queue_id += pipe_id * RTE_SCHED_QUEUES_PER_PIPE; -- 2.21.0
Remove redundant data structure fields from port level data structures and update release notes. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- doc/guides/rel_notes/release_19_11.rst | 6 +++- lib/librte_sched/rte_sched.c | 43 +------------------------- lib/librte_sched/rte_sched.h | 22 ------------- 3 files changed, 6 insertions(+), 65 deletions(-) diff --git a/doc/guides/rel_notes/release_19_11.rst b/doc/guides/rel_notes/release_19_11.rst index 8490d897c..746aeb0ea 100644 --- a/doc/guides/rel_notes/release_19_11.rst +++ b/doc/guides/rel_notes/release_19_11.rst @@ -85,6 +85,10 @@ API Changes Also, make sure to start the actual text at the margin. ========================================================= +* sched: The pipe nodes configuration parameters such as number of pipes, + pipe queue sizes, pipe profiles, etc., are moved from port level structure + to subport level. This allows different subports of the same port to + have different configuration for the pipe nodes. ABI Changes ----------- @@ -172,7 +176,7 @@ The libraries prepended with a plus sign were incremented in this version. librte_rcu.so.1 librte_reorder.so.1 librte_ring.so.2 - librte_sched.so.3 + + librte_sched.so.4 librte_security.so.2 librte_stack.so.1 librte_table.so.3 diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 8a7727286..ba504da1e 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -207,10 +207,8 @@ struct rte_sched_subport { struct rte_sched_port { /* User parameters */ uint32_t n_subports_per_port; - uint32_t n_pipes_per_subport; uint32_t n_max_pipes_per_subport; uint32_t n_max_pipes_per_subport_log2; - uint32_t n_pipes_per_subport_log2; 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]; @@ -218,13 +216,7 @@ struct rte_sched_port { uint32_t mtu; uint32_t frame_overhead; int socket; - uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - uint32_t n_pipe_profiles; uint32_t n_max_pipe_profiles; - uint32_t pipe_tc_be_rate_max; -#ifdef RTE_SCHED_RED - struct rte_red_config red_config[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; -#endif /* Timing */ uint64_t time_cpu_cycles; /* Current CPU time measured in CPU cyles */ @@ -232,48 +224,15 @@ struct rte_sched_port { uint64_t time; /* Current NIC TX time measured in bytes */ struct rte_reciprocal inv_cycles_per_byte; /* CPU cycles per byte */ - /* Scheduling loop detection */ - uint32_t pipe_loop; - uint32_t pipe_exhaustion; - - /* Bitmap */ - struct rte_bitmap *bmp; - uint32_t grinder_base_bmp_pos[RTE_SCHED_PORT_N_GRINDERS] __rte_aligned_16; - /* Grinders */ - struct rte_sched_grinder grinder[RTE_SCHED_PORT_N_GRINDERS]; - uint32_t busy_grinders; struct rte_mbuf **pkts_out; uint32_t n_pkts_out; uint32_t subport_id; - /* Queue base calculation */ - uint32_t qsize_add[RTE_SCHED_QUEUES_PER_PIPE]; - uint32_t qsize_sum; - /* Large data structures */ - struct rte_sched_subport *subports[0]; - struct rte_sched_subport *subport; - struct rte_sched_pipe *pipe; - struct rte_sched_queue *queue; - struct rte_sched_queue_extra *queue_extra; - struct rte_sched_pipe_profile *pipe_profiles; - uint8_t *bmp_array; - struct rte_mbuf **queue_array; - uint8_t memory[0] __rte_cache_aligned; + struct rte_sched_subport *subports[0] __rte_cache_aligned; } __rte_cache_aligned; -enum rte_sched_port_array { - e_RTE_SCHED_PORT_ARRAY_SUBPORT = 0, - e_RTE_SCHED_PORT_ARRAY_PIPE, - e_RTE_SCHED_PORT_ARRAY_QUEUE, - e_RTE_SCHED_PORT_ARRAY_QUEUE_EXTRA, - e_RTE_SCHED_PORT_ARRAY_PIPE_PROFILES, - e_RTE_SCHED_PORT_ARRAY_BMP_ARRAY, - e_RTE_SCHED_PORT_ARRAY_QUEUE_ARRAY, - e_RTE_SCHED_PORT_ARRAY_TOTAL, -}; - enum rte_sched_subport_array { e_RTE_SCHED_SUBPORT_ARRAY_PIPE = 0, e_RTE_SCHED_SUBPORT_ARRAY_QUEUE, diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index ea2b07448..db1b0232f 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -246,33 +246,11 @@ struct rte_sched_port_params { /** Number of subports */ uint32_t n_subports_per_port; - /** Number of subport_pipes */ - uint32_t n_pipes_per_subport; - /** Maximum number of subport_pipes */ uint32_t n_max_pipes_per_subport; - /** Packet queue size for each traffic class. - * All the pipes within the same subport share the similar - * configuration for the queues. - */ - uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - - /** Pipe profile table. - * Every pipe is configured using one of the profiles from this table. - */ - struct rte_sched_pipe_params *pipe_profiles; - - /** Profiles in the pipe profile table */ - uint32_t n_pipe_profiles; - /** Max profiles allowed in the pipe profile table */ uint32_t n_max_pipe_profiles; - -#ifdef RTE_SCHED_RED - /** RED parameters */ - struct rte_red_params red_params[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; -#endif }; /* -- 2.21.0
Hi Jasvinder,
> -----Original Message-----
> From: Singh, Jasvinder
> Sent: Monday, September 9, 2019 11:05 AM
> To: dev@dpdk.org
> Cc: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>
> Subject: [PATCH v2 00/15] sched: subport level configuration of pipe nodes
>
> This patchset refactors the dpdk qos sched library to allow subport
> level configuration flexibility of the pipe nodes.
>
> Currently, all parameters for the pipe nodes (subscribers)
> configuration are part of the port level structure which forces
> all groups of subscribers (pipes) in different subports to
> have similar configurations in terms of their number, queue sizes,
> traffic-classes, etc.
>
> The new implementation moves pipe nodes configuration parameters
> from port level to subport level structure. This allows different
> subports of the same port to have different configuration for the
> pipe nodes, for examples- number of pipes, queue sizes, pipe
> profiles, etc.
>
> In order to keep the implementation complexity under control, all
> pipes within the same subport share the same configuration for queue
> sizes.
>
> v2:
> - fix qsize parsing in sample application
> - fix checkpatch warnings
>
> Jasvinder Singh (15):
> sched: add pipe config params to subport struct
> sched: modify internal structs for config flexibility
> sched: remove pipe params config from port level
> shced: add pipe config to subport level
> sched: modify pipe functions for config flexibility
> sched: modify pkt enqueue for config flexibility
> sched: update memory compute to support flexiblity
> sched: update grinder functions for config flexibility
> sched: update pkt dequeue for flexible config
> sched: update queue stats read for config flexibility
> test/sched: modify tests for subport config flexibility
> net/softnic: add subport config flexibility to TM
> ip_pipeline: add subport config flexibility to TM
> examples/qos_sched: add subport configuration flexibility
> sched: remove redundant code
>
> app/test/test_sched.c | 35 +-
> doc/guides/rel_notes/release_19_11.rst | 6 +-
> drivers/net/softnic/rte_eth_softnic_tm.c | 51 +-
> examples/ip_pipeline/cli.c | 71 +-
> examples/ip_pipeline/tmgr.c | 23 +-
> examples/ip_pipeline/tmgr.h | 7 +-
> examples/qos_sched/app_thread.c | 4 +-
> examples/qos_sched/cfg_file.c | 229 ++--
> examples/qos_sched/init.c | 54 +-
> examples/qos_sched/main.h | 1 +
> examples/qos_sched/profile.cfg | 5 +-
> examples/qos_sched/profile_ov.cfg | 5 +-
> examples/qos_sched/stats.c | 36 +-
> lib/librte_sched/Makefile | 2 +-
> lib/librte_sched/meson.build | 2 +-
> lib/librte_sched/rte_sched.c | 1400 +++++++++++++---------
> lib/librte_sched/rte_sched.h | 114 +-
> 17 files changed, 1183 insertions(+), 862 deletions(-)
>
> --
> 2.21.0
Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
A few comments/suggestion, mainly on some API name changes:
1. We need a good comment explaining the difference between rte_sched_port_params::n_max_pipes_per_subport and rte_sched_subport_params::n_pipes_per_subport. The former reserves a fixed number of bits in struct rte_mbuf::sched.queue_id for the pipe_id for all the subports of the same port, while the latter provides a mechanism to enable/allocate fewer pipes for each subport, as needed, with the benefit of avoiding memory allocation for the queues of the pipes that are not really needed. Another way to look at it is to say all subports have the same number of pipes (n_max_pipes_per_subport), but some of these pipes might not be implemented by all the subports. Maybe we should name the port parameter as n_pipes_per_subport and the subport parameter as n_pipes_per_subport_enabled?
PS: I did check the critical functions rte_sched_port_qindex() and rte_sched_port_pkt_read_tree_path(), and they look good to me.
2. The rte_sched_PORT_pipe_profile_add() should probably be now renamed as rte_sched_SUBPORT_pipe_profile_add(), right?
3. The port parameter n_max_pipe_profiles does not make sense to me, as we are now introducing the n_pipe_profiles subport parameter. Is this a code leftover or is this used to simplify the memory allocation? Assuming the latter, my vote is to remove it.
Regards,
Cristian
> -----Original Message----- > From: Dumitrescu, Cristian > Sent: Monday, September 23, 2019 2:06 PM > To: Singh, Jasvinder <jasvinder.singh@intel.com>; dev@dpdk.org > Subject: RE: [PATCH v2 00/15] sched: subport level configuration of pipe nodes > > Hi Jasvinder, > > > -----Original Message----- > > From: Singh, Jasvinder > > Sent: Monday, September 9, 2019 11:05 AM > > To: dev@dpdk.org > > Cc: Dumitrescu, Cristian <cristian.dumitrescu@intel.com> > > Subject: [PATCH v2 00/15] sched: subport level configuration of pipe > > nodes > > > > This patchset refactors the dpdk qos sched library to allow subport > > level configuration flexibility of the pipe nodes. > > > > Currently, all parameters for the pipe nodes (subscribers) > > configuration are part of the port level structure which forces all > > groups of subscribers (pipes) in different subports to have similar > > configurations in terms of their number, queue sizes, traffic-classes, > > etc. > > > > The new implementation moves pipe nodes configuration parameters from > > port level to subport level structure. This allows different subports > > of the same port to have different configuration for the pipe nodes, > > for examples- number of pipes, queue sizes, pipe profiles, etc. > > > > In order to keep the implementation complexity under control, all > > pipes within the same subport share the same configuration for queue > > sizes. > > > > v2: > > - fix qsize parsing in sample application > > - fix checkpatch warnings > > > > Jasvinder Singh (15): > > sched: add pipe config params to subport struct > > sched: modify internal structs for config flexibility > > sched: remove pipe params config from port level > > shced: add pipe config to subport level > > sched: modify pipe functions for config flexibility > > sched: modify pkt enqueue for config flexibility > > sched: update memory compute to support flexiblity > > sched: update grinder functions for config flexibility > > sched: update pkt dequeue for flexible config > > sched: update queue stats read for config flexibility > > test/sched: modify tests for subport config flexibility > > net/softnic: add subport config flexibility to TM > > ip_pipeline: add subport config flexibility to TM > > examples/qos_sched: add subport configuration flexibility > > sched: remove redundant code > > > > app/test/test_sched.c | 35 +- > > doc/guides/rel_notes/release_19_11.rst | 6 +- > > drivers/net/softnic/rte_eth_softnic_tm.c | 51 +- > > examples/ip_pipeline/cli.c | 71 +- > > examples/ip_pipeline/tmgr.c | 23 +- > > examples/ip_pipeline/tmgr.h | 7 +- > > examples/qos_sched/app_thread.c | 4 +- > > examples/qos_sched/cfg_file.c | 229 ++-- > > examples/qos_sched/init.c | 54 +- > > examples/qos_sched/main.h | 1 + > > examples/qos_sched/profile.cfg | 5 +- > > examples/qos_sched/profile_ov.cfg | 5 +- > > examples/qos_sched/stats.c | 36 +- > > lib/librte_sched/Makefile | 2 +- > > lib/librte_sched/meson.build | 2 +- > > lib/librte_sched/rte_sched.c | 1400 +++++++++++++--------- > > lib/librte_sched/rte_sched.h | 114 +- > > 17 files changed, 1183 insertions(+), 862 deletions(-) > > > > -- > > 2.21.0 > > Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com> > > A few comments/suggestion, mainly on some API name changes: > > 1. We need a good comment explaining the difference between > rte_sched_port_params::n_max_pipes_per_subport and > rte_sched_subport_params::n_pipes_per_subport. The former reserves a fixed > number of bits in struct rte_mbuf::sched.queue_id for the pipe_id for all the > subports of the same port, while the latter provides a mechanism to > enable/allocate fewer pipes for each subport, as needed, with the benefit of > avoiding memory allocation for the queues of the pipes that are not really > needed. Another way to look at it is to say all subports have the same number > of pipes (n_max_pipes_per_subport), but some of these pipes might not be > implemented by all the subports. I will improve doxygen comments as suggested above, thanks. Maybe we should name the port parameter > as n_pipes_per_subport and the subport parameter as > n_pipes_per_subport_enabled? Will rename these parameters as suggested. > PS: I did check the critical functions rte_sched_port_qindex() and > rte_sched_port_pkt_read_tree_path(), and they look good to me. > > 2. The rte_sched_PORT_pipe_profile_add() should probably be now renamed > as rte_sched_SUBPORT_pipe_profile_add(), right? Thanks for spotting this :) > 3. The port parameter n_max_pipe_profiles does not make sense to me, as we > are now introducing the n_pipe_profiles subport parameter. Is this a code > leftover or is this used to simplify the memory allocation? Assuming the latter, > my vote is to remove it. I will remove this field from the port structure. Thank you once again for review and comments, will fix above in v3 version. Jasvinder
This patchset refactors the dpdk qos sched library to allow subport level configuration flexibility of the pipe nodes. Currently, all parameters for the pipe nodes (subscribers) configuration are part of the port level structure which forces all groups of subscribers (pipes) in different subports to have similar configurations in terms of their number, queue sizes, traffic-classes, etc. The new implementation moves pipe nodes configuration parameters from port level to subport level structure. This allows different subports of the same port to have different configuration for the pipe nodes, for examples- number of pipes, queue sizes, pipe profiles, etc. In order to keep the implementation complexity under control, all pipes within the same subport share the same configuration for queue sizes. Acked-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com> v3: - improve doxygen comments - remove n_max_pipe_profiles parameter from struct rte_sched_port_params - rename n_max_pipes_per_subport in struct rte_sched_port_params to n_pipes_per_subport - rename n_pipes_per_subport in struct rte_sched_subport_params to n_pipes_per_subport_enabled - rename rte_sched_port_pipe_profile_add() to rte_sched_subport_pipe_profile_add() v2: - fix qsize parsing in sample application - fix checkpatch warnings Jasvinder Singh (15): sched: add pipe config params to subport struct sched: modify internal structs for config flexibility sched: remove pipe params config from port level shced: add pipe config to subport level sched: modify pipe functions for config flexibility sched: modify pkt enqueue for config flexibility sched: update memory compute to support flexiblity sched: update grinder functions for config flexibility sched: update pkt dequeue for flexible config sched: update queue stats read for config flexibility test/sched: modify tests for subport config flexibility net/softnic: add subport config flexibility to TM ip_pipeline: add subport config flexibility to TM examples/qos_sched: add subport configuration flexibility sched: remove redundant code app/test/test_sched.c | 35 +- doc/guides/rel_notes/release_19_11.rst | 6 +- drivers/net/softnic/rte_eth_softnic_tm.c | 54 +- examples/ip_pipeline/cli.c | 71 +- examples/ip_pipeline/tmgr.c | 25 +- examples/ip_pipeline/tmgr.h | 7 +- examples/qos_sched/app_thread.c | 20 +- examples/qos_sched/cfg_file.c | 229 ++-- examples/qos_sched/init.c | 54 +- examples/qos_sched/main.h | 1 + examples/qos_sched/profile.cfg | 5 +- examples/qos_sched/profile_ov.cfg | 5 +- examples/qos_sched/stats.c | 44 +- lib/librte_sched/Makefile | 2 +- lib/librte_sched/meson.build | 2 +- lib/librte_sched/rte_sched.c | 1394 +++++++++++++--------- lib/librte_sched/rte_sched.h | 129 +- lib/librte_sched/rte_sched_version.map | 2 +- 18 files changed, 1212 insertions(+), 873 deletions(-) -- 2.21.0
Add pipe configuration parameters to subport level structure to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/Makefile | 2 +- lib/librte_sched/meson.build | 2 +- lib/librte_sched/rte_sched.h | 92 ++++++++++++++++++++++++------------ 3 files changed, 65 insertions(+), 31 deletions(-) diff --git a/lib/librte_sched/Makefile b/lib/librte_sched/Makefile index 3d7f410e1..6e4a72d89 100644 --- a/lib/librte_sched/Makefile +++ b/lib/librte_sched/Makefile @@ -18,7 +18,7 @@ LDLIBS += -lrte_timer EXPORT_MAP := rte_sched_version.map -LIBABIVER := 3 +LIBABIVER := 4 # # all source are stored in SRCS-y diff --git a/lib/librte_sched/meson.build b/lib/librte_sched/meson.build index 59d43c6d8..9f40a2368 100644 --- a/lib/librte_sched/meson.build +++ b/lib/librte_sched/meson.build @@ -1,7 +1,7 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2017 Intel Corporation -version = 3 +version = 4 sources = files('rte_sched.c', 'rte_red.c', 'rte_approx.c') headers = files('rte_sched.h', 'rte_sched_common.h', 'rte_red.h', 'rte_approx.h') diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index eac6db274..fbb0e23fa 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -111,7 +111,7 @@ extern "C" { #endif /* - * Subport configuration parameters. The period and credits_per_period + * Pipe configuration parameters. The period and credits_per_period * parameters are measured in bytes, with one byte meaning the time * duration associated with the transmission of one byte on the * physical medium of the output port, with pipe or pipe traffic class @@ -119,7 +119,7 @@ extern "C" { * credits_per_period divided by period. One credit represents one * byte. */ -struct rte_sched_subport_params { +struct rte_sched_pipe_params { /** Token bucket rate (measured in bytes per second) */ uint32_t tb_rate; @@ -129,32 +129,18 @@ struct rte_sched_subport_params { /** Traffic class rates (measured in bytes per second) */ uint32_t tc_rate[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - /** Enforcement period for rates (measured in milliseconds) */ + /** Enforcement period (measured in milliseconds) */ uint32_t tc_period; -}; - -/** Subport statistics */ -struct rte_sched_subport_stats { - /** Number of packets successfully written */ - uint32_t n_pkts_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - - /** Number of packets dropped */ - uint32_t n_pkts_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - /** Number of bytes successfully written for each traffic class */ - uint32_t n_bytes_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - - /** Number of bytes dropped for each traffic class */ - uint32_t n_bytes_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + /** Best-effort traffic class oversubscription weight */ + uint8_t tc_ov_weight; -#ifdef RTE_SCHED_RED - /** Number of packets dropped by red */ - uint32_t n_pkts_red_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; -#endif + /** WRR weights of best-effort traffic class queues */ + uint8_t wrr_weights[RTE_SCHED_BE_QUEUES_PER_PIPE]; }; /* - * Pipe configuration parameters. The period and credits_per_period + * Subport configuration parameters. The period and credits_per_period * parameters are measured in bytes, with one byte meaning the time * duration associated with the transmission of one byte on the * physical medium of the output port, with pipe or pipe traffic class @@ -162,7 +148,7 @@ struct rte_sched_subport_stats { * credits_per_period divided by period. One credit represents one * byte. */ -struct rte_sched_pipe_params { +struct rte_sched_subport_params { /** Token bucket rate (measured in bytes per second) */ uint32_t tb_rate; @@ -172,14 +158,58 @@ struct rte_sched_pipe_params { /** Traffic class rates (measured in bytes per second) */ uint32_t tc_rate[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - /** Enforcement period (measured in milliseconds) */ + /** Enforcement period for rates (measured in milliseconds) */ uint32_t tc_period; - /** Best-effort traffic class oversubscription weight */ - uint8_t tc_ov_weight; + /** Number of subport pipes. + * The subport can enable/allocate fewer pipes than the maximum + * number set through struct port_params::n_max_pipes_per_subport, + * as needed, to avoid memory allocation for the queues of the + * pipes that are not really needed. + */ + uint32_t n_pipes_per_subport_enabled; - /** WRR weights of best-effort traffic class queues */ - uint8_t wrr_weights[RTE_SCHED_BE_QUEUES_PER_PIPE]; + /** Packet queue size for each traffic class. + * All the pipes within the same subport share the similar + * configuration for the queues. + */ + uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + + /** Pipe profile table. + * Every pipe is configured using one of the profiles from this table. + */ + struct rte_sched_pipe_params *pipe_profiles; + + /** Profiles in the pipe profile table */ + uint32_t n_pipe_profiles; + + /** Max allowed profiles in the pipe profile table */ + uint32_t n_max_pipe_profiles; + +#ifdef RTE_SCHED_RED + /** RED parameters */ + struct rte_red_params red_params[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; +#endif +}; + +/** Subport statistics */ +struct rte_sched_subport_stats { + /** Number of packets successfully written */ + uint32_t n_pkts_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + + /** Number of packets dropped */ + uint32_t n_pkts_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + + /** Number of bytes successfully written for each traffic class */ + uint32_t n_bytes_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + + /** Number of bytes dropped for each traffic class */ + uint32_t n_bytes_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + +#ifdef RTE_SCHED_RED + /** Number of packets dropped by red */ + uint32_t n_pkts_red_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; +#endif }; /** Queue statistics */ @@ -224,7 +254,11 @@ struct rte_sched_port_params { /** Number of subports */ uint32_t n_subports_per_port; - /** Number of subport_pipes */ + /** 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 + * the subports of the same port. + */ uint32_t n_pipes_per_subport; /** Packet queue size for each traffic class. -- 2.21.0
Update internal structures related to port and subport to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 106 ++++++++++++++++++++++++++--------- 1 file changed, 78 insertions(+), 28 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index d8ab21d64..672412b77 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -47,33 +47,6 @@ */ #define RTE_SCHED_TIME_SHIFT 8 -struct rte_sched_subport { - /* Token bucket (TB) */ - uint64_t tb_time; /* time of last update */ - uint32_t tb_period; - uint32_t tb_credits_per_period; - uint32_t tb_size; - uint32_t tb_credits; - - /* Traffic classes (TCs) */ - uint64_t tc_time; /* time of next update */ - uint32_t tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - uint32_t tc_credits[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - uint32_t tc_period; - - /* TC oversubscription */ - uint32_t tc_ov_wm; - uint32_t tc_ov_wm_min; - uint32_t tc_ov_wm_max; - uint8_t tc_ov_period_id; - uint8_t tc_ov; - uint32_t tc_ov_n; - double tc_ov_rate; - - /* Statistics */ - struct rte_sched_subport_stats stats; -}; - struct rte_sched_pipe_profile { /* Token bucket (TB) */ uint32_t tb_period; @@ -107,7 +80,6 @@ struct rte_sched_pipe { /* TC oversubscription */ uint32_t tc_ov_credits; uint8_t tc_ov_period_id; - uint8_t reserved[3]; } __rte_cache_aligned; struct rte_sched_queue { @@ -166,6 +138,72 @@ struct rte_sched_grinder { uint8_t wrr_cost[RTE_SCHED_BE_QUEUES_PER_PIPE]; }; +struct rte_sched_subport { + /* Token bucket (TB) */ + uint64_t tb_time; /* time of last update */ + uint32_t tb_period; + uint32_t tb_credits_per_period; + uint32_t tb_size; + uint32_t tb_credits; + + /* Traffic classes (TCs) */ + uint64_t tc_time; /* time of next update */ + uint32_t tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + uint32_t tc_credits[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + uint32_t tc_period; + + /* TC oversubscription */ + uint32_t tc_ov_wm; + uint32_t tc_ov_wm_min; + uint32_t tc_ov_wm_max; + uint8_t tc_ov_period_id; + uint8_t tc_ov; + uint32_t tc_ov_n; + double tc_ov_rate; + + /* Statistics */ + struct rte_sched_subport_stats stats; + + /* Subport pipes */ + uint32_t n_pipes_per_subport_enabled; + uint32_t n_pipe_profiles; + uint32_t n_max_pipe_profiles; + + /* Pipe best-effort TC rate */ + uint32_t pipe_tc_be_rate_max; + + /* Pipe queues size */ + uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + +#ifdef RTE_SCHED_RED + struct rte_red_config red_config[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; +#endif + + /* Scheduling loop detection */ + uint32_t pipe_loop; + uint32_t pipe_exhaustion; + + /* Bitmap */ + struct rte_bitmap *bmp; + uint32_t grinder_base_bmp_pos[RTE_SCHED_PORT_N_GRINDERS] __rte_aligned_16; + + /* Grinders */ + struct rte_sched_grinder grinder[RTE_SCHED_PORT_N_GRINDERS]; + uint32_t busy_grinders; + + /* Queue base calculation */ + uint32_t qsize_add[RTE_SCHED_QUEUES_PER_PIPE]; + uint32_t qsize_sum; + + struct rte_sched_pipe *pipe; + struct rte_sched_queue *queue; + struct rte_sched_queue_extra *queue_extra; + struct rte_sched_pipe_profile *pipe_profiles; + uint8_t *bmp_array; + struct rte_mbuf **queue_array; + uint8_t memory[0] __rte_cache_aligned; +} __rte_cache_aligned; + struct rte_sched_port { /* User parameters */ uint32_t n_subports_per_port; @@ -177,6 +215,7 @@ struct rte_sched_port { uint32_t rate; uint32_t mtu; uint32_t frame_overhead; + int socket; uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; uint32_t n_pipe_profiles; uint32_t n_max_pipe_profiles; @@ -210,6 +249,7 @@ struct rte_sched_port { uint32_t qsize_sum; /* Large data structures */ + struct rte_sched_subport *subports[0]; struct rte_sched_subport *subport; struct rte_sched_pipe *pipe; struct rte_sched_queue *queue; @@ -231,6 +271,16 @@ enum rte_sched_port_array { e_RTE_SCHED_PORT_ARRAY_TOTAL, }; +enum rte_sched_subport_array { + e_RTE_SCHED_SUBPORT_ARRAY_PIPE = 0, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_EXTRA, + e_RTE_SCHED_SUBPORT_ARRAY_PIPE_PROFILES, + e_RTE_SCHED_SUBPORT_ARRAY_BMP_ARRAY, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_ARRAY, + e_RTE_SCHED_SUBPORT_ARRAY_TOTAL, +}; + #ifdef RTE_SCHED_COLLECT_STATS static inline uint32_t -- 2.21.0
Remove pipes configuration from the port level to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 254 ++++++++++------------------------- 1 file changed, 71 insertions(+), 183 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 672412b77..952e449f7 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -291,6 +291,31 @@ rte_sched_port_queues_per_subport(struct rte_sched_port *port) #endif +static inline uint32_t +rte_sched_subport_pipe_queues(struct rte_sched_subport *subport) +{ + return RTE_SCHED_QUEUES_PER_PIPE * subport->n_pipes_per_subport_enabled; +} + +static inline struct rte_mbuf ** +rte_sched_subport_pipe_qbase(struct rte_sched_subport *subport, uint32_t qindex) +{ + uint32_t pindex = qindex >> 4; + uint32_t qpos = qindex & (RTE_SCHED_QUEUES_PER_PIPE - 1); + + return (subport->queue_array + pindex * + subport->qsize_sum + subport->qsize_add[qpos]); +} + +static inline uint16_t +rte_sched_subport_pipe_qsize(struct rte_sched_port *port, +struct rte_sched_subport *subport, uint32_t qindex) +{ + uint32_t tc = port->pipe_tc[qindex & (RTE_SCHED_QUEUES_PER_PIPE - 1)]; + + return subport->qsize[tc]; +} + static inline uint32_t rte_sched_port_queues_per_port(struct rte_sched_port *port) { @@ -414,8 +439,6 @@ pipe_profile_check(struct rte_sched_pipe_params *params, 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__); @@ -456,45 +479,10 @@ rte_sched_port_check_params(struct rte_sched_port_params *params) if (params->n_pipes_per_subport == 0 || !rte_is_power_of_2(params->n_pipes_per_subport)) { RTE_LOG(ERR, SCHED, - "%s: Incorrect value for pipes number\n", __func__); - return -EINVAL; - } - - /* qsize: if non-zero, power of 2, - * no bigger than 32K (due to 16-bit read/write pointers) - */ - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - uint16_t qsize = params->qsize[i]; - - if ((qsize != 0 && !rte_is_power_of_2(qsize)) || - ((i == RTE_SCHED_TRAFFIC_CLASS_BE) && (qsize == 0))) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tc rate\n", __func__); - return -EINVAL; - } - } - - /* pipe_profiles and n_pipe_profiles */ - if (params->pipe_profiles == NULL || - params->n_pipe_profiles == 0 || - params->n_pipe_profiles > params->n_max_pipe_profiles) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for number of pipe profiles\n", __func__); + "%s: Incorrect value for maximum pipes number\n", __func__); return -EINVAL; } - for (i = 0; i < params->n_pipe_profiles; i++) { - struct rte_sched_pipe_params *p = params->pipe_profiles + i; - int status; - - status = pipe_profile_check(p, params->rate, ¶ms->qsize[0]); - if (status != 0) { - RTE_LOG(ERR, SCHED, - "%s: Pipe profile check failed(%d)\n", __func__, status); - return -EINVAL; - } - } - return 0; } @@ -582,32 +570,6 @@ rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params) return size0 + size1; } -static void -rte_sched_port_config_qsize(struct rte_sched_port *port) -{ - uint32_t i; - - port->qsize_add[0] = 0; - - /* Strict prority traffic class */ - for (i = 1; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - port->qsize_add[i] = port->qsize_add[i-1] + port->qsize[i-1]; - - /* Best-effort traffic class */ - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 1] = - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE] + - port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 2] = - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 1] + - port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 3] = - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 2] + - port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; - - port->qsize_sum = port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 3] + - port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; -} - static void rte_sched_port_log_pipe_profile(struct rte_sched_port *port, uint32_t i) { @@ -717,56 +679,41 @@ rte_sched_pipe_profile_convert(struct rte_sched_port *port, dst->wrr_cost[3] = (uint8_t) wrr_cost[3]; } -static void -rte_sched_port_config_pipe_profile_table(struct rte_sched_port *port, - struct rte_sched_port_params *params) -{ - uint32_t i; - - for (i = 0; i < port->n_pipe_profiles; i++) { - struct rte_sched_pipe_params *src = params->pipe_profiles + i; - struct rte_sched_pipe_profile *dst = port->pipe_profiles + i; - - rte_sched_pipe_profile_convert(port, src, dst, params->rate); - rte_sched_port_log_pipe_profile(port, i); - } - - port->pipe_tc_be_rate_max = 0; - for (i = 0; i < port->n_pipe_profiles; i++) { - struct rte_sched_pipe_params *src = params->pipe_profiles + i; - uint32_t pipe_tc_be_rate = src->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; - - if (port->pipe_tc_be_rate_max < pipe_tc_be_rate) - port->pipe_tc_be_rate_max = pipe_tc_be_rate; - } -} - struct rte_sched_port * rte_sched_port_config(struct rte_sched_port_params *params) { struct rte_sched_port *port = NULL; - uint32_t mem_size, bmp_mem_size, n_queues_per_port, i, j, cycles_per_byte; + uint32_t size0, size1; + uint32_t cycles_per_byte; + uint32_t i, j; + int status; - /* Check user parameters. Determine the amount of memory to allocate */ - mem_size = rte_sched_port_get_memory_footprint(params); - if (mem_size == 0) + status = rte_sched_port_check_params(params); + if (status != 0) { + RTE_LOG(ERR, SCHED, + "%s: Port scheduler params check failed (%d)\n", + __func__, status); return NULL; + } + + size0 = sizeof(struct rte_sched_port); + size1 = params->n_subports_per_port * sizeof(struct rte_sched_subport *); /* Allocate memory to store the data structures */ - port = rte_zmalloc_socket("qos_params", mem_size, RTE_CACHE_LINE_SIZE, + port = rte_zmalloc_socket("qos_params", size0 + size1, RTE_CACHE_LINE_SIZE, params->socket); - if (port == NULL) - return NULL; + if (port == NULL) { + RTE_LOG(ERR, SCHED, "%s: Memory allocation fails\n", __func__); - /* compile time checks */ - RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS == 0); - RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS & (RTE_SCHED_PORT_N_GRINDERS - 1)); + return NULL; + } /* User parameters */ port->n_subports_per_port = params->n_subports_per_port; port->n_pipes_per_subport = params->n_pipes_per_subport; port->n_pipes_per_subport_log2 = __builtin_ctz(params->n_pipes_per_subport); + port->socket = params->socket; for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) port->pipe_queue[i] = i; @@ -787,32 +734,6 @@ rte_sched_port_config(struct rte_sched_port_params *params) port->rate = params->rate; port->mtu = params->mtu + params->frame_overhead; port->frame_overhead = params->frame_overhead; - memcpy(port->qsize, params->qsize, sizeof(params->qsize)); - port->n_pipe_profiles = params->n_pipe_profiles; - port->n_max_pipe_profiles = params->n_max_pipe_profiles; - -#ifdef RTE_SCHED_RED - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - uint32_t j; - - for (j = 0; j < RTE_COLORS; j++) { - /* if min/max are both zero, then RED is disabled */ - if ((params->red_params[i][j].min_th | - params->red_params[i][j].max_th) == 0) { - continue; - } - - if (rte_red_config_init(&port->red_config[i][j], - params->red_params[i][j].wq_log2, - params->red_params[i][j].min_th, - params->red_params[i][j].max_th, - params->red_params[i][j].maxp_inv) != 0) { - rte_free(port); - return NULL; - } - } - } -#endif /* Timing */ port->time_cpu_cycles = rte_get_tsc_cycles(); @@ -823,79 +744,32 @@ rte_sched_port_config(struct rte_sched_port_params *params) / params->rate; port->inv_cycles_per_byte = rte_reciprocal_value(cycles_per_byte); - /* Scheduling loop detection */ - port->pipe_loop = RTE_SCHED_PIPE_INVALID; - port->pipe_exhaustion = 0; - /* Grinders */ - port->busy_grinders = 0; port->pkts_out = NULL; port->n_pkts_out = 0; - /* Queue base calculation */ - rte_sched_port_config_qsize(port); - - /* Large data structures */ - port->subport = (struct rte_sched_subport *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_SUBPORT)); - port->pipe = (struct rte_sched_pipe *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_PIPE)); - port->queue = (struct rte_sched_queue *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_QUEUE)); - port->queue_extra = (struct rte_sched_queue_extra *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_QUEUE_EXTRA)); - port->pipe_profiles = (struct rte_sched_pipe_profile *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_PIPE_PROFILES)); - port->bmp_array = port->memory - + rte_sched_port_get_array_base(params, e_RTE_SCHED_PORT_ARRAY_BMP_ARRAY); - port->queue_array = (struct rte_mbuf **) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_QUEUE_ARRAY)); - - /* Pipe profile table */ - rte_sched_port_config_pipe_profile_table(port, params); - - /* Bitmap */ - n_queues_per_port = rte_sched_port_queues_per_port(port); - bmp_mem_size = rte_bitmap_get_memory_footprint(n_queues_per_port); - port->bmp = rte_bitmap_init(n_queues_per_port, port->bmp_array, - bmp_mem_size); - if (port->bmp == NULL) { - RTE_LOG(ERR, SCHED, "Bitmap init error\n"); - rte_free(port); - return NULL; - } - - for (i = 0; i < RTE_SCHED_PORT_N_GRINDERS; i++) - port->grinder_base_bmp_pos[i] = RTE_SCHED_PIPE_INVALID; - - return port; } -void -rte_sched_port_free(struct rte_sched_port *port) +static inline void +rte_sched_subport_free(struct rte_sched_port *port, + struct rte_sched_subport *subport) { + uint32_t n_subport_pipe_queues; uint32_t qindex; - uint32_t n_queues_per_port; - /* Check user parameters */ - if (port == NULL) + if (subport == NULL) return; - n_queues_per_port = rte_sched_port_queues_per_port(port); + n_subport_pipe_queues = rte_sched_subport_pipe_queues(subport); /* Free enqueued mbufs */ - for (qindex = 0; qindex < n_queues_per_port; qindex++) { - struct rte_mbuf **mbufs = rte_sched_port_qbase(port, qindex); - uint16_t qsize = rte_sched_port_qsize(port, qindex); + for (qindex = 0; qindex < n_subport_pipe_queues; qindex++) { + struct rte_mbuf **mbufs = + rte_sched_subport_pipe_qbase(subport, qindex); + uint16_t qsize = rte_sched_subport_pipe_qsize(port, subport, qindex); if (qsize != 0) { - struct rte_sched_queue *queue = port->queue + qindex; + struct rte_sched_queue *queue = subport->queue + qindex; uint16_t qr = queue->qr & (qsize - 1); uint16_t qw = queue->qw & (qsize - 1); @@ -904,7 +778,21 @@ rte_sched_port_free(struct rte_sched_port *port) } } - rte_bitmap_free(port->bmp); + rte_bitmap_free(subport->bmp); +} + +void +rte_sched_port_free(struct rte_sched_port *port) +{ + uint32_t i; + + /* Check user parameters */ + if (port == NULL) + return; + + for (i = 0; i < port->n_subports_per_port; i++) + rte_sched_subport_free(port, port->subports[i]); + rte_free(port); } -- 2.21.0
Add pipes configuration from the port level to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 388 ++++++++++++++++++++++++++++++----- 1 file changed, 332 insertions(+), 56 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 952e449f7..60dfc6232 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -550,24 +550,91 @@ rte_sched_port_get_array_base(struct rte_sched_port_params *params, enum rte_sch return base; } -uint32_t -rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params) +static uint32_t +rte_sched_subport_get_array_base(struct rte_sched_subport_params *params, + enum rte_sched_subport_array array) { - uint32_t size0, size1; - int status; + uint32_t n_pipes_per_subport = params->n_pipes_per_subport_enabled; + uint32_t n_subport_pipe_queues = + RTE_SCHED_QUEUES_PER_PIPE * n_pipes_per_subport; - status = rte_sched_port_check_params(params); - if (status != 0) { - RTE_LOG(NOTICE, SCHED, - "Port scheduler params check failed (%d)\n", status); + uint32_t size_pipe = n_pipes_per_subport * sizeof(struct rte_sched_pipe); + uint32_t size_queue = + n_subport_pipe_queues * sizeof(struct rte_sched_queue); + uint32_t size_queue_extra + = n_subport_pipe_queues * sizeof(struct rte_sched_queue_extra); + uint32_t size_pipe_profiles = params->n_max_pipe_profiles * + sizeof(struct rte_sched_pipe_profile); + uint32_t size_bmp_array = + rte_bitmap_get_memory_footprint(n_subport_pipe_queues); + uint32_t size_per_pipe_queue_array, size_queue_array; - return 0; + uint32_t base, i; + + size_per_pipe_queue_array = 0; + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + if (i < RTE_SCHED_TRAFFIC_CLASS_BE) + size_per_pipe_queue_array += + params->qsize[i] * sizeof(struct rte_mbuf *); + else + size_per_pipe_queue_array += RTE_SCHED_MAX_QUEUES_PER_TC * + params->qsize[i] * sizeof(struct rte_mbuf *); } + size_queue_array = n_pipes_per_subport * size_per_pipe_queue_array; - size0 = sizeof(struct rte_sched_port); - size1 = rte_sched_port_get_array_base(params, e_RTE_SCHED_PORT_ARRAY_TOTAL); + base = 0; - return size0 + size1; + if (array == e_RTE_SCHED_SUBPORT_ARRAY_PIPE) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_pipe); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_QUEUE) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_queue); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_EXTRA) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_queue_extra); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_PIPE_PROFILES) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_pipe_profiles); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_BMP_ARRAY) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_bmp_array); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_ARRAY) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_queue_array); + + return base; +} + +static void +rte_sched_subport_config_qsize(struct rte_sched_subport *subport) +{ + uint32_t i; + + subport->qsize_add[0] = 0; + + /* Strict prority traffic class */ + for (i = 1; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) + subport->qsize_add[i] = subport->qsize_add[i-1] + subport->qsize[i-1]; + + /* Best-effort traffic class */ + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 1] = + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE] + + subport->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 2] = + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 1] + + subport->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 3] = + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 2] + + subport->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; + + subport->qsize_sum = subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 3] + + subport->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; } static void @@ -679,6 +746,126 @@ rte_sched_pipe_profile_convert(struct rte_sched_port *port, dst->wrr_cost[3] = (uint8_t) wrr_cost[3]; } +static int +rte_sched_subport_check_params(struct rte_sched_subport_params *params, + uint32_t n_max_pipes_per_subport, + uint32_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; + } + + /* qsize: if non-zero, power of 2, + * no bigger than 32K (due to 16-bit read/write pointers) + */ + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + uint16_t qsize = params->qsize[i]; + + if (qsize != 0 && !rte_is_power_of_2(qsize)) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for qsize\n", __func__); + return -EINVAL; + } + } + + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + uint32_t tc_rate = params->tc_rate[i]; + uint16_t qsize = params->qsize[i]; + + if ((qsize == 0 && tc_rate != 0) || + (qsize != 0 && tc_rate == 0) || + (tc_rate > params->tb_rate)) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for tc rate\n", __func__); + return -EINVAL; + } + } + + if (params->qsize[RTE_SCHED_TRAFFIC_CLASS_BE] == 0 || + params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE] == 0) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect qsize or 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; + } + + /* n_pipes_per_subport: non-zero, power of 2 */ + if (params->n_pipes_per_subport_enabled == 0 || + params->n_pipes_per_subport_enabled > n_max_pipes_per_subport || + !rte_is_power_of_2(params->n_pipes_per_subport_enabled)) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for pipes number\n", __func__); + return -EINVAL; + } + + /* pipe_profiles and n_pipe_profiles */ + if (params->pipe_profiles == NULL || + params->n_pipe_profiles == 0 || + params->n_max_pipe_profiles == 0 || + params->n_pipe_profiles > params->n_max_pipe_profiles) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for pipe profiles\n", __func__); + return -EINVAL; + } + + for (i = 0; i < params->n_pipe_profiles; i++) { + struct rte_sched_pipe_params *p = params->pipe_profiles + i; + int status; + + status = pipe_profile_check(p, rate, ¶ms->qsize[0]); + if (status != 0) { + RTE_LOG(ERR, SCHED, + "%s: Pipe profile check failed(%d)\n", __func__, status); + return -EINVAL; + } + } + + return 0; +} + +uint32_t +rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params) +{ + uint32_t size0, size1; + int status; + + status = rte_sched_port_check_params(params); + if (status != 0) { + RTE_LOG(NOTICE, SCHED, + "Port scheduler params check failed (%d)\n", status); + + return 0; + } + + size0 = sizeof(struct rte_sched_port); + size1 = rte_sched_port_get_array_base(params, + e_RTE_SCHED_PORT_ARRAY_TOTAL); + + return size0 + size1; +} + struct rte_sched_port * rte_sched_port_config(struct rte_sched_port_params *params) { @@ -799,7 +986,7 @@ rte_sched_port_free(struct rte_sched_port *port) static void rte_sched_port_log_subport_config(struct rte_sched_port *port, uint32_t i) { - struct rte_sched_subport *s = port->subport + i; + struct rte_sched_subport *s = port->subports[i]; RTE_LOG(DEBUG, SCHED, "Low level config for subport %u:\n" " Token bucket: period = %u, credits per period = %u, size = %u\n" @@ -834,72 +1021,78 @@ rte_sched_port_log_subport_config(struct rte_sched_port *port, uint32_t i) s->tc_ov_wm_max); } +static void +rte_sched_free_memory(struct rte_sched_port *port, uint32_t n_subports) +{ + uint32_t i; + + for (i = 0; i < n_subports; i++) { + struct rte_sched_subport *subport = port->subports[i]; + + rte_sched_subport_free(port, subport); + } + + rte_free(port); +} + int rte_sched_subport_config(struct rte_sched_port *port, uint32_t subport_id, struct rte_sched_subport_params *params) { - struct rte_sched_subport *s; - uint32_t i; + struct rte_sched_subport *s = NULL; + uint32_t n_subports = subport_id; + uint32_t n_subport_pipe_queues, i; + uint32_t size0, size1, bmp_mem_size; + int status; /* Check user parameters */ if (port == NULL) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for parameter port\n", __func__); - return -EINVAL; + return 0; } if (subport_id >= port->n_subports_per_port) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for subport id\n", __func__); - return -EINVAL; - } - if (params == NULL) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for parameter params\n", __func__); + rte_sched_free_memory(port, n_subports); return -EINVAL; } - if (params->tb_rate == 0 || params->tb_rate > port->rate) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tb rate\n", __func__); - return -EINVAL; - } + status = rte_sched_subport_check_params(params, + port->n_pipes_per_subport, + port->rate); + if (status != 0) { + RTE_LOG(NOTICE, SCHED, + "%s: Port scheduler params check failed (%d)\n", + __func__, status); - if (params->tb_size == 0) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tb size\n", __func__); + rte_sched_free_memory(port, n_subports); return -EINVAL; } - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - uint32_t tc_rate = params->tc_rate[i]; - uint16_t qsize = port->qsize[i]; + /* Determine the amount of memory to allocate */ + size0 = sizeof(struct rte_sched_subport); + size1 = rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_TOTAL); - if ((qsize == 0 && tc_rate != 0) || - (qsize != 0 && tc_rate == 0) || - (tc_rate > params->tb_rate)) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tc rate\n", __func__); - return -EINVAL; - } - } - - if (port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE] == 0 || - params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE] == 0) { + /* Allocate memory to store the data structures */ + s = rte_zmalloc_socket("subport_params", size0 + size1, + RTE_CACHE_LINE_SIZE, port->socket); + if (s == NULL) { RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tc rate(best effort)\n", __func__); - return -EINVAL; - } + "%s: Memory allocation fails\n", __func__); - if (params->tc_period == 0) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tc period\n", __func__); - return -EINVAL; + rte_sched_free_memory(port, n_subports); + return -ENOMEM; } - s = port->subport + subport_id; + n_subports++; + + /* Port */ + port->subports[subport_id] = s; /* Token Bucket (TB) */ if (params->tb_rate == port->rate) { @@ -919,26 +1112,109 @@ rte_sched_subport_config(struct rte_sched_port *port, /* Traffic Classes (TCs) */ s->tc_period = rte_sched_time_ms_to_bytes(params->tc_period, port->rate); for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - if (port->qsize[i]) + if (params->qsize[i]) s->tc_credits_per_period[i] = rte_sched_time_ms_to_bytes(params->tc_period, - params->tc_rate[i]); - + params->tc_rate[i]); } s->tc_time = port->time + s->tc_period; for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - if (port->qsize[i]) + if (params->qsize[i]) s->tc_credits[i] = s->tc_credits_per_period[i]; + /* compile time checks */ + RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS == 0); + RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS & + (RTE_SCHED_PORT_N_GRINDERS - 1)); + + /* User parameters */ + s->n_pipes_per_subport_enabled = params->n_pipes_per_subport_enabled; + memcpy(s->qsize, params->qsize, sizeof(params->qsize)); + s->n_pipe_profiles = params->n_pipe_profiles; + s->n_max_pipe_profiles = params->n_max_pipe_profiles; + +#ifdef RTE_SCHED_RED + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + uint32_t j; + + for (j = 0; j < RTE_COLORS; j++) { + /* if min/max are both zero, then RED is disabled */ + if ((params->red_params[i][j].min_th | + params->red_params[i][j].max_th) == 0) { + continue; + } + + if (rte_red_config_init(&s->red_config[i][j], + params->red_params[i][j].wq_log2, + params->red_params[i][j].min_th, + params->red_params[i][j].max_th, + params->red_params[i][j].maxp_inv) != 0) { + rte_sched_free_memory(port, n_subports); + + RTE_LOG(NOTICE, SCHED, + "%s: RED configuration init fails\n", __func__); + return -EINVAL; + } + } + } +#endif + + /* Scheduling loop detection */ + s->pipe_loop = RTE_SCHED_PIPE_INVALID; + s->pipe_exhaustion = 0; + + /* Grinders */ + s->busy_grinders = 0; + + /* Queue base calculation */ + rte_sched_subport_config_qsize(s); + + /* Large data structures */ + s->pipe = (struct rte_sched_pipe *) + (s->memory + rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_PIPE)); + s->queue = (struct rte_sched_queue *) + (s->memory + rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE)); + s->queue_extra = (struct rte_sched_queue_extra *) + (s->memory + rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_EXTRA)); + s->pipe_profiles = (struct rte_sched_pipe_profile *) + (s->memory + rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_PIPE_PROFILES)); + s->bmp_array = s->memory + rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_BMP_ARRAY); + s->queue_array = (struct rte_mbuf **) + (s->memory + rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_ARRAY)); + + /* Bitmap */ + n_subport_pipe_queues = rte_sched_subport_pipe_queues(s); + bmp_mem_size = rte_bitmap_get_memory_footprint(n_subport_pipe_queues); + s->bmp = rte_bitmap_init(n_subport_pipe_queues, s->bmp_array, + bmp_mem_size); + if (s->bmp == NULL) { + RTE_LOG(ERR, SCHED, + "%s: Subport bitmap init error\n", __func__); + + rte_sched_free_memory(port, n_subports); + return -EINVAL; + } + + for (i = 0; i < RTE_SCHED_PORT_N_GRINDERS; i++) + s->grinder_base_bmp_pos[i] = RTE_SCHED_PIPE_INVALID; + +#ifdef RTE_SCHED_SUBPORT_TC_OV /* TC oversubscription */ s->tc_ov_wm_min = port->mtu; s->tc_ov_wm_max = rte_sched_time_ms_to_bytes(params->tc_period, - port->pipe_tc_be_rate_max); + s->pipe_tc_be_rate_max); s->tc_ov_wm = s->tc_ov_wm_max; s->tc_ov_period_id = 0; s->tc_ov = 0; s->tc_ov_n = 0; s->tc_ov_rate = 0; +#endif rte_sched_port_log_subport_config(port, subport_id); -- 2.21.0
Modify pipe level functions to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 103 +++++++++++++++++-------- lib/librte_sched/rte_sched.h | 7 +- lib/librte_sched/rte_sched_version.map | 2 +- 3 files changed, 76 insertions(+), 36 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 60dfc6232..6b6219e45 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -638,9 +638,9 @@ rte_sched_subport_config_qsize(struct rte_sched_subport *subport) } static void -rte_sched_port_log_pipe_profile(struct rte_sched_port *port, uint32_t i) +rte_sched_port_log_pipe_profile(struct rte_sched_subport *subport, uint32_t i) { - struct rte_sched_pipe_profile *p = port->pipe_profiles + i; + struct rte_sched_pipe_profile *p = subport->pipe_profiles + i; RTE_LOG(DEBUG, SCHED, "Low level config for pipe profile %u:\n" " Token bucket: period = %u, credits per period = %u, size = %u\n" @@ -689,7 +689,7 @@ rte_sched_time_ms_to_bytes(uint32_t time_ms, uint32_t rate) } static void -rte_sched_pipe_profile_convert(struct rte_sched_port *port, +rte_sched_pipe_profile_convert(struct rte_sched_subport *subport, struct rte_sched_pipe_params *src, struct rte_sched_pipe_profile *dst, uint32_t rate) @@ -718,7 +718,7 @@ rte_sched_pipe_profile_convert(struct rte_sched_port *port, rate); for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - if (port->qsize[i]) + if (subport->qsize[i]) dst->tc_credits_per_period[i] = rte_sched_time_ms_to_bytes(src->tc_period, src->tc_rate[i]); @@ -746,6 +746,30 @@ rte_sched_pipe_profile_convert(struct rte_sched_port *port, dst->wrr_cost[3] = (uint8_t) wrr_cost[3]; } +static void +rte_sched_subport_config_pipe_profile_table(struct rte_sched_subport *subport, + struct rte_sched_subport_params *params, uint32_t rate) +{ + uint32_t i; + + for (i = 0; i < subport->n_pipe_profiles; i++) { + struct rte_sched_pipe_params *src = params->pipe_profiles + i; + struct rte_sched_pipe_profile *dst = subport->pipe_profiles + i; + + rte_sched_pipe_profile_convert(subport, src, dst, rate); + rte_sched_port_log_pipe_profile(subport, i); + } + + subport->pipe_tc_be_rate_max = 0; + for (i = 0; i < subport->n_pipe_profiles; i++) { + struct rte_sched_pipe_params *src = params->pipe_profiles + i; + uint32_t pipe_tc_be_rate = src->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; + + if (subport->pipe_tc_be_rate_max < pipe_tc_be_rate) + subport->pipe_tc_be_rate_max = pipe_tc_be_rate; + } +} + static int rte_sched_subport_check_params(struct rte_sched_subport_params *params, uint32_t n_max_pipes_per_subport, @@ -1188,6 +1212,9 @@ rte_sched_subport_config(struct rte_sched_port *port, (s->memory + rte_sched_subport_get_array_base(params, e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_ARRAY)); + /* Pipe profile table */ + rte_sched_subport_config_pipe_profile_table(s, params, port->rate); + /* Bitmap */ n_subport_pipe_queues = rte_sched_subport_pipe_queues(s); bmp_mem_size = rte_bitmap_get_memory_footprint(n_subport_pipe_queues); @@ -1230,6 +1257,7 @@ rte_sched_pipe_config(struct rte_sched_port *port, struct rte_sched_subport *s; struct rte_sched_pipe *p; struct rte_sched_pipe_profile *params; + uint32_t n_subports = subport_id + 1; uint32_t deactivate, profile, i; /* Check user parameters */ @@ -1245,34 +1273,32 @@ rte_sched_pipe_config(struct rte_sched_port *port, if (subport_id >= port->n_subports_per_port) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for parameter subport id\n", __func__); + + rte_sched_free_memory(port, n_subports); return -EINVAL; } - if (pipe_id >= port->n_pipes_per_subport) { + s = port->subports[subport_id]; + if (pipe_id >= s->n_pipes_per_subport_enabled) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for parameter pipe id\n", __func__); + + rte_sched_free_memory(port, n_subports); return -EINVAL; } - if (!deactivate && profile >= port->n_pipe_profiles) { + if (!deactivate && profile >= s->n_pipe_profiles) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for parameter pipe profile\n", __func__); - return -EINVAL; - } - /* Check that subport configuration is valid */ - s = port->subport + subport_id; - if (s->tb_period == 0) { - RTE_LOG(ERR, SCHED, - "%s: Subport configuration invalid\n", __func__); + rte_sched_free_memory(port, n_subports); return -EINVAL; } - p = port->pipe + (subport_id * port->n_pipes_per_subport + pipe_id); - /* Handle the case when pipe already has a valid configuration */ + p = s->pipe + pipe_id; if (p->tb_time) { - params = port->pipe_profiles + p->profile; + params = s->pipe_profiles + p->profile; double subport_tc_be_rate = (double) s->tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASS_BE] @@ -1302,7 +1328,7 @@ rte_sched_pipe_config(struct rte_sched_port *port, /* Apply the new pipe configuration */ p->profile = profile; - params = port->pipe_profiles + p->profile; + params = s->pipe_profiles + p->profile; /* Token Bucket (TB) */ p->tb_time = port->time; @@ -1312,7 +1338,7 @@ rte_sched_pipe_config(struct rte_sched_port *port, p->tc_time = port->time + params->tc_period; for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - if (port->qsize[i]) + if (s->qsize[i]) p->tc_credits[i] = params->tc_credits_per_period[i]; { @@ -1342,10 +1368,12 @@ rte_sched_pipe_config(struct rte_sched_port *port, } int -rte_sched_port_pipe_profile_add(struct rte_sched_port *port, +rte_sched_subport_pipe_profile_add(struct rte_sched_port *port, + uint32_t subport_id, struct rte_sched_pipe_params *params, uint32_t *pipe_profile_id) { + struct rte_sched_subport *s; struct rte_sched_pipe_profile *pp; uint32_t i; int status; @@ -1357,40 +1385,49 @@ rte_sched_port_pipe_profile_add(struct rte_sched_port *port, return -EINVAL; } - /* Pipe profiles not exceeds the max limit */ - if (port->n_pipe_profiles >= port->n_max_pipe_profiles) { + /* Subport id not exceeds the max limit */ + if (subport_id > port->n_subports_per_port) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for subport id\n", __func__); + return -EINVAL; + } + + s = port->subports[subport_id]; + + /* Pipe profiles exceeds the max limit */ + if (s->n_pipe_profiles >= s->n_max_pipe_profiles) { RTE_LOG(ERR, SCHED, "%s: Number of pipe profiles exceeds the max limit\n", __func__); return -EINVAL; } /* Pipe params */ - status = pipe_profile_check(params, port->rate, &port->qsize[0]); + status = pipe_profile_check(params, port->rate, &s->qsize[0]); if (status != 0) { RTE_LOG(ERR, SCHED, "%s: Pipe profile check failed(%d)\n", __func__, status); return -EINVAL; } - pp = &port->pipe_profiles[port->n_pipe_profiles]; - rte_sched_pipe_profile_convert(port, params, pp, port->rate); + pp = &s->pipe_profiles[s->n_pipe_profiles]; + rte_sched_pipe_profile_convert(s, params, pp, port->rate); - /* Pipe profile not exists */ - for (i = 0; i < port->n_pipe_profiles; i++) - if (memcmp(port->pipe_profiles + i, pp, sizeof(*pp)) == 0) { + /* Pipe profile should not exists */ + for (i = 0; i < s->n_pipe_profiles; i++) + if (memcmp(s->pipe_profiles + i, pp, sizeof(*pp)) == 0) { RTE_LOG(ERR, SCHED, - "%s: Pipe profile doesn't exist\n", __func__); + "%s: Pipe profile exists\n", __func__); return -EINVAL; } /* Pipe profile commit */ - *pipe_profile_id = port->n_pipe_profiles; - port->n_pipe_profiles++; + *pipe_profile_id = s->n_pipe_profiles; + s->n_pipe_profiles++; - if (port->pipe_tc_be_rate_max < params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]) - port->pipe_tc_be_rate_max = params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; + if (s->pipe_tc_be_rate_max < params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]) + s->pipe_tc_be_rate_max = params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; - rte_sched_port_log_pipe_profile(port, *pipe_profile_id); + rte_sched_port_log_pipe_profile(s, *pipe_profile_id); return 0; } diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index fbb0e23fa..5001f09ed 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -317,6 +317,8 @@ rte_sched_port_free(struct rte_sched_port *port); * * @param port * Handle to port scheduler instance + * @param subport_id + * Subport ID * @param params * Pipe profile parameters * @param pipe_profile_id @@ -326,7 +328,8 @@ rte_sched_port_free(struct rte_sched_port *port); */ __rte_experimental int -rte_sched_port_pipe_profile_add(struct rte_sched_port *port, +rte_sched_subport_pipe_profile_add(struct rte_sched_port *port, + uint32_t subport_id, struct rte_sched_pipe_params *params, uint32_t *pipe_profile_id); @@ -357,7 +360,7 @@ rte_sched_subport_config(struct rte_sched_port *port, * @param pipe_id * Pipe ID within subport * @param pipe_profile - * ID of port-level pre-configured pipe profile + * ID of subport-level pre-configured pipe profile * @return * 0 upon success, error code otherwise */ diff --git a/lib/librte_sched/rte_sched_version.map b/lib/librte_sched/rte_sched_version.map index 729588794..f33761e63 100644 --- a/lib/librte_sched/rte_sched_version.map +++ b/lib/librte_sched/rte_sched_version.map @@ -33,5 +33,5 @@ DPDK_2.1 { EXPERIMENTAL { global: - rte_sched_port_pipe_profile_add; + rte_sched_subport_pipe_profile_add; }; -- 2.21.0
Modify scheduler packet enqueue operation of the scheduler to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 277 ++++++++++++++++++++++------------- 1 file changed, 178 insertions(+), 99 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 6b6219e45..a8174afad 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -1440,10 +1440,11 @@ rte_sched_port_qindex(struct rte_sched_port *port, 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) | - ((rte_sched_port_pipe_queue(port, traffic_class) + queue) & - (RTE_SCHED_QUEUES_PER_PIPE - 1)); + (port->n_pipes_per_subport_log2 + 4)) | + ((pipe & + (port->subports[subport]->n_pipes_per_subport_enabled - 1)) << 4) | + ((rte_sched_port_pipe_queue(port, traffic_class) + queue) & + (RTE_SCHED_QUEUES_PER_PIPE - 1)); } void @@ -1468,7 +1469,8 @@ rte_sched_port_pkt_read_tree_path(struct rte_sched_port *port, uint32_t queue_id = rte_mbuf_sched_queue_get(pkt); *subport = queue_id >> (port->n_pipes_per_subport_log2 + 4); - *pipe = (queue_id >> 4) & (port->n_pipes_per_subport - 1); + *pipe = (queue_id >> 4) & + (port->subports[*subport]->n_pipes_per_subport_enabled - 1); *traffic_class = rte_sched_port_pipe_tc(port, queue_id); *queue = rte_sched_port_tc_queue(port, queue_id); } @@ -1512,7 +1514,7 @@ rte_sched_subport_read_stats(struct rte_sched_port *port, return -EINVAL; } - s = port->subport + subport_id; + s = port->subports[subport_id]; /* Copy subport stats and clear */ memcpy(stats, &s->stats, sizeof(struct rte_sched_subport_stats)); @@ -1585,43 +1587,50 @@ rte_sched_port_queue_is_empty(struct rte_sched_port *port, uint32_t qindex) #ifdef RTE_SCHED_COLLECT_STATS static inline void -rte_sched_port_update_subport_stats(struct rte_sched_port *port, uint32_t qindex, struct rte_mbuf *pkt) +rte_sched_port_update_subport_stats(struct rte_sched_port *port, + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt) { - struct rte_sched_subport *s = port->subport + (qindex / rte_sched_port_queues_per_subport(port)); uint32_t tc_index = rte_sched_port_pipe_tc(port, qindex); uint32_t pkt_len = pkt->pkt_len; - s->stats.n_pkts_tc[tc_index] += 1; - s->stats.n_bytes_tc[tc_index] += pkt_len; + subport->stats.n_pkts_tc[tc_index] += 1; + subport->stats.n_bytes_tc[tc_index] += pkt_len; } #ifdef RTE_SCHED_RED static inline void rte_sched_port_update_subport_stats_on_drop(struct rte_sched_port *port, - uint32_t qindex, - struct rte_mbuf *pkt, uint32_t red) + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt, + uint32_t red) #else static inline void rte_sched_port_update_subport_stats_on_drop(struct rte_sched_port *port, - uint32_t qindex, - struct rte_mbuf *pkt, __rte_unused uint32_t red) + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt, + __rte_unused uint32_t red) #endif { - struct rte_sched_subport *s = port->subport + (qindex / rte_sched_port_queues_per_subport(port)); uint32_t tc_index = rte_sched_port_pipe_tc(port, qindex); uint32_t pkt_len = pkt->pkt_len; - s->stats.n_pkts_tc_dropped[tc_index] += 1; - s->stats.n_bytes_tc_dropped[tc_index] += pkt_len; + subport->stats.n_pkts_tc_dropped[tc_index] += 1; + subport->stats.n_bytes_tc_dropped[tc_index] += pkt_len; #ifdef RTE_SCHED_RED - s->stats.n_pkts_red_dropped[tc_index] += red; + subport->stats.n_pkts_red_dropped[tc_index] += red; #endif } static inline void -rte_sched_port_update_queue_stats(struct rte_sched_port *port, uint32_t qindex, struct rte_mbuf *pkt) +rte_sched_port_update_queue_stats(struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt) { - struct rte_sched_queue_extra *qe = port->queue_extra + qindex; + struct rte_sched_queue_extra *qe = subport->queue_extra + qindex; uint32_t pkt_len = pkt->pkt_len; qe->stats.n_pkts += 1; @@ -1630,17 +1639,19 @@ rte_sched_port_update_queue_stats(struct rte_sched_port *port, uint32_t qindex, #ifdef RTE_SCHED_RED static inline void -rte_sched_port_update_queue_stats_on_drop(struct rte_sched_port *port, - uint32_t qindex, - struct rte_mbuf *pkt, uint32_t red) +rte_sched_port_update_queue_stats_on_drop(struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt, + uint32_t red) #else static inline void -rte_sched_port_update_queue_stats_on_drop(struct rte_sched_port *port, - uint32_t qindex, - struct rte_mbuf *pkt, __rte_unused uint32_t red) +rte_sched_port_update_queue_stats_on_drop(struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt, + __rte_unused uint32_t red) #endif { - struct rte_sched_queue_extra *qe = port->queue_extra + qindex; + struct rte_sched_queue_extra *qe = subport->queue_extra + qindex; uint32_t pkt_len = pkt->pkt_len; qe->stats.n_pkts_dropped += 1; @@ -1655,7 +1666,11 @@ rte_sched_port_update_queue_stats_on_drop(struct rte_sched_port *port, #ifdef RTE_SCHED_RED static inline int -rte_sched_port_red_drop(struct rte_sched_port *port, struct rte_mbuf *pkt, uint32_t qindex, uint16_t qlen) +rte_sched_port_red_drop(struct rte_sched_port *port, + struct rte_sched_subport *subport, + struct rte_mbuf *pkt, + uint32_t qindex, + uint16_t qlen) { struct rte_sched_queue_extra *qe; struct rte_red_config *red_cfg; @@ -1665,12 +1680,12 @@ rte_sched_port_red_drop(struct rte_sched_port *port, struct rte_mbuf *pkt, uint3 tc_index = rte_sched_port_pipe_tc(port, qindex); color = rte_sched_port_pkt_read_color(pkt); - red_cfg = &port->red_config[tc_index][color]; + red_cfg = &subport->red_config[tc_index][color]; if ((red_cfg->min_th | red_cfg->max_th) == 0) return 0; - qe = port->queue_extra + qindex; + qe = subport->queue_extra + qindex; red = &qe->red; return rte_red_enqueue(red_cfg, red, qlen, port->time); @@ -1687,7 +1702,14 @@ rte_sched_port_set_queue_empty_timestamp(struct rte_sched_port *port, uint32_t q #else -#define rte_sched_port_red_drop(port, pkt, qindex, qlen) 0 +static inline int rte_sched_port_red_drop(struct rte_sched_port *port __rte_unused, + struct rte_sched_subport *subport __rte_unused, + struct rte_mbuf *pkt __rte_unused, + uint32_t qindex __rte_unused, + uint16_t qlen __rte_unused) +{ + return 0; +} #define rte_sched_port_set_queue_empty_timestamp(port, qindex) @@ -1722,63 +1744,79 @@ debug_check_queue_slab(struct rte_sched_port *port, uint32_t bmp_pos, #endif /* RTE_SCHED_DEBUG */ +static inline struct rte_sched_subport * +rte_sched_port_subport(struct rte_sched_port *port, + struct rte_mbuf *pkt) +{ + uint32_t queue_id = rte_mbuf_sched_queue_get(pkt); + uint32_t subport_id = queue_id >> (port->n_pipes_per_subport_log2 + 4); + + return port->subports[subport_id]; +} + static inline uint32_t -rte_sched_port_enqueue_qptrs_prefetch0(struct rte_sched_port *port, - struct rte_mbuf *pkt) +rte_sched_port_enqueue_qptrs_prefetch0(struct rte_sched_subport *subport, + struct rte_mbuf *pkt, uint32_t subport_qmask) { struct rte_sched_queue *q; #ifdef RTE_SCHED_COLLECT_STATS struct rte_sched_queue_extra *qe; #endif uint32_t qindex = rte_mbuf_sched_queue_get(pkt); + uint32_t subport_queue_id = subport_qmask & qindex; - q = port->queue + qindex; + q = subport->queue + subport_queue_id; rte_prefetch0(q); #ifdef RTE_SCHED_COLLECT_STATS - qe = port->queue_extra + qindex; + qe = subport->queue_extra + subport_queue_id; rte_prefetch0(qe); #endif - return qindex; + return subport_queue_id; } static inline void rte_sched_port_enqueue_qwa_prefetch0(struct rte_sched_port *port, - uint32_t qindex, struct rte_mbuf **qbase) + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf **qbase) { struct rte_sched_queue *q; struct rte_mbuf **q_qw; uint16_t qsize; - q = port->queue + qindex; - qsize = rte_sched_port_qsize(port, qindex); + q = subport->queue + qindex; + qsize = rte_sched_subport_pipe_qsize(port, subport, qindex); q_qw = qbase + (q->qw & (qsize - 1)); rte_prefetch0(q_qw); - rte_bitmap_prefetch0(port->bmp, qindex); + rte_bitmap_prefetch0(subport->bmp, qindex); } static inline int -rte_sched_port_enqueue_qwa(struct rte_sched_port *port, uint32_t qindex, - struct rte_mbuf **qbase, struct rte_mbuf *pkt) +rte_sched_port_enqueue_qwa(struct rte_sched_port *port, + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf **qbase, + struct rte_mbuf *pkt) { struct rte_sched_queue *q; uint16_t qsize; uint16_t qlen; - q = port->queue + qindex; - qsize = rte_sched_port_qsize(port, qindex); + q = subport->queue + qindex; + qsize = rte_sched_subport_pipe_qsize(port, subport, qindex); qlen = q->qw - q->qr; /* Drop the packet (and update drop stats) when queue is full */ - if (unlikely(rte_sched_port_red_drop(port, pkt, qindex, qlen) || + if (unlikely(rte_sched_port_red_drop(port, subport, pkt, qindex, qlen) || (qlen >= qsize))) { rte_pktmbuf_free(pkt); #ifdef RTE_SCHED_COLLECT_STATS - rte_sched_port_update_subport_stats_on_drop(port, qindex, pkt, - qlen < qsize); - rte_sched_port_update_queue_stats_on_drop(port, qindex, pkt, - qlen < qsize); + rte_sched_port_update_subport_stats_on_drop(port, subport, + qindex, pkt, qlen < qsize); + rte_sched_port_update_queue_stats_on_drop(subport, qindex, pkt, + qlen < qsize); #endif return 0; } @@ -1787,13 +1825,13 @@ rte_sched_port_enqueue_qwa(struct rte_sched_port *port, uint32_t qindex, qbase[q->qw & (qsize - 1)] = pkt; q->qw++; - /* Activate queue in the port bitmap */ - rte_bitmap_set(port->bmp, qindex); + /* Activate queue in the subport bitmap */ + rte_bitmap_set(subport->bmp, qindex); /* Statistics */ #ifdef RTE_SCHED_COLLECT_STATS - rte_sched_port_update_subport_stats(port, qindex, pkt); - rte_sched_port_update_queue_stats(port, qindex, pkt); + rte_sched_port_update_subport_stats(port, subport, qindex, pkt); + rte_sched_port_update_queue_stats(subport, qindex, pkt); #endif return 1; @@ -1821,17 +1859,22 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, *pkt30, *pkt31, *pkt_last; struct rte_mbuf **q00_base, **q01_base, **q10_base, **q11_base, **q20_base, **q21_base, **q30_base, **q31_base, **q_last_base; + struct rte_sched_subport *subport00, *subport01, *subport10, *subport11, + *subport20, *subport21, *subport30, *subport31, *subport_last; uint32_t q00, q01, q10, q11, q20, q21, q30, q31, q_last; uint32_t r00, r01, r10, r11, r20, r21, r30, r31, r_last; + uint32_t subport_qmask; uint32_t result, i; result = 0; + subport_qmask = (1 << (port->n_pipes_per_subport_log2 + 4)) - 1; /* * Less then 6 input packets available, which is not enough to * feed the pipeline */ if (unlikely(n_pkts < 6)) { + struct rte_sched_subport *subports[5]; struct rte_mbuf **q_base[5]; uint32_t q[5]; @@ -1839,22 +1882,26 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, for (i = 0; i < n_pkts; i++) rte_prefetch0(pkts[i]); + /* Prefetch the subport structure for each packet */ + for (i = 0; i < n_pkts; i++) + subports[i] = rte_sched_port_subport(port, pkts[i]); + /* Prefetch the queue structure for each queue */ for (i = 0; i < n_pkts; i++) - q[i] = rte_sched_port_enqueue_qptrs_prefetch0(port, - pkts[i]); + q[i] = rte_sched_port_enqueue_qptrs_prefetch0(subports[i], + pkts[i], subport_qmask); /* Prefetch the write pointer location of each queue */ for (i = 0; i < n_pkts; i++) { - q_base[i] = rte_sched_port_qbase(port, q[i]); - rte_sched_port_enqueue_qwa_prefetch0(port, q[i], - q_base[i]); + q_base[i] = rte_sched_subport_pipe_qbase(subports[i], q[i]); + rte_sched_port_enqueue_qwa_prefetch0(port, subports[i], + q[i], q_base[i]); } /* Write each packet to its queue */ for (i = 0; i < n_pkts; i++) - result += rte_sched_port_enqueue_qwa(port, q[i], - q_base[i], pkts[i]); + result += rte_sched_port_enqueue_qwa(port, subports[i], + q[i], q_base[i], pkts[i]); return result; } @@ -1870,21 +1917,29 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, rte_prefetch0(pkt10); rte_prefetch0(pkt11); - q20 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt20); - q21 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt21); + subport20 = rte_sched_port_subport(port, pkt20); + subport21 = rte_sched_port_subport(port, pkt21); + q20 = rte_sched_port_enqueue_qptrs_prefetch0(subport20, + pkt20, subport_qmask); + q21 = rte_sched_port_enqueue_qptrs_prefetch0(subport21, + pkt21, subport_qmask); pkt00 = pkts[4]; pkt01 = pkts[5]; rte_prefetch0(pkt00); rte_prefetch0(pkt01); - q10 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt10); - q11 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt11); + subport10 = rte_sched_port_subport(port, pkt10); + subport11 = rte_sched_port_subport(port, pkt11); + q10 = rte_sched_port_enqueue_qptrs_prefetch0(subport10, + pkt10, subport_qmask); + q11 = rte_sched_port_enqueue_qptrs_prefetch0(subport11, + pkt11, subport_qmask); - q20_base = rte_sched_port_qbase(port, q20); - q21_base = rte_sched_port_qbase(port, q21); - rte_sched_port_enqueue_qwa_prefetch0(port, q20, q20_base); - rte_sched_port_enqueue_qwa_prefetch0(port, q21, q21_base); + q20_base = rte_sched_subport_pipe_qbase(subport20, q20); + q21_base = rte_sched_subport_pipe_qbase(subport21, q21); + rte_sched_port_enqueue_qwa_prefetch0(port, subport20, q20, q20_base); + rte_sched_port_enqueue_qwa_prefetch0(port, subport21, q21, q21_base); /* Run the pipeline */ for (i = 6; i < (n_pkts & (~1)); i += 2) { @@ -1899,6 +1954,10 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, q31 = q21; q20 = q10; q21 = q11; + subport30 = subport20; + subport31 = subport21; + subport20 = subport10; + subport21 = subport11; q30_base = q20_base; q31_base = q21_base; @@ -1908,19 +1967,25 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, rte_prefetch0(pkt00); rte_prefetch0(pkt01); - /* Stage 1: Prefetch queue structure storing queue pointers */ - q10 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt10); - q11 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt11); + /* Stage 1: Prefetch subport and queue structure storing queue pointers */ + subport10 = rte_sched_port_subport(port, pkt10); + subport11 = rte_sched_port_subport(port, pkt11); + q10 = rte_sched_port_enqueue_qptrs_prefetch0(subport10, + pkt10, subport_qmask); + q11 = rte_sched_port_enqueue_qptrs_prefetch0(subport11, + pkt11, subport_qmask); /* Stage 2: Prefetch queue write location */ - q20_base = rte_sched_port_qbase(port, q20); - q21_base = rte_sched_port_qbase(port, q21); - rte_sched_port_enqueue_qwa_prefetch0(port, q20, q20_base); - rte_sched_port_enqueue_qwa_prefetch0(port, q21, q21_base); + q20_base = rte_sched_subport_pipe_qbase(subport20, q20); + q21_base = rte_sched_subport_pipe_qbase(subport21, q21); + rte_sched_port_enqueue_qwa_prefetch0(port, subport20, q20, q20_base); + rte_sched_port_enqueue_qwa_prefetch0(port, subport21, q21, q21_base); /* Stage 3: Write packet to queue and activate queue */ - r30 = rte_sched_port_enqueue_qwa(port, q30, q30_base, pkt30); - r31 = rte_sched_port_enqueue_qwa(port, q31, q31_base, pkt31); + r30 = rte_sched_port_enqueue_qwa(port, subport30, + q30, q30_base, pkt30); + r31 = rte_sched_port_enqueue_qwa(port, subport31, + q31, q31_base, pkt31); result += r30 + r31; } @@ -1932,38 +1997,52 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, pkt_last = pkts[n_pkts - 1]; rte_prefetch0(pkt_last); - q00 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt00); - q01 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt01); - - q10_base = rte_sched_port_qbase(port, q10); - q11_base = rte_sched_port_qbase(port, q11); - rte_sched_port_enqueue_qwa_prefetch0(port, q10, q10_base); - rte_sched_port_enqueue_qwa_prefetch0(port, q11, q11_base); - - r20 = rte_sched_port_enqueue_qwa(port, q20, q20_base, pkt20); - r21 = rte_sched_port_enqueue_qwa(port, q21, q21_base, pkt21); + subport00 = rte_sched_port_subport(port, pkt00); + subport01 = rte_sched_port_subport(port, pkt01); + q00 = rte_sched_port_enqueue_qptrs_prefetch0(subport00, + pkt00, subport_qmask); + q01 = rte_sched_port_enqueue_qptrs_prefetch0(subport01, + pkt01, subport_qmask); + + q10_base = rte_sched_subport_pipe_qbase(subport10, q10); + q11_base = rte_sched_subport_pipe_qbase(subport11, q11); + rte_sched_port_enqueue_qwa_prefetch0(port, subport10, q10, q10_base); + rte_sched_port_enqueue_qwa_prefetch0(port, subport11, q11, q11_base); + + r20 = rte_sched_port_enqueue_qwa(port, subport20, + q20, q20_base, pkt20); + r21 = rte_sched_port_enqueue_qwa(port, subport21, + q21, q21_base, pkt21); result += r20 + r21; - q_last = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt_last); + subport_last = rte_sched_port_subport(port, pkt_last); + q_last = rte_sched_port_enqueue_qptrs_prefetch0(subport_last, + pkt_last, subport_qmask); - q00_base = rte_sched_port_qbase(port, q00); - q01_base = rte_sched_port_qbase(port, q01); - rte_sched_port_enqueue_qwa_prefetch0(port, q00, q00_base); - rte_sched_port_enqueue_qwa_prefetch0(port, q01, q01_base); + q00_base = rte_sched_subport_pipe_qbase(subport00, q00); + q01_base = rte_sched_subport_pipe_qbase(subport01, q01); + rte_sched_port_enqueue_qwa_prefetch0(port, subport00, q00, q00_base); + rte_sched_port_enqueue_qwa_prefetch0(port, subport01, q01, q01_base); - r10 = rte_sched_port_enqueue_qwa(port, q10, q10_base, pkt10); - r11 = rte_sched_port_enqueue_qwa(port, q11, q11_base, pkt11); + r10 = rte_sched_port_enqueue_qwa(port, subport10, q10, + q10_base, pkt10); + r11 = rte_sched_port_enqueue_qwa(port, subport11, q11, + q11_base, pkt11); result += r10 + r11; - q_last_base = rte_sched_port_qbase(port, q_last); - rte_sched_port_enqueue_qwa_prefetch0(port, q_last, q_last_base); + q_last_base = rte_sched_subport_pipe_qbase(subport_last, q_last); + rte_sched_port_enqueue_qwa_prefetch0(port, subport_last, + q_last, q_last_base); - r00 = rte_sched_port_enqueue_qwa(port, q00, q00_base, pkt00); - r01 = rte_sched_port_enqueue_qwa(port, q01, q01_base, pkt01); + r00 = rte_sched_port_enqueue_qwa(port, subport00, q00, + q00_base, pkt00); + r01 = rte_sched_port_enqueue_qwa(port, subport01, q01, + q01_base, pkt01); result += r00 + r01; if (n_pkts & 1) { - r_last = rte_sched_port_enqueue_qwa(port, q_last, q_last_base, pkt_last); + r_last = rte_sched_port_enqueue_qwa(port, subport_last, + q_last, q_last_base, pkt_last); result += r_last; } -- 2.21.0
Update memory footprint compute function for allowing subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 100 ++++++++++------------------------- lib/librte_sched/rte_sched.h | 8 +-- 2 files changed, 34 insertions(+), 74 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index a8174afad..58f34359c 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -486,70 +486,6 @@ rte_sched_port_check_params(struct rte_sched_port_params *params) return 0; } -static uint32_t -rte_sched_port_get_array_base(struct rte_sched_port_params *params, enum rte_sched_port_array array) -{ - uint32_t n_subports_per_port = params->n_subports_per_port; - uint32_t n_pipes_per_subport = params->n_pipes_per_subport; - uint32_t n_pipes_per_port = n_pipes_per_subport * n_subports_per_port; - uint32_t n_queues_per_port = RTE_SCHED_QUEUES_PER_PIPE * n_pipes_per_subport * n_subports_per_port; - - uint32_t size_subport = n_subports_per_port * sizeof(struct rte_sched_subport); - uint32_t size_pipe = n_pipes_per_port * sizeof(struct rte_sched_pipe); - uint32_t size_queue = n_queues_per_port * sizeof(struct rte_sched_queue); - uint32_t size_queue_extra - = n_queues_per_port * sizeof(struct rte_sched_queue_extra); - uint32_t size_pipe_profiles - = params->n_max_pipe_profiles * sizeof(struct rte_sched_pipe_profile); - uint32_t size_bmp_array = rte_bitmap_get_memory_footprint(n_queues_per_port); - uint32_t size_per_pipe_queue_array, size_queue_array; - - uint32_t base, i; - - size_per_pipe_queue_array = 0; - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - if (i < RTE_SCHED_TRAFFIC_CLASS_BE) - size_per_pipe_queue_array += - params->qsize[i] * sizeof(struct rte_mbuf *); - else - size_per_pipe_queue_array += RTE_SCHED_MAX_QUEUES_PER_TC * - params->qsize[i] * sizeof(struct rte_mbuf *); - } - size_queue_array = n_pipes_per_port * size_per_pipe_queue_array; - - base = 0; - - if (array == e_RTE_SCHED_PORT_ARRAY_SUBPORT) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_subport); - - if (array == e_RTE_SCHED_PORT_ARRAY_PIPE) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_pipe); - - if (array == e_RTE_SCHED_PORT_ARRAY_QUEUE) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_queue); - - if (array == e_RTE_SCHED_PORT_ARRAY_QUEUE_EXTRA) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_queue_extra); - - if (array == e_RTE_SCHED_PORT_ARRAY_PIPE_PROFILES) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_pipe_profiles); - - if (array == e_RTE_SCHED_PORT_ARRAY_BMP_ARRAY) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_bmp_array); - - if (array == e_RTE_SCHED_PORT_ARRAY_QUEUE_ARRAY) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_queue_array); - - return base; -} - static uint32_t rte_sched_subport_get_array_base(struct rte_sched_subport_params *params, enum rte_sched_subport_array array) @@ -870,22 +806,44 @@ rte_sched_subport_check_params(struct rte_sched_subport_params *params, } uint32_t -rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params) +rte_sched_port_get_memory_footprint(struct rte_sched_port_params *port_params, + struct rte_sched_subport_params **subport_params) { - uint32_t size0, size1; + uint32_t size0 = 0, size1 = 0, i; int status; - status = rte_sched_port_check_params(params); + status = rte_sched_port_check_params(port_params); if (status != 0) { - RTE_LOG(NOTICE, SCHED, - "Port scheduler params check failed (%d)\n", status); + RTE_LOG(ERR, SCHED, + "%s: Port scheduler port params check failed (%d)\n", + __func__, status); return 0; } + for (i = 0; i < port_params->n_subports_per_port; i++) { + struct rte_sched_subport_params *sp = subport_params[i]; + + status = rte_sched_subport_check_params(sp, + port_params->n_pipes_per_subport, + port_params->rate); + if (status != 0) { + RTE_LOG(ERR, SCHED, + "%s: Port scheduler subport params check failed (%d)\n", + __func__, status); + + return 0; + } + } + size0 = sizeof(struct rte_sched_port); - size1 = rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_TOTAL); + + for (i = 0; i < port_params->n_subports_per_port; i++) { + struct rte_sched_subport_params *sp = subport_params[i]; + + size1 += rte_sched_subport_get_array_base(sp, + e_RTE_SCHED_SUBPORT_ARRAY_TOTAL); + } return size0 + size1; } diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index 5001f09ed..40f02f124 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -373,14 +373,16 @@ rte_sched_pipe_config(struct rte_sched_port *port, /** * Hierarchical scheduler memory footprint size per port * - * @param params + * @param port_params * Port scheduler configuration parameter structure + * @param subport_params + * Array of subport parameter structures * @return * Memory footprint size in bytes upon success, 0 otherwise */ uint32_t -rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params); - +rte_sched_port_get_memory_footprint(struct rte_sched_port_params *port_params, + struct rte_sched_subport_params **subport_params); /* * Statistics * -- 2.21.0
Modify packet grinder functions of the schedule to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 223 +++++++++++++++++------------------ 1 file changed, 106 insertions(+), 117 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 58f34359c..d7abe9661 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -322,24 +322,6 @@ rte_sched_port_queues_per_port(struct rte_sched_port *port) return RTE_SCHED_QUEUES_PER_PIPE * port->n_pipes_per_subport * port->n_subports_per_port; } -static inline struct rte_mbuf ** -rte_sched_port_qbase(struct rte_sched_port *port, uint32_t qindex) -{ - uint32_t pindex = qindex >> 4; - uint32_t qpos = qindex & 0xF; - - return (port->queue_array + pindex * - port->qsize_sum + port->qsize_add[qpos]); -} - -static inline uint16_t -rte_sched_port_qsize(struct rte_sched_port *port, uint32_t qindex) -{ - uint32_t tc = port->pipe_tc[qindex & (RTE_SCHED_QUEUES_PER_PIPE - 1)]; - - return port->qsize[tc]; -} - static inline uint16_t rte_sched_port_pipe_queue(struct rte_sched_port *port, uint32_t traffic_class) { @@ -1533,9 +1515,10 @@ rte_sched_queue_read_stats(struct rte_sched_port *port, #ifdef RTE_SCHED_DEBUG static inline int -rte_sched_port_queue_is_empty(struct rte_sched_port *port, uint32_t qindex) +rte_sched_port_queue_is_empty(struct rte_sched_subport *subport, + uint32_t qindex) { - struct rte_sched_queue *queue = port->queue + qindex; + struct rte_sched_queue *queue = subport->queue + qindex; return queue->qr == queue->qw; } @@ -1650,9 +1633,10 @@ rte_sched_port_red_drop(struct rte_sched_port *port, } static inline void -rte_sched_port_set_queue_empty_timestamp(struct rte_sched_port *port, uint32_t qindex) +rte_sched_port_set_queue_empty_timestamp(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t qindex) { - struct rte_sched_queue_extra *qe = port->queue_extra + qindex; + struct rte_sched_queue_extra *qe = subport->queue_extra + qindex; struct rte_red *red = &qe->red; rte_red_mark_queue_empty(red, port->time); @@ -1669,14 +1653,14 @@ static inline int rte_sched_port_red_drop(struct rte_sched_port *port __rte_unus return 0; } -#define rte_sched_port_set_queue_empty_timestamp(port, qindex) +#define rte_sched_port_set_queue_empty_timestamp(port, subport, qindex) #endif /* RTE_SCHED_RED */ #ifdef RTE_SCHED_DEBUG static inline void -debug_check_queue_slab(struct rte_sched_port *port, uint32_t bmp_pos, +debug_check_queue_slab(struct rte_sched_subport *subport, uint32_t bmp_pos, uint64_t bmp_slab) { uint64_t mask; @@ -1688,7 +1672,7 @@ debug_check_queue_slab(struct rte_sched_port *port, uint32_t bmp_pos, panic = 0; for (i = 0, mask = 1; i < 64; i++, mask <<= 1) { if (mask & bmp_slab) { - if (rte_sched_port_queue_is_empty(port, bmp_pos + i)) { + if (rte_sched_port_queue_is_empty(subport, bmp_pos + i)) { printf("Queue %u (slab offset %u) is empty\n", bmp_pos + i, i); panic = 1; } @@ -2010,10 +1994,10 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, #ifndef RTE_SCHED_SUBPORT_TC_OV static inline void -grinder_credits_update(struct rte_sched_port *port, uint32_t pos) +grinder_credits_update(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; struct rte_sched_pipe_profile *params = grinder->pipe_params; uint64_t n_periods; @@ -2051,10 +2035,9 @@ grinder_credits_update(struct rte_sched_port *port, uint32_t pos) #else static inline uint32_t -grinder_tc_ov_credits_update(struct rte_sched_port *port, uint32_t pos) +grinder_tc_ov_credits_update(struct rte_sched_port *port, + struct rte_sched_subport *subport) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; uint32_t tc_ov_consumption[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; uint32_t tc_consumption = 0, tc_ov_consumption_max; uint32_t tc_ov_wm = subport->tc_ov_wm; @@ -2094,10 +2077,10 @@ grinder_tc_ov_credits_update(struct rte_sched_port *port, uint32_t pos) } static inline void -grinder_credits_update(struct rte_sched_port *port, uint32_t pos) +grinder_credits_update(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; struct rte_sched_pipe_profile *params = grinder->pipe_params; uint64_t n_periods; @@ -2117,7 +2100,7 @@ grinder_credits_update(struct rte_sched_port *port, uint32_t pos) /* Subport TCs */ if (unlikely(port->time >= subport->tc_time)) { - subport->tc_ov_wm = grinder_tc_ov_credits_update(port, pos); + subport->tc_ov_wm = grinder_tc_ov_credits_update(port, subport); for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) subport->tc_credits[i] = subport->tc_credits_per_period[i]; @@ -2147,10 +2130,10 @@ grinder_credits_update(struct rte_sched_port *port, uint32_t pos) #ifndef RTE_SCHED_SUBPORT_TC_OV static inline int -grinder_credits_check(struct rte_sched_port *port, uint32_t pos) +grinder_credits_check(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; + 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; @@ -2182,10 +2165,10 @@ grinder_credits_check(struct rte_sched_port *port, uint32_t pos) #else static inline int -grinder_credits_check(struct rte_sched_port *port, uint32_t pos) +grinder_credits_check(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; + 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; @@ -2230,15 +2213,16 @@ grinder_credits_check(struct rte_sched_port *port, uint32_t pos) static inline int -grinder_schedule(struct rte_sched_port *port, uint32_t pos) +grinder_schedule(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_queue *queue = grinder->queue[grinder->qpos]; struct rte_mbuf *pkt = grinder->pkt; uint32_t pkt_len = pkt->pkt_len + port->frame_overhead; uint32_t be_tc_active; - if (!grinder_credits_check(port, pos)) + if (!grinder_credits_check(port, subport, pos)) return 0; /* Advance port time */ @@ -2255,15 +2239,15 @@ grinder_schedule(struct rte_sched_port *port, uint32_t pos) if (queue->qr == queue->qw) { uint32_t qindex = grinder->qindex[grinder->qpos]; - rte_bitmap_clear(port->bmp, qindex); + rte_bitmap_clear(subport->bmp, qindex); grinder->qmask &= ~(1 << grinder->qpos); if (be_tc_active) grinder->wrr_mask[grinder->qpos] = 0; - rte_sched_port_set_queue_empty_timestamp(port, qindex); + rte_sched_port_set_queue_empty_timestamp(port, subport, qindex); } /* Reset pipe loop detection */ - port->pipe_loop = RTE_SCHED_PIPE_INVALID; + subport->pipe_loop = RTE_SCHED_PIPE_INVALID; grinder->productive = 1; return 1; @@ -2272,13 +2256,13 @@ grinder_schedule(struct rte_sched_port *port, uint32_t pos) #ifdef SCHED_VECTOR_SSE4 static inline int -grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) +grinder_pipe_exists(struct rte_sched_subport *subport, uint32_t base_pipe) { __m128i index = _mm_set1_epi32(base_pipe); - __m128i pipes = _mm_load_si128((__m128i *)port->grinder_base_bmp_pos); + __m128i pipes = _mm_load_si128((__m128i *)subport->grinder_base_bmp_pos); __m128i res = _mm_cmpeq_epi32(pipes, index); - pipes = _mm_load_si128((__m128i *)(port->grinder_base_bmp_pos + 4)); + pipes = _mm_load_si128((__m128i *)(subport->grinder_base_bmp_pos + 4)); pipes = _mm_cmpeq_epi32(pipes, index); res = _mm_or_si128(res, pipes); @@ -2291,10 +2275,10 @@ grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) #elif defined(SCHED_VECTOR_NEON) static inline int -grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) +grinder_pipe_exists(struct rte_sched_subport *subport, uint32_t base_pipe) { uint32x4_t index, pipes; - uint32_t *pos = (uint32_t *)port->grinder_base_bmp_pos; + uint32_t *pos = (uint32_t *)subport->grinder_base_bmp_pos; index = vmovq_n_u32(base_pipe); pipes = vld1q_u32(pos); @@ -2311,12 +2295,12 @@ grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) #else static inline int -grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) +grinder_pipe_exists(struct rte_sched_subport *subport, uint32_t base_pipe) { uint32_t i; for (i = 0; i < RTE_SCHED_PORT_N_GRINDERS; i++) { - if (port->grinder_base_bmp_pos[i] == base_pipe) + if (subport->grinder_base_bmp_pos[i] == base_pipe) return 1; } @@ -2326,9 +2310,10 @@ grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) #endif /* RTE_SCHED_OPTIMIZATIONS */ static inline void -grinder_pcache_populate(struct rte_sched_port *port, uint32_t pos, uint32_t bmp_pos, uint64_t bmp_slab) +grinder_pcache_populate(struct rte_sched_subport *subport, + uint32_t pos, uint32_t bmp_pos, uint64_t bmp_slab) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint16_t w[4]; grinder->pcache_w = 0; @@ -2357,9 +2342,10 @@ grinder_pcache_populate(struct rte_sched_port *port, uint32_t pos, uint32_t bmp_ } static inline void -grinder_tccache_populate(struct rte_sched_port *port, uint32_t pos, uint32_t qindex, uint16_t qmask) +grinder_tccache_populate(struct rte_sched_subport *subport, + uint32_t pos, uint32_t qindex, uint16_t qmask) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint8_t b, i; grinder->tccache_w = 0; @@ -2380,9 +2366,10 @@ grinder_tccache_populate(struct rte_sched_port *port, uint32_t pos, uint32_t qin } static inline int -grinder_next_tc(struct rte_sched_port *port, uint32_t pos) +grinder_next_tc(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_mbuf **qbase; uint32_t qindex; uint16_t qsize; @@ -2391,15 +2378,15 @@ grinder_next_tc(struct rte_sched_port *port, uint32_t pos) return 0; qindex = grinder->tccache_qindex[grinder->tccache_r]; - qbase = rte_sched_port_qbase(port, qindex); - qsize = rte_sched_port_qsize(port, qindex); + qbase = rte_sched_subport_pipe_qbase(subport, qindex); + qsize = rte_sched_subport_pipe_qsize(port, subport, qindex); grinder->tc_index = rte_sched_port_pipe_tc(port, qindex); grinder->qmask = grinder->tccache_qmask[grinder->tccache_r]; grinder->qsize = qsize; if (grinder->tc_index < RTE_SCHED_TRAFFIC_CLASS_BE) { - grinder->queue[0] = port->queue + qindex; + grinder->queue[0] = subport->queue + qindex; grinder->qbase[0] = qbase; grinder->qindex[0] = qindex; grinder->tccache_r++; @@ -2407,10 +2394,10 @@ grinder_next_tc(struct rte_sched_port *port, uint32_t pos) return 1; } - grinder->queue[0] = port->queue + qindex; - grinder->queue[1] = port->queue + qindex + 1; - grinder->queue[2] = port->queue + qindex + 2; - grinder->queue[3] = port->queue + qindex + 3; + grinder->queue[0] = subport->queue + qindex; + grinder->queue[1] = subport->queue + qindex + 1; + grinder->queue[2] = subport->queue + qindex + 2; + grinder->queue[3] = subport->queue + qindex + 3; grinder->qbase[0] = qbase; grinder->qbase[1] = qbase + qsize; @@ -2427,9 +2414,10 @@ grinder_next_tc(struct rte_sched_port *port, uint32_t pos) } static inline int -grinder_next_pipe(struct rte_sched_port *port, uint32_t pos) +grinder_next_pipe(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint32_t pipe_qindex; uint16_t pipe_qmask; @@ -2442,22 +2430,22 @@ grinder_next_pipe(struct rte_sched_port *port, uint32_t pos) uint32_t bmp_pos = 0; /* Get another non-empty pipe group */ - if (unlikely(rte_bitmap_scan(port->bmp, &bmp_pos, &bmp_slab) <= 0)) + if (unlikely(rte_bitmap_scan(subport->bmp, &bmp_pos, &bmp_slab) <= 0)) return 0; #ifdef RTE_SCHED_DEBUG - debug_check_queue_slab(port, bmp_pos, bmp_slab); + debug_check_queue_slab(subport, bmp_pos, bmp_slab); #endif /* Return if pipe group already in one of the other grinders */ - port->grinder_base_bmp_pos[pos] = RTE_SCHED_BMP_POS_INVALID; - if (unlikely(grinder_pipe_exists(port, bmp_pos))) + subport->grinder_base_bmp_pos[pos] = RTE_SCHED_BMP_POS_INVALID; + if (unlikely(grinder_pipe_exists(subport, bmp_pos))) return 0; - port->grinder_base_bmp_pos[pos] = bmp_pos; + subport->grinder_base_bmp_pos[pos] = bmp_pos; /* Install new pipe group into grinder's pipe cache */ - grinder_pcache_populate(port, pos, bmp_pos, bmp_slab); + grinder_pcache_populate(subport, pos, bmp_pos, bmp_slab); pipe_qmask = grinder->pcache_qmask[0]; pipe_qindex = grinder->pcache_qindex[0]; @@ -2466,18 +2454,18 @@ grinder_next_pipe(struct rte_sched_port *port, uint32_t pos) /* Install new pipe in the grinder */ grinder->pindex = pipe_qindex >> 4; - grinder->subport = port->subport + (grinder->pindex / port->n_pipes_per_subport); - grinder->pipe = port->pipe + grinder->pindex; + grinder->subport = subport; + grinder->pipe = subport->pipe + grinder->pindex; grinder->pipe_params = NULL; /* to be set after the pipe structure is prefetched */ grinder->productive = 0; - grinder_tccache_populate(port, pos, pipe_qindex, pipe_qmask); - grinder_next_tc(port, pos); + grinder_tccache_populate(subport, pos, pipe_qindex, pipe_qmask); + grinder_next_tc(port, subport, pos); /* Check for pipe exhaustion */ - if (grinder->pindex == port->pipe_loop) { - port->pipe_exhaustion = 1; - port->pipe_loop = RTE_SCHED_PIPE_INVALID; + if (grinder->pindex == subport->pipe_loop) { + subport->pipe_exhaustion = 1; + subport->pipe_loop = RTE_SCHED_PIPE_INVALID; } return 1; @@ -2485,9 +2473,9 @@ grinder_next_pipe(struct rte_sched_port *port, uint32_t pos) static inline void -grinder_wrr_load(struct rte_sched_port *port, uint32_t pos) +grinder_wrr_load(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; struct rte_sched_pipe_profile *pipe_params = grinder->pipe_params; uint32_t qmask = grinder->qmask; @@ -2513,9 +2501,9 @@ grinder_wrr_load(struct rte_sched_port *port, uint32_t pos) } static inline void -grinder_wrr_store(struct rte_sched_port *port, uint32_t pos) +grinder_wrr_store(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; pipe->wrr_tokens[0] = @@ -2533,9 +2521,9 @@ grinder_wrr_store(struct rte_sched_port *port, uint32_t pos) } static inline void -grinder_wrr(struct rte_sched_port *port, uint32_t pos) +grinder_wrr(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint16_t wrr_tokens_min; grinder->wrr_tokens[0] |= ~grinder->wrr_mask[0]; @@ -2553,21 +2541,21 @@ grinder_wrr(struct rte_sched_port *port, uint32_t pos) } -#define grinder_evict(port, pos) +#define grinder_evict(subport, pos) static inline void -grinder_prefetch_pipe(struct rte_sched_port *port, uint32_t pos) +grinder_prefetch_pipe(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; rte_prefetch0(grinder->pipe); rte_prefetch0(grinder->queue[0]); } static inline void -grinder_prefetch_tc_queue_arrays(struct rte_sched_port *port, uint32_t pos) +grinder_prefetch_tc_queue_arrays(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint16_t qsize, qr[RTE_SCHED_MAX_QUEUES_PER_TC]; qsize = grinder->qsize; @@ -2588,17 +2576,17 @@ grinder_prefetch_tc_queue_arrays(struct rte_sched_port *port, uint32_t pos) rte_prefetch0(grinder->qbase[0] + qr[0]); rte_prefetch0(grinder->qbase[1] + qr[1]); - grinder_wrr_load(port, pos); - grinder_wrr(port, pos); + grinder_wrr_load(subport, pos); + grinder_wrr(subport, pos); rte_prefetch0(grinder->qbase[2] + qr[2]); rte_prefetch0(grinder->qbase[3] + qr[3]); } static inline void -grinder_prefetch_mbuf(struct rte_sched_port *port, uint32_t pos) +grinder_prefetch_mbuf(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint32_t qpos = grinder->qpos; struct rte_mbuf **qbase = grinder->qbase[qpos]; uint16_t qsize = grinder->qsize; @@ -2617,14 +2605,15 @@ grinder_prefetch_mbuf(struct rte_sched_port *port, uint32_t pos) static inline uint32_t grinder_handle(struct rte_sched_port *port, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_subport *subport = port->subport; + struct rte_sched_grinder *grinder = subport->grinder + pos; switch (grinder->state) { case e_GRINDER_PREFETCH_PIPE: { - if (grinder_next_pipe(port, pos)) { - grinder_prefetch_pipe(port, pos); - port->busy_grinders++; + if (grinder_next_pipe(port, subport, pos)) { + grinder_prefetch_pipe(subport, pos); + subport->busy_grinders++; grinder->state = e_GRINDER_PREFETCH_TC_QUEUE_ARRAYS; return 0; @@ -2637,9 +2626,9 @@ grinder_handle(struct rte_sched_port *port, uint32_t pos) { struct rte_sched_pipe *pipe = grinder->pipe; - grinder->pipe_params = port->pipe_profiles + pipe->profile; - grinder_prefetch_tc_queue_arrays(port, pos); - grinder_credits_update(port, pos); + grinder->pipe_params = subport->pipe_profiles + pipe->profile; + grinder_prefetch_tc_queue_arrays(subport, pos); + grinder_credits_update(port, subport, pos); grinder->state = e_GRINDER_PREFETCH_MBUF; return 0; @@ -2647,7 +2636,7 @@ grinder_handle(struct rte_sched_port *port, uint32_t pos) case e_GRINDER_PREFETCH_MBUF: { - grinder_prefetch_mbuf(port, pos); + grinder_prefetch_mbuf(subport, pos); grinder->state = e_GRINDER_READ_MBUF; return 0; @@ -2657,47 +2646,47 @@ grinder_handle(struct rte_sched_port *port, uint32_t pos) { uint32_t wrr_active, result = 0; - result = grinder_schedule(port, pos); + result = grinder_schedule(port, subport, pos); wrr_active = (grinder->tc_index == RTE_SCHED_TRAFFIC_CLASS_BE); /* Look for next packet within the same TC */ if (result && grinder->qmask) { if (wrr_active) - grinder_wrr(port, pos); + grinder_wrr(subport, pos); - grinder_prefetch_mbuf(port, pos); + grinder_prefetch_mbuf(subport, pos); return 1; } if (wrr_active) - grinder_wrr_store(port, pos); + grinder_wrr_store(subport, pos); /* Look for another active TC within same pipe */ - if (grinder_next_tc(port, pos)) { - grinder_prefetch_tc_queue_arrays(port, pos); + if (grinder_next_tc(port, subport, pos)) { + grinder_prefetch_tc_queue_arrays(subport, pos); grinder->state = e_GRINDER_PREFETCH_MBUF; return result; } if (grinder->productive == 0 && - port->pipe_loop == RTE_SCHED_PIPE_INVALID) - port->pipe_loop = grinder->pindex; + subport->pipe_loop == RTE_SCHED_PIPE_INVALID) + subport->pipe_loop = grinder->pindex; - grinder_evict(port, pos); + grinder_evict(subport, pos); /* Look for another active pipe */ - if (grinder_next_pipe(port, pos)) { - grinder_prefetch_pipe(port, pos); + if (grinder_next_pipe(port, subport, pos)) { + grinder_prefetch_pipe(subport, pos); grinder->state = e_GRINDER_PREFETCH_TC_QUEUE_ARRAYS; return result; } /* No active pipe found */ - port->busy_grinders--; + subport->busy_grinders--; grinder->state = e_GRINDER_PREFETCH_PIPE; return result; -- 2.21.0
Modify scheduler packet dequeue operation to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 51 ++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index d7abe9661..e14506b2d 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -243,6 +243,7 @@ struct rte_sched_port { uint32_t busy_grinders; struct rte_mbuf **pkts_out; uint32_t n_pkts_out; + uint32_t subport_id; /* Queue base calculation */ uint32_t qsize_add[RTE_SCHED_QUEUES_PER_PIPE]; @@ -898,6 +899,7 @@ rte_sched_port_config(struct rte_sched_port_params *params) /* Grinders */ port->pkts_out = NULL; port->n_pkts_out = 0; + port->subport_id = 0; return port; } @@ -2603,9 +2605,9 @@ grinder_prefetch_mbuf(struct rte_sched_subport *subport, uint32_t pos) } static inline uint32_t -grinder_handle(struct rte_sched_port *port, uint32_t pos) +grinder_handle(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_subport *subport = port->subport; struct rte_sched_grinder *grinder = subport->grinder + pos; switch (grinder->state) { @@ -2704,6 +2706,7 @@ rte_sched_port_time_resync(struct rte_sched_port *port) uint64_t cycles = rte_get_tsc_cycles(); uint64_t cycles_diff = cycles - port->time_cpu_cycles; uint64_t bytes_diff; + uint32_t i; /* Compute elapsed time in bytes */ bytes_diff = rte_reciprocal_divide(cycles_diff << RTE_SCHED_TIME_SHIFT, @@ -2716,20 +2719,21 @@ rte_sched_port_time_resync(struct rte_sched_port *port) port->time = port->time_cpu_bytes; /* Reset pipe loop detection */ - port->pipe_loop = RTE_SCHED_PIPE_INVALID; + for (i = 0; i < port->n_subports_per_port; i++) + port->subports[i]->pipe_loop = RTE_SCHED_PIPE_INVALID; } static inline int -rte_sched_port_exceptions(struct rte_sched_port *port, int second_pass) +rte_sched_port_exceptions(struct rte_sched_subport *subport, int second_pass) { int exceptions; /* Check if any exception flag is set */ - exceptions = (second_pass && port->busy_grinders == 0) || - (port->pipe_exhaustion == 1); + exceptions = (second_pass && subport->busy_grinders == 0) || + (subport->pipe_exhaustion == 1); /* Clear exception flags */ - port->pipe_exhaustion = 0; + subport->pipe_exhaustion = 0; return exceptions; } @@ -2737,7 +2741,9 @@ rte_sched_port_exceptions(struct rte_sched_port *port, int second_pass) int rte_sched_port_dequeue(struct rte_sched_port *port, struct rte_mbuf **pkts, uint32_t n_pkts) { - uint32_t i, count; + struct rte_sched_subport *subport; + uint32_t subport_id = port->subport_id; + uint32_t i, n_subports = 0, count; port->pkts_out = pkts; port->n_pkts_out = 0; @@ -2746,9 +2752,32 @@ rte_sched_port_dequeue(struct rte_sched_port *port, struct rte_mbuf **pkts, uint /* Take each queue in the grinder one step further */ for (i = 0, count = 0; ; i++) { - count += grinder_handle(port, i & (RTE_SCHED_PORT_N_GRINDERS - 1)); - if ((count == n_pkts) || - rte_sched_port_exceptions(port, i >= RTE_SCHED_PORT_N_GRINDERS)) { + subport = port->subports[subport_id]; + + count += grinder_handle(port, subport, + i & (RTE_SCHED_PORT_N_GRINDERS - 1)); + + if (count == n_pkts) { + subport_id++; + + if (subport_id == port->n_subports_per_port) + subport_id = 0; + + port->subport_id = subport_id; + break; + } + + if (rte_sched_port_exceptions(subport, i >= RTE_SCHED_PORT_N_GRINDERS)) { + i = 0; + subport_id++; + n_subports++; + } + + if (subport_id == port->n_subports_per_port) + subport_id = 0; + + if (n_subports == port->n_subports_per_port) { + port->subport_id = subport_id; break; } } -- 2.21.0
Modify pipe queue stats read function to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index e14506b2d..1faa580d0 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -282,16 +282,6 @@ enum rte_sched_subport_array { e_RTE_SCHED_SUBPORT_ARRAY_TOTAL, }; -#ifdef RTE_SCHED_COLLECT_STATS - -static inline uint32_t -rte_sched_port_queues_per_subport(struct rte_sched_port *port) -{ - return RTE_SCHED_QUEUES_PER_PIPE * port->n_pipes_per_subport; -} - -#endif - static inline uint32_t rte_sched_subport_pipe_queues(struct rte_sched_subport *subport) { @@ -320,7 +310,12 @@ struct rte_sched_subport *subport, uint32_t qindex) static inline uint32_t rte_sched_port_queues_per_port(struct rte_sched_port *port) { - return RTE_SCHED_QUEUES_PER_PIPE * port->n_pipes_per_subport * port->n_subports_per_port; + uint32_t n_queues = 0, i; + + for (i = 0; i < port->n_subports_per_port; i++) + n_queues += rte_sched_subport_pipe_queues(port->subports[i]); + + return n_queues; } static inline uint16_t @@ -1474,8 +1469,10 @@ rte_sched_queue_read_stats(struct rte_sched_port *port, struct rte_sched_queue_stats *stats, uint16_t *qlen) { + struct rte_sched_subport *s; struct rte_sched_queue *q; struct rte_sched_queue_extra *qe; + uint32_t subport_id, subport_qmask, subport_qindex; /* Check user parameters */ if (port == NULL) { @@ -1501,8 +1498,13 @@ rte_sched_queue_read_stats(struct rte_sched_port *port, "%s: Incorrect value for parameter qlen\n", __func__); return -EINVAL; } - q = port->queue + queue_id; - qe = port->queue_extra + queue_id; + subport_qmask = port->n_pipes_per_subport_log2 + 4; + subport_id = (queue_id >> subport_qmask) & (port->n_subports_per_port - 1); + + s = port->subports[subport_id]; + subport_qindex = ((1 << subport_qmask) - 1) & queue_id; + q = s->queue + subport_qindex; + qe = s->queue_extra + subport_qindex; /* Copy queue stats and clear */ memcpy(stats, &qe->stats, sizeof(struct rte_sched_queue_stats)); -- 2.21.0
Modify tests function to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- app/test/test_sched.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/app/test/test_sched.c b/app/test/test_sched.c index afe0b0765..fc31080ef 100644 --- a/app/test/test_sched.c +++ b/app/test/test_sched.c @@ -22,18 +22,6 @@ #define TC 2 #define QUEUE 0 -static struct rte_sched_subport_params subport_param[] = { - { - .tb_rate = 1250000000, - .tb_size = 1000000, - - .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000, - 1250000000, 1250000000, 1250000000, 1250000000, 1250000000, - 1250000000, 1250000000, 1250000000, 1250000000}, - .tc_period = 10, - }, -}; - static struct rte_sched_pipe_params pipe_profile[] = { { /* Profile #0 */ .tb_rate = 305175, @@ -48,6 +36,23 @@ static struct rte_sched_pipe_params pipe_profile[] = { }, }; +static struct rte_sched_subport_params subport_param[] = { + { + .tb_rate = 1250000000, + .tb_size = 1000000, + + .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000, + 1250000000, 1250000000, 1250000000, 1250000000, 1250000000, + 1250000000, 1250000000, 1250000000, 1250000000}, + .tc_period = 10, + .n_pipes_per_subport_enabled = 1024, + .qsize = {32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}, + .pipe_profiles = pipe_profile, + .n_pipe_profiles = 1, + .n_max_pipe_profiles = 1, + }, +}; + static struct rte_sched_port_params port_param = { .socket = 0, /* computed */ .rate = 0, /* computed */ @@ -55,10 +60,6 @@ static struct rte_sched_port_params port_param = { .frame_overhead = RTE_SCHED_FRAME_OVERHEAD_DEFAULT, .n_subports_per_port = 1, .n_pipes_per_subport = 1024, - .qsize = {32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}, - .pipe_profiles = pipe_profile, - .n_pipe_profiles = 1, - .n_max_pipe_profiles = 1, }; #define NB_MBUF 32 @@ -140,7 +141,7 @@ test_sched(void) err = rte_sched_subport_config(port, SUBPORT, subport_param); TEST_ASSERT_SUCCESS(err, "Error config sched, err=%d\n", err); - for (pipe = 0; pipe < port_param.n_pipes_per_subport; pipe ++) { + for (pipe = 0; pipe < subport_param[0].n_pipes_per_subport_enabled; pipe++) { err = rte_sched_pipe_config(port, SUBPORT, pipe, 0); TEST_ASSERT_SUCCESS(err, "Error config sched pipe %u, err=%d\n", pipe, err); } -- 2.21.0
Modify softnic traffic management function to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- drivers/net/softnic/rte_eth_softnic_tm.c | 54 ++++++++++++------------ 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/drivers/net/softnic/rte_eth_softnic_tm.c b/drivers/net/softnic/rte_eth_softnic_tm.c index 61c3adc82..80a470c9e 100644 --- a/drivers/net/softnic/rte_eth_softnic_tm.c +++ b/drivers/net/softnic/rte_eth_softnic_tm.c @@ -85,7 +85,8 @@ softnic_tmgr_port_create(struct pmd_internals *p, /* Subport */ n_subports = t->port_params.n_subports_per_port; for (subport_id = 0; subport_id < n_subports; subport_id++) { - uint32_t n_pipes_per_subport = t->port_params.n_pipes_per_subport; + uint32_t n_pipes_per_subport = + t->subport_params[subport_id].n_pipes_per_subport_enabled; uint32_t pipe_id; int status; @@ -2211,10 +2212,11 @@ tm_tc_wred_profile_get(struct rte_eth_dev *dev, uint32_t tc_id) #ifdef RTE_SCHED_RED static void -wred_profiles_set(struct rte_eth_dev *dev) +wred_profiles_set(struct rte_eth_dev *dev, uint32_t subport_id) { struct pmd_internals *p = dev->data->dev_private; - struct rte_sched_port_params *pp = &p->soft.tm.params.port_params; + struct rte_sched_subport_params *pp = + &p->soft.tm.params.subport_params[subport_id]; uint32_t tc_id; enum rte_color color; @@ -2234,7 +2236,7 @@ wred_profiles_set(struct rte_eth_dev *dev) #else -#define wred_profiles_set(dev) +#define wred_profiles_set(dev, subport_id) #endif @@ -2526,29 +2528,9 @@ hierarchy_blueprints_create(struct rte_eth_dev *dev) .frame_overhead = root->shaper_profile->params.pkt_length_adjust, .n_subports_per_port = root->n_children, - .n_pipes_per_subport = h->n_tm_nodes[TM_NODE_LEVEL_PIPE] / - h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT], - .qsize = {p->params.tm.qsize[0], - p->params.tm.qsize[1], - p->params.tm.qsize[2], - p->params.tm.qsize[3], - p->params.tm.qsize[4], - p->params.tm.qsize[5], - p->params.tm.qsize[6], - p->params.tm.qsize[7], - p->params.tm.qsize[8], - p->params.tm.qsize[9], - p->params.tm.qsize[10], - p->params.tm.qsize[11], - p->params.tm.qsize[12], - }, - .pipe_profiles = t->pipe_profiles, - .n_pipe_profiles = t->n_pipe_profiles, - .n_max_pipe_profiles = TM_MAX_PIPE_PROFILE, + .n_pipes_per_subport = TM_MAX_PIPES_PER_SUBPORT, }; - wred_profiles_set(dev); - subport_id = 0; TAILQ_FOREACH(n, nl, node) { uint64_t tc_rate[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; @@ -2588,8 +2570,28 @@ hierarchy_blueprints_create(struct rte_eth_dev *dev) tc_rate[12], }, .tc_period = SUBPORT_TC_PERIOD, + .n_pipes_per_subport_enabled = + h->n_tm_nodes[TM_NODE_LEVEL_PIPE] / + h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT], + .qsize = {p->params.tm.qsize[0], + p->params.tm.qsize[1], + p->params.tm.qsize[2], + p->params.tm.qsize[3], + p->params.tm.qsize[4], + p->params.tm.qsize[5], + p->params.tm.qsize[6], + p->params.tm.qsize[7], + p->params.tm.qsize[8], + p->params.tm.qsize[9], + p->params.tm.qsize[10], + p->params.tm.qsize[11], + p->params.tm.qsize[12], + }, + .pipe_profiles = t->pipe_profiles, + .n_pipe_profiles = t->n_pipe_profiles, + .n_max_pipe_profiles = TM_MAX_PIPE_PROFILE, }; - + wred_profiles_set(dev, subport_id); subport_id++; } } -- 2.21.0
Modify ip pipeline traffic management function to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- examples/ip_pipeline/cli.c | 71 ++++++++++++++++++------------------- examples/ip_pipeline/tmgr.c | 25 +++++++------ examples/ip_pipeline/tmgr.h | 7 ++-- 3 files changed, 51 insertions(+), 52 deletions(-) diff --git a/examples/ip_pipeline/cli.c b/examples/ip_pipeline/cli.c index c6cf4204e..e37a84444 100644 --- a/examples/ip_pipeline/cli.c +++ b/examples/ip_pipeline/cli.c @@ -380,7 +380,12 @@ static const char cmd_tmgr_subport_profile_help[] = " <tc0_rate> <tc1_rate> <tc2_rate> <tc3_rate> <tc4_rate>" " <tc5_rate> <tc6_rate> <tc7_rate> <tc8_rate>" " <tc9_rate> <tc10_rate> <tc11_rate> <tc12_rate>\n" -" <tc_period>\n"; +" <tc_period>\n" +" pps <n_pipes_per_subport>\n" +" qsize <qsize_tc0> <qsize_tc1> <qsize_tc2>" +" <qsize_tc3> <qsize_tc4> <qsize_tc5> <qsize_tc6>" +" <qsize_tc7> <qsize_tc8> <qsize_tc9> <qsize_tc10>" +" <qsize_tc11> <qsize_tc12>"; static void cmd_tmgr_subport_profile(char **tokens, @@ -391,7 +396,7 @@ cmd_tmgr_subport_profile(char **tokens, struct rte_sched_subport_params p; int status, i; - if (n_tokens != 19) { + if (n_tokens != 35) { snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); return; } @@ -417,6 +422,27 @@ cmd_tmgr_subport_profile(char **tokens, return; } + if (strcmp(tokens[19], "pps") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps"); + return; + } + + if (parser_read_uint32(&p.n_pipes_per_subport_enabled, tokens[20]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "n_pipes_per_subport"); + return; + } + + if (strcmp(tokens[21], "qsize") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "qsize"); + return; + } + + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) + if (parser_read_uint16(&p.qsize[i], tokens[22 + i]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "qsize"); + return; + } + status = tmgr_subport_profile_add(&p); if (status != 0) { snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); @@ -491,11 +517,6 @@ static const char cmd_tmgr_help[] = "tmgr <tmgr_name>\n" " rate <rate>\n" " spp <n_subports_per_port>\n" -" pps <n_pipes_per_subport>\n" -" qsize <qsize_tc0> <qsize_tc1> <qsize_tc2>" -" <qsize_tc3> <qsize_tc4> <qsize_tc5> <qsize_tc6>" -" <qsize_tc7> <qsize_tc8> <qsize_tc9> <qsize_tc10>" -" <qsize_tc11> <qsize_tc12>\n" " fo <frame_overhead>\n" " mtu <mtu>\n" " cpu <cpu_id>\n"; @@ -509,9 +530,8 @@ cmd_tmgr(char **tokens, struct tmgr_port_params p; char *name; struct tmgr_port *tmgr_port; - int i; - if (n_tokens != 28) { + if (n_tokens != 12) { snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); return; } @@ -538,53 +558,32 @@ cmd_tmgr(char **tokens, return; } - if (strcmp(tokens[6], "pps") != 0) { - snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps"); - return; - } - - if (parser_read_uint32(&p.n_pipes_per_subport, tokens[7]) != 0) { - snprintf(out, out_size, MSG_ARG_INVALID, "n_pipes_per_subport"); - return; - } - - if (strcmp(tokens[8], "qsize") != 0) { - snprintf(out, out_size, MSG_ARG_NOT_FOUND, "qsize"); - return; - } - - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - if (parser_read_uint16(&p.qsize[i], tokens[9 + i]) != 0) { - snprintf(out, out_size, MSG_ARG_INVALID, "qsize"); - return; - } - - if (strcmp(tokens[22], "fo") != 0) { + if (strcmp(tokens[6], "fo") != 0) { snprintf(out, out_size, MSG_ARG_NOT_FOUND, "fo"); return; } - if (parser_read_uint32(&p.frame_overhead, tokens[23]) != 0) { + if (parser_read_uint32(&p.frame_overhead, tokens[7]) != 0) { snprintf(out, out_size, MSG_ARG_INVALID, "frame_overhead"); return; } - if (strcmp(tokens[24], "mtu") != 0) { + if (strcmp(tokens[8], "mtu") != 0) { snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mtu"); return; } - if (parser_read_uint32(&p.mtu, tokens[25]) != 0) { + if (parser_read_uint32(&p.mtu, tokens[9]) != 0) { snprintf(out, out_size, MSG_ARG_INVALID, "mtu"); return; } - if (strcmp(tokens[26], "cpu") != 0) { + if (strcmp(tokens[10], "cpu") != 0) { snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu"); return; } - if (parser_read_uint32(&p.cpu_id, tokens[27]) != 0) { + if (parser_read_uint32(&p.cpu_id, tokens[11]) != 0) { snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id"); return; } diff --git a/examples/ip_pipeline/tmgr.c b/examples/ip_pipeline/tmgr.c index 40cbf1d0a..91ccbf60f 100644 --- a/examples/ip_pipeline/tmgr.c +++ b/examples/ip_pipeline/tmgr.c @@ -47,7 +47,8 @@ int tmgr_subport_profile_add(struct rte_sched_subport_params *p) { /* Check input params */ - if (p == NULL) + if (p == NULL || + p->n_pipes_per_subport_enabled == 0) return -1; /* Save profile */ @@ -90,7 +91,6 @@ tmgr_port_create(const char *name, struct tmgr_port_params *params) tmgr_port_find(name) || (params == NULL) || (params->n_subports_per_port == 0) || - (params->n_pipes_per_subport == 0) || (params->cpu_id >= RTE_MAX_NUMA_NODES) || (n_subport_profiles == 0) || (n_pipe_profiles == 0)) @@ -103,18 +103,16 @@ tmgr_port_create(const char *name, struct tmgr_port_params *params) p.mtu = params->mtu; p.frame_overhead = params->frame_overhead; p.n_subports_per_port = params->n_subports_per_port; - p.n_pipes_per_subport = params->n_pipes_per_subport; - - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - p.qsize[i] = params->qsize[i]; - - p.pipe_profiles = pipe_profile; - p.n_pipe_profiles = n_pipe_profiles; + p.n_pipes_per_subport = TMGR_PIPE_SUBPORT_MAX; s = rte_sched_port_config(&p); if (s == NULL) return NULL; + subport_profile[0].pipe_profiles = pipe_profile; + subport_profile[0].n_pipe_profiles = n_pipe_profiles; + subport_profile[0].n_max_pipe_profiles = TMGR_PIPE_PROFILE_MAX; + for (i = 0; i < params->n_subports_per_port; i++) { int status; @@ -128,7 +126,7 @@ tmgr_port_create(const char *name, struct tmgr_port_params *params) return NULL; } - for (j = 0; j < params->n_pipes_per_subport; j++) { + for (j = 0; j < subport_profile[0].n_pipes_per_subport_enabled; j++) { status = rte_sched_pipe_config( s, i, @@ -153,7 +151,6 @@ tmgr_port_create(const char *name, struct tmgr_port_params *params) strlcpy(tmgr_port->name, name, sizeof(tmgr_port->name)); tmgr_port->s = s; tmgr_port->n_subports_per_port = params->n_subports_per_port; - tmgr_port->n_pipes_per_subport = params->n_pipes_per_subport; /* Node add to list */ TAILQ_INSERT_TAIL(&tmgr_port_list, tmgr_port, node); @@ -205,8 +202,10 @@ tmgr_pipe_config(const char *port_name, port = tmgr_port_find(port_name); if ((port == NULL) || (subport_id >= port->n_subports_per_port) || - (pipe_id_first >= port->n_pipes_per_subport) || - (pipe_id_last >= port->n_pipes_per_subport) || + (pipe_id_first >= + subport_profile[subport_id].n_pipes_per_subport_enabled) || + (pipe_id_last >= + subport_profile[subport_id].n_pipes_per_subport_enabled) || (pipe_id_first > pipe_id_last) || (pipe_profile_id >= n_pipe_profiles)) return -1; diff --git a/examples/ip_pipeline/tmgr.h b/examples/ip_pipeline/tmgr.h index 8703a2e00..1fcf66ee1 100644 --- a/examples/ip_pipeline/tmgr.h +++ b/examples/ip_pipeline/tmgr.h @@ -12,6 +12,10 @@ #include "common.h" +#ifndef TMGR_PIPE_SUBPORT_MAX +#define TMGR_PIPE_SUBPORT_MAX 4096 +#endif + #ifndef TMGR_SUBPORT_PROFILE_MAX #define TMGR_SUBPORT_PROFILE_MAX 256 #endif @@ -25,7 +29,6 @@ struct tmgr_port { char name[NAME_SIZE]; struct rte_sched_port *s; uint32_t n_subports_per_port; - uint32_t n_pipes_per_subport; }; TAILQ_HEAD(tmgr_port_list, tmgr_port); @@ -42,8 +45,6 @@ struct tmgr_port_params { uint32_t frame_overhead; uint32_t mtu; uint32_t cpu_id; - uint32_t n_pipes_per_subport; - uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; }; int -- 2.21.0
Modify qos sample app to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- examples/qos_sched/app_thread.c | 20 ++- examples/qos_sched/cfg_file.c | 229 ++++++++++++++++-------------- examples/qos_sched/init.c | 54 +++---- examples/qos_sched/main.h | 1 + examples/qos_sched/profile.cfg | 5 +- examples/qos_sched/profile_ov.cfg | 5 +- examples/qos_sched/stats.c | 44 +++--- 7 files changed, 203 insertions(+), 155 deletions(-) diff --git a/examples/qos_sched/app_thread.c b/examples/qos_sched/app_thread.c index 18b734a14..dbc878b55 100644 --- a/examples/qos_sched/app_thread.c +++ b/examples/qos_sched/app_thread.c @@ -35,15 +35,25 @@ get_pkt_sched(struct rte_mbuf *m, uint32_t *subport, uint32_t *pipe, uint16_t *pdata = rte_pktmbuf_mtod(m, uint16_t *); uint16_t pipe_queue; + /* Outer VLAN ID*/ *subport = (rte_be_to_cpu_16(pdata[SUBPORT_OFFSET]) & 0x0FFF) & - (port_params.n_subports_per_port - 1); /* Outer VLAN ID*/ + (port_params.n_subports_per_port - 1); + + /* Inner VLAN ID */ *pipe = (rte_be_to_cpu_16(pdata[PIPE_OFFSET]) & 0x0FFF) & - (port_params.n_pipes_per_subport - 1); /* Inner VLAN ID */ + (subport_params[*subport].n_pipes_per_subport_enabled - 1); + pipe_queue = active_queues[(pdata[QUEUE_OFFSET] >> 8) % n_active_queues]; + + /* Traffic class (Destination IP) */ *traffic_class = pipe_queue > RTE_SCHED_TRAFFIC_CLASS_BE ? - RTE_SCHED_TRAFFIC_CLASS_BE : pipe_queue; /* Destination IP */ - *queue = pipe_queue - *traffic_class; /* Destination IP */ - *color = pdata[COLOR_OFFSET] & 0x03; /* Destination IP */ + RTE_SCHED_TRAFFIC_CLASS_BE : pipe_queue; + + /* Traffic class queue (Destination IP) */ + *queue = pipe_queue - *traffic_class; + + /* Color (Destination IP) */ + *color = pdata[COLOR_OFFSET] & 0x03; return 0; } diff --git a/examples/qos_sched/cfg_file.c b/examples/qos_sched/cfg_file.c index 45bf599e4..c6d3f5ab6 100644 --- a/examples/qos_sched/cfg_file.c +++ b/examples/qos_sched/cfg_file.c @@ -24,14 +24,10 @@ int cfg_load_port(struct rte_cfgfile *cfg, struct rte_sched_port_params *port_params) { const char *entry; - int j; if (!cfg || !port_params) return -1; - memset(active_queues, 0, sizeof(active_queues)); - n_active_queues = 0; - entry = rte_cfgfile_get_entry(cfg, "port", "frame overhead"); if (entry) port_params->frame_overhead = (uint32_t)atoi(entry); @@ -40,106 +36,6 @@ cfg_load_port(struct rte_cfgfile *cfg, struct rte_sched_port_params *port_params if (entry) port_params->n_subports_per_port = (uint32_t)atoi(entry); - entry = rte_cfgfile_get_entry(cfg, "port", "number of pipes per subport"); - if (entry) - port_params->n_pipes_per_subport = (uint32_t)atoi(entry); - - entry = rte_cfgfile_get_entry(cfg, "port", "queue sizes"); - if (entry) { - char *next; - - for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { - port_params->qsize[j] = (uint16_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - - for (j = 0; j < RTE_SCHED_TRAFFIC_CLASS_BE; j++) - if (port_params->qsize[j]) { - active_queues[n_active_queues] = j; - n_active_queues++; - } - - if (port_params->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]) - for (j = 0; j < RTE_SCHED_BE_QUEUES_PER_PIPE; j++) { - active_queues[n_active_queues] = - RTE_SCHED_TRAFFIC_CLASS_BE + j; - n_active_queues++; - } - } - -#ifdef RTE_SCHED_RED - for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { - char str[32]; - - /* Parse WRED min thresholds */ - snprintf(str, sizeof(str), "tc %d wred min", j); - entry = rte_cfgfile_get_entry(cfg, "red", str); - if (entry) { - char *next; - int k; - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < RTE_COLORS; k++) { - port_params->red_params[j][k].min_th - = (uint16_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - } - - /* Parse WRED max thresholds */ - snprintf(str, sizeof(str), "tc %d wred max", j); - entry = rte_cfgfile_get_entry(cfg, "red", str); - if (entry) { - char *next; - int k; - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < RTE_COLORS; k++) { - port_params->red_params[j][k].max_th - = (uint16_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - } - - /* Parse WRED inverse mark probabilities */ - snprintf(str, sizeof(str), "tc %d wred inv prob", j); - entry = rte_cfgfile_get_entry(cfg, "red", str); - if (entry) { - char *next; - int k; - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < RTE_COLORS; k++) { - port_params->red_params[j][k].maxp_inv - = (uint8_t)strtol(entry, &next, 10); - - if (next == NULL) - break; - entry = next; - } - } - - /* Parse WRED EWMA filter weights */ - snprintf(str, sizeof(str), "tc %d wred weight", j); - entry = rte_cfgfile_get_entry(cfg, "red", str); - if (entry) { - char *next; - int k; - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < RTE_COLORS; k++) { - port_params->red_params[j][k].wq_log2 - = (uint8_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - } - } -#endif /* RTE_SCHED_RED */ - return 0; } @@ -155,7 +51,7 @@ cfg_load_pipe(struct rte_cfgfile *cfg, struct rte_sched_pipe_params *pipe_params return -1; profiles = rte_cfgfile_num_sections(cfg, "pipe profile", sizeof("pipe profile") - 1); - port_params.n_pipe_profiles = profiles; + subport_params[0].n_pipe_profiles = profiles; for (j = 0; j < profiles; j++) { char pipe_name[32]; @@ -253,12 +149,121 @@ cfg_load_subport(struct rte_cfgfile *cfg, struct rte_sched_subport_params *subpo return -1; memset(app_pipe_to_profile, -1, sizeof(app_pipe_to_profile)); + memset(active_queues, 0, sizeof(active_queues)); + n_active_queues = 0; + +#ifdef RTE_SCHED_RED + char sec_name[CFG_NAME_LEN]; + struct rte_red_params red_params[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; + + snprintf(sec_name, sizeof(sec_name), "red"); + + if (rte_cfgfile_has_section(cfg, sec_name)) { + + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + char str[32]; + + /* Parse WRED min thresholds */ + snprintf(str, sizeof(str), "tc %d wred min", i); + entry = rte_cfgfile_get_entry(cfg, sec_name, str); + if (entry) { + char *next; + /* for each packet colour (green, yellow, red) */ + for (j = 0; j < RTE_COLORS; j++) { + red_params[i][j].min_th + = (uint16_t)strtol(entry, &next, 10); + if (next == NULL) + break; + entry = next; + } + } + + /* Parse WRED max thresholds */ + snprintf(str, sizeof(str), "tc %d wred max", i); + entry = rte_cfgfile_get_entry(cfg, "red", str); + if (entry) { + char *next; + /* for each packet colour (green, yellow, red) */ + for (j = 0; j < RTE_COLORS; j++) { + red_params[i][j].max_th + = (uint16_t)strtol(entry, &next, 10); + if (next == NULL) + break; + entry = next; + } + } + + /* Parse WRED inverse mark probabilities */ + snprintf(str, sizeof(str), "tc %d wred inv prob", i); + entry = rte_cfgfile_get_entry(cfg, "red", str); + if (entry) { + char *next; + /* for each packet colour (green, yellow, red) */ + for (j = 0; j < RTE_COLORS; j++) { + red_params[i][j].maxp_inv + = (uint8_t)strtol(entry, &next, 10); + + if (next == NULL) + break; + entry = next; + } + } + + /* Parse WRED EWMA filter weights */ + snprintf(str, sizeof(str), "tc %d wred weight", i); + entry = rte_cfgfile_get_entry(cfg, "red", str); + if (entry) { + char *next; + /* for each packet colour (green, yellow, red) */ + for (j = 0; j < RTE_COLORS; j++) { + red_params[i][j].wq_log2 + = (uint8_t)strtol(entry, &next, 10); + if (next == NULL) + break; + entry = next; + } + } + } + } +#endif /* RTE_SCHED_RED */ for (i = 0; i < MAX_SCHED_SUBPORTS; i++) { char sec_name[CFG_NAME_LEN]; snprintf(sec_name, sizeof(sec_name), "subport %d", i); if (rte_cfgfile_has_section(cfg, sec_name)) { + entry = rte_cfgfile_get_entry(cfg, sec_name, + "number of pipes per subport"); + if (entry) + subport_params[i].n_pipes_per_subport_enabled = + (uint32_t)atoi(entry); + + entry = rte_cfgfile_get_entry(cfg, sec_name, "queue sizes"); + if (entry) { + char *next; + + for (j = 0; j < RTE_SCHED_TRAFFIC_CLASS_BE; j++) { + subport_params[i].qsize[j] = + (uint16_t)strtol(entry, &next, 10); + if (subport_params[i].qsize[j] != 0) { + active_queues[n_active_queues] = j; + n_active_queues++; + } + if (next == NULL) + break; + entry = next; + } + + subport_params[i].qsize[RTE_SCHED_TRAFFIC_CLASS_BE] = + (uint16_t)strtol(entry, &next, 10); + + for (j = 0; j < RTE_SCHED_BE_QUEUES_PER_PIPE; j++) { + active_queues[n_active_queues] = + RTE_SCHED_TRAFFIC_CLASS_BE + j; + n_active_queues++; + } + } + entry = rte_cfgfile_get_entry(cfg, sec_name, "tb rate"); if (entry) subport_params[i].tb_rate = (uint32_t)atoi(entry); @@ -362,6 +367,20 @@ cfg_load_subport(struct rte_cfgfile *cfg, struct rte_sched_subport_params *subpo } } } +#ifdef RTE_SCHED_RED + for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { + for (k = 0; k < RTE_COLORS; k++) { + subport_params[i].red_params[j][k].min_th = + red_params[j][k].min_th; + subport_params[i].red_params[j][k].max_th = + red_params[j][k].max_th; + subport_params[i].red_params[j][k].maxp_inv = + red_params[j][k].maxp_inv; + subport_params[i].red_params[j][k].wq_log2 = + red_params[j][k].wq_log2; + } + } +#endif } } diff --git a/examples/qos_sched/init.c b/examples/qos_sched/init.c index b05206d5a..6af01d6a1 100644 --- a/examples/qos_sched/init.c +++ b/examples/qos_sched/init.c @@ -165,18 +165,6 @@ app_init_port(uint16_t portid, struct rte_mempool *mp) return 0; } -static struct rte_sched_subport_params subport_params[MAX_SCHED_SUBPORTS] = { - { - .tb_rate = 1250000000, - .tb_size = 1000000, - - .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000, - 1250000000, 1250000000, 1250000000, 1250000000, 1250000000, - 1250000000, 1250000000, 1250000000, 1250000000}, - .tc_period = 10, - }, -}; - static struct rte_sched_pipe_params pipe_profiles[MAX_SCHED_PIPE_PROFILES] = { { /* Profile #0 */ .tb_rate = 305175, @@ -193,19 +181,21 @@ static struct rte_sched_pipe_params pipe_profiles[MAX_SCHED_PIPE_PROFILES] = { }, }; -struct rte_sched_port_params port_params = { - .name = "port_scheduler_0", - .socket = 0, /* computed */ - .rate = 0, /* computed */ - .mtu = 6 + 6 + 4 + 4 + 2 + 1500, - .frame_overhead = RTE_SCHED_FRAME_OVERHEAD_DEFAULT, - .n_subports_per_port = 1, - .n_pipes_per_subport = 4096, - .qsize = {64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}, - .pipe_profiles = pipe_profiles, - .n_pipe_profiles = sizeof(pipe_profiles) / sizeof(struct rte_sched_pipe_params), - .n_max_pipe_profiles = MAX_SCHED_PIPE_PROFILES, +struct rte_sched_subport_params subport_params[MAX_SCHED_SUBPORTS] = { + { + .tb_rate = 1250000000, + .tb_size = 1000000, + .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000, + 1250000000, 1250000000, 1250000000, 1250000000, 1250000000, + 1250000000, 1250000000, 1250000000, 1250000000}, + .tc_period = 10, + .n_pipes_per_subport_enabled = 4096, + .qsize = {64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}, + .pipe_profiles = pipe_profiles, + .n_pipe_profiles = sizeof(pipe_profiles) / + sizeof(struct rte_sched_pipe_params), + .n_max_pipe_profiles = MAX_SCHED_PIPE_PROFILES, #ifdef RTE_SCHED_RED .red_params = { /* Traffic Class 0 Colors Green / Yellow / Red */ @@ -274,6 +264,17 @@ struct rte_sched_port_params port_params = { [12][2] = {.min_th = 32, .max_th = 64, .maxp_inv = 10, .wq_log2 = 9}, }, #endif /* RTE_SCHED_RED */ + }, +}; + +struct rte_sched_port_params port_params = { + .name = "port_scheduler_0", + .socket = 0, /* computed */ + .rate = 0, /* computed */ + .mtu = 6 + 6 + 4 + 4 + 2 + 1500, + .frame_overhead = RTE_SCHED_FRAME_OVERHEAD_DEFAULT, + .n_subports_per_port = 1, + .n_pipes_per_subport = MAX_SCHED_PIPES, }; static struct rte_sched_port * @@ -304,7 +305,10 @@ app_init_sched_port(uint32_t portid, uint32_t socketid) subport, err); } - for (pipe = 0; pipe < port_params.n_pipes_per_subport; pipe++) { + uint32_t n_pipes_per_subport = + subport_params[subport].n_pipes_per_subport_enabled; + + for (pipe = 0; pipe < n_pipes_per_subport; pipe++) { if (app_pipe_to_profile[subport][pipe] != -1) { err = rte_sched_pipe_config(port, subport, pipe, app_pipe_to_profile[subport][pipe]); diff --git a/examples/qos_sched/main.h b/examples/qos_sched/main.h index d8f890b64..baa2b3ead 100644 --- a/examples/qos_sched/main.h +++ b/examples/qos_sched/main.h @@ -152,6 +152,7 @@ uint32_t active_queues[RTE_SCHED_QUEUES_PER_PIPE]; uint32_t n_active_queues; extern struct rte_sched_port_params port_params; +extern struct rte_sched_subport_params subport_params[MAX_SCHED_SUBPORTS]; int app_parse_args(int argc, char **argv); int app_init(void); diff --git a/examples/qos_sched/profile.cfg b/examples/qos_sched/profile.cfg index 335561370..61b8b7071 100644 --- a/examples/qos_sched/profile.cfg +++ b/examples/qos_sched/profile.cfg @@ -20,11 +20,12 @@ [port] frame overhead = 24 number of subports per port = 1 -number of pipes per subport = 4096 -queue sizes = 64 64 64 64 64 64 64 64 64 64 64 64 64 ; Subport configuration [subport 0] +number of pipes per subport = 4096 +queue sizes = 64 64 64 64 64 64 64 64 64 64 64 64 64 + tb rate = 1250000000 ; Bytes per second tb size = 1000000 ; Bytes diff --git a/examples/qos_sched/profile_ov.cfg b/examples/qos_sched/profile_ov.cfg index 394987399..ab509d28d 100644 --- a/examples/qos_sched/profile_ov.cfg +++ b/examples/qos_sched/profile_ov.cfg @@ -5,11 +5,12 @@ [port] frame overhead = 24 number of subports per port = 1 -number of pipes per subport = 32 -queue sizes = 64 64 64 64 64 64 64 64 64 64 64 64 64 ; Subport configuration [subport 0] +number of pipes per subport = 32 +queue sizes = 64 64 64 64 64 64 64 64 64 64 64 64 64 + tb rate = 8400000 ; Bytes per second tb size = 100000 ; Bytes diff --git a/examples/qos_sched/stats.c b/examples/qos_sched/stats.c index e62e4a2f6..ce34b6c7c 100644 --- a/examples/qos_sched/stats.c +++ b/examples/qos_sched/stats.c @@ -24,7 +24,7 @@ qavg_q(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id, uint8_t tc, if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || - pipe_id >= port_params.n_pipes_per_subport || + pipe_id >= subport_params[subport_id].n_pipes_per_subport_enabled || tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE || q >= RTE_SCHED_BE_QUEUES_PER_PIPE || (tc < RTE_SCHED_TRAFFIC_CLASS_BE && q > 0)) @@ -32,7 +32,7 @@ qavg_q(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id, uint8_t tc, port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - queue_id += port_params.n_pipes_per_subport * + queue_id += subport_params[i].n_pipes_per_subport_enabled * RTE_SCHED_QUEUES_PER_PIPE; if (tc < RTE_SCHED_TRAFFIC_CLASS_BE) queue_id += pipe_id * RTE_SCHED_QUEUES_PER_PIPE + tc; @@ -69,14 +69,16 @@ qavg_tcpipe(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id, } if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || - pipe_id >= port_params.n_pipes_per_subport || + pipe_id >= subport_params[subport_id].n_pipes_per_subport_enabled || tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE) return -1; port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - queue_id += port_params.n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; + queue_id += + subport_params[i].n_pipes_per_subport_enabled * + RTE_SCHED_QUEUES_PER_PIPE; queue_id += pipe_id * RTE_SCHED_QUEUES_PER_PIPE + tc; @@ -123,13 +125,13 @@ qavg_pipe(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id) if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || - pipe_id >= port_params.n_pipes_per_subport) + pipe_id >= subport_params[subport_id].n_pipes_per_subport_enabled) return -1; port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - queue_id += port_params.n_pipes_per_subport * + queue_id += subport_params[i].n_pipes_per_subport_enabled * RTE_SCHED_QUEUES_PER_PIPE; queue_id += pipe_id * RTE_SCHED_QUEUES_PER_PIPE; @@ -177,13 +179,17 @@ qavg_tcsubport(uint16_t port_id, uint32_t subport_id, uint8_t tc) for (i = 0; i < subport_id; i++) subport_queue_id += - port_params.n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; + subport_params[i].n_pipes_per_subport_enabled * + RTE_SCHED_QUEUES_PER_PIPE; average = 0; for (count = 0; count < qavg_ntimes; count++) { + uint32_t n_pipes_per_subport = + subport_params[subport_id].n_pipes_per_subport_enabled; + part_average = 0; - for (i = 0; i < port_params.n_pipes_per_subport; i++) { + for (i = 0; i < n_pipes_per_subport; i++) { if (tc < RTE_SCHED_TRAFFIC_CLASS_BE) { queue_id = subport_queue_id + i * RTE_SCHED_QUEUES_PER_PIPE + tc; @@ -203,10 +209,11 @@ qavg_tcsubport(uint16_t port_id, uint32_t subport_id, uint8_t tc) } if (tc < RTE_SCHED_TRAFFIC_CLASS_BE) - average += part_average / (port_params.n_pipes_per_subport); + average += part_average / + (subport_params[subport_id].n_pipes_per_subport_enabled); else - average += - part_average / (port_params.n_pipes_per_subport) * + average += part_average / + (subport_params[subport_id].n_pipes_per_subport_enabled) * RTE_SCHED_BE_QUEUES_PER_PIPE; usleep(qavg_period); @@ -240,14 +247,17 @@ qavg_subport(uint16_t port_id, uint32_t subport_id) port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - subport_queue_id += port_params.n_pipes_per_subport * + subport_queue_id += subport_params[i].n_pipes_per_subport_enabled * RTE_SCHED_QUEUES_PER_PIPE; average = 0; for (count = 0; count < qavg_ntimes; count++) { + uint32_t n_pipes_per_subport = + subport_params[subport_id].n_pipes_per_subport_enabled; + part_average = 0; - for (i = 0; i < port_params.n_pipes_per_subport; i++) { + for (i = 0; i < n_pipes_per_subport; i++) { queue_id = subport_queue_id + i * RTE_SCHED_QUEUES_PER_PIPE; for (j = 0; j < RTE_SCHED_QUEUES_PER_PIPE; j++) { @@ -258,7 +268,8 @@ qavg_subport(uint16_t port_id, uint32_t subport_id) } average += part_average / - (port_params.n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE); + (subport_params[subport_id].n_pipes_per_subport_enabled * + RTE_SCHED_QUEUES_PER_PIPE); usleep(qavg_period); } @@ -322,12 +333,13 @@ pipe_stat(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id) if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || - pipe_id >= port_params.n_pipes_per_subport) + pipe_id >= subport_params[subport_id].n_pipes_per_subport_enabled) return -1; port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - queue_id += port_params.n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; + queue_id += subport_params[i].n_pipes_per_subport_enabled * + RTE_SCHED_QUEUES_PER_PIPE; queue_id += pipe_id * RTE_SCHED_QUEUES_PER_PIPE; -- 2.21.0
Remove redundant data structure fields from port level data structures and update release notes. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- doc/guides/rel_notes/release_19_11.rst | 6 +++- lib/librte_sched/rte_sched.c | 42 +------------------------- lib/librte_sched/rte_sched.h | 22 -------------- 3 files changed, 6 insertions(+), 64 deletions(-) diff --git a/doc/guides/rel_notes/release_19_11.rst b/doc/guides/rel_notes/release_19_11.rst index 27cfbd9e3..dd122f00a 100644 --- a/doc/guides/rel_notes/release_19_11.rst +++ b/doc/guides/rel_notes/release_19_11.rst @@ -94,6 +94,10 @@ API Changes Also, make sure to start the actual text at the margin. ========================================================= +* sched: The pipe nodes configuration parameters such as number of pipes, + pipe queue sizes, pipe profiles, etc., are moved from port level structure + to subport level. This allows different subports of the same port to + have different configuration for the pipe nodes. ABI Changes ----------- @@ -181,7 +185,7 @@ The libraries prepended with a plus sign were incremented in this version. librte_rcu.so.1 librte_reorder.so.1 librte_ring.so.2 - librte_sched.so.3 + + librte_sched.so.4 librte_security.so.2 librte_stack.so.1 librte_table.so.3 diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 1faa580d0..710ecf65a 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -216,13 +216,6 @@ struct rte_sched_port { uint32_t mtu; uint32_t frame_overhead; int socket; - uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - uint32_t n_pipe_profiles; - uint32_t n_max_pipe_profiles; - uint32_t pipe_tc_be_rate_max; -#ifdef RTE_SCHED_RED - struct rte_red_config red_config[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; -#endif /* Timing */ uint64_t time_cpu_cycles; /* Current CPU time measured in CPU cyles */ @@ -230,48 +223,15 @@ struct rte_sched_port { uint64_t time; /* Current NIC TX time measured in bytes */ struct rte_reciprocal inv_cycles_per_byte; /* CPU cycles per byte */ - /* Scheduling loop detection */ - uint32_t pipe_loop; - uint32_t pipe_exhaustion; - - /* Bitmap */ - struct rte_bitmap *bmp; - uint32_t grinder_base_bmp_pos[RTE_SCHED_PORT_N_GRINDERS] __rte_aligned_16; - /* Grinders */ - struct rte_sched_grinder grinder[RTE_SCHED_PORT_N_GRINDERS]; - uint32_t busy_grinders; struct rte_mbuf **pkts_out; uint32_t n_pkts_out; uint32_t subport_id; - /* Queue base calculation */ - uint32_t qsize_add[RTE_SCHED_QUEUES_PER_PIPE]; - uint32_t qsize_sum; - /* Large data structures */ - struct rte_sched_subport *subports[0]; - struct rte_sched_subport *subport; - struct rte_sched_pipe *pipe; - struct rte_sched_queue *queue; - struct rte_sched_queue_extra *queue_extra; - struct rte_sched_pipe_profile *pipe_profiles; - uint8_t *bmp_array; - struct rte_mbuf **queue_array; - uint8_t memory[0] __rte_cache_aligned; + struct rte_sched_subport *subports[0] __rte_cache_aligned; } __rte_cache_aligned; -enum rte_sched_port_array { - e_RTE_SCHED_PORT_ARRAY_SUBPORT = 0, - e_RTE_SCHED_PORT_ARRAY_PIPE, - e_RTE_SCHED_PORT_ARRAY_QUEUE, - e_RTE_SCHED_PORT_ARRAY_QUEUE_EXTRA, - e_RTE_SCHED_PORT_ARRAY_PIPE_PROFILES, - e_RTE_SCHED_PORT_ARRAY_BMP_ARRAY, - e_RTE_SCHED_PORT_ARRAY_QUEUE_ARRAY, - e_RTE_SCHED_PORT_ARRAY_TOTAL, -}; - enum rte_sched_subport_array { e_RTE_SCHED_SUBPORT_ARRAY_PIPE = 0, e_RTE_SCHED_SUBPORT_ARRAY_QUEUE, diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index 40f02f124..c82c23c14 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -260,28 +260,6 @@ struct rte_sched_port_params { * the subports of the same port. */ uint32_t n_pipes_per_subport; - - /** Packet queue size for each traffic class. - * All the pipes within the same subport share the similar - * configuration for the queues. - */ - uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - - /** Pipe profile table. - * Every pipe is configured using one of the profiles from this table. - */ - struct rte_sched_pipe_params *pipe_profiles; - - /** Profiles in the pipe profile table */ - uint32_t n_pipe_profiles; - - /** Max profiles allowed in the pipe profile table */ - uint32_t n_max_pipe_profiles; - -#ifdef RTE_SCHED_RED - /** RED parameters */ - struct rte_red_params red_params[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; -#endif }; /* -- 2.21.0
This patchset refactors the dpdk qos sched library to allow subport level configuration flexibility of the pipe nodes. Currently, all parameters for the pipe nodes (subscribers) configuration are part of the port level structure which forces all groups of subscribers (pipes) in different subports to have similar configurations in terms of their number, queue sizes, traffic-classes, etc. The new implementation moves pipe nodes configuration parameters from port level to subport level structure. This allows different subports of the same port to have different configuration for the pipe nodes, for examples- number of pipes, queue sizes, pipe profiles, etc. In order to keep the implementation complexity under control, all pipes within the same subport share the same configuration for queue sizes. v4: - remove deprecation note - rebase on current dpdk head - add 64-bit values support v3: - improve doxygen comments v2: - fix qsize parsing in sample application - fix checkpatch warnings Jasvinder Singh (17): sched: add pipe config params to subport struct sched: modify internal structs for config flexibility sched: remove pipe params config from port level sched: add pipe config to subport level sched: modify pipe functions for config flexibility sched: modify pkt enqueue for config flexibility sched: update memory compute to support flexiblity sched: update grinder functions for config flexibility sched: update pkt dequeue for flexible config sched: update queue stats read for config flexibility test/sched: modify tests for subport config flexibility net/softnic: add subport config flexibility to TM ip_pipeline: add subport config flexibility to TM examples/qos_sched: add subport configuration flexibility sched: remove redundant code sched: add support for 64 bit values sched: modify internal structs and functions for 64 bit values app/test/test_sched.c | 35 +- doc/guides/rel_notes/deprecation.rst | 6 - doc/guides/rel_notes/release_19_11.rst | 7 +- drivers/net/softnic/rte_eth_softnic_tm.c | 54 +- examples/ip_pipeline/cli.c | 89 +- examples/ip_pipeline/tmgr.c | 25 +- examples/ip_pipeline/tmgr.h | 9 +- examples/qos_sched/app_thread.c | 20 +- examples/qos_sched/cfg_file.c | 293 ++-- examples/qos_sched/init.c | 54 +- examples/qos_sched/main.h | 1 + examples/qos_sched/profile.cfg | 5 +- examples/qos_sched/profile_ov.cfg | 5 +- examples/qos_sched/stats.c | 50 +- lib/librte_sched/Makefile | 2 +- lib/librte_sched/meson.build | 2 +- lib/librte_sched/rte_approx.c | 57 +- lib/librte_sched/rte_approx.h | 3 +- lib/librte_sched/rte_sched.c | 1575 +++++++++++++--------- lib/librte_sched/rte_sched.h | 157 ++- lib/librte_sched/rte_sched_common.h | 12 +- lib/librte_sched/rte_sched_version.map | 2 +- 22 files changed, 1413 insertions(+), 1050 deletions(-) -- 2.21.0
Add pipe configuration parameters to subport level structure to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/Makefile | 2 +- lib/librte_sched/meson.build | 2 +- lib/librte_sched/rte_sched.h | 92 ++++++++++++++++++++++++------------ 3 files changed, 65 insertions(+), 31 deletions(-) diff --git a/lib/librte_sched/Makefile b/lib/librte_sched/Makefile index 3d7f410e1..6e4a72d89 100644 --- a/lib/librte_sched/Makefile +++ b/lib/librte_sched/Makefile @@ -18,7 +18,7 @@ LDLIBS += -lrte_timer EXPORT_MAP := rte_sched_version.map -LIBABIVER := 3 +LIBABIVER := 4 # # all source are stored in SRCS-y diff --git a/lib/librte_sched/meson.build b/lib/librte_sched/meson.build index 59d43c6d8..9f40a2368 100644 --- a/lib/librte_sched/meson.build +++ b/lib/librte_sched/meson.build @@ -1,7 +1,7 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2017 Intel Corporation -version = 3 +version = 4 sources = files('rte_sched.c', 'rte_red.c', 'rte_approx.c') headers = files('rte_sched.h', 'rte_sched_common.h', 'rte_red.h', 'rte_approx.h') diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index eac6db274..fbb0e23fa 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -111,7 +111,7 @@ extern "C" { #endif /* - * Subport configuration parameters. The period and credits_per_period + * Pipe configuration parameters. The period and credits_per_period * parameters are measured in bytes, with one byte meaning the time * duration associated with the transmission of one byte on the * physical medium of the output port, with pipe or pipe traffic class @@ -119,7 +119,7 @@ extern "C" { * credits_per_period divided by period. One credit represents one * byte. */ -struct rte_sched_subport_params { +struct rte_sched_pipe_params { /** Token bucket rate (measured in bytes per second) */ uint32_t tb_rate; @@ -129,32 +129,18 @@ struct rte_sched_subport_params { /** Traffic class rates (measured in bytes per second) */ uint32_t tc_rate[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - /** Enforcement period for rates (measured in milliseconds) */ + /** Enforcement period (measured in milliseconds) */ uint32_t tc_period; -}; - -/** Subport statistics */ -struct rte_sched_subport_stats { - /** Number of packets successfully written */ - uint32_t n_pkts_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - - /** Number of packets dropped */ - uint32_t n_pkts_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - /** Number of bytes successfully written for each traffic class */ - uint32_t n_bytes_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - - /** Number of bytes dropped for each traffic class */ - uint32_t n_bytes_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + /** Best-effort traffic class oversubscription weight */ + uint8_t tc_ov_weight; -#ifdef RTE_SCHED_RED - /** Number of packets dropped by red */ - uint32_t n_pkts_red_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; -#endif + /** WRR weights of best-effort traffic class queues */ + uint8_t wrr_weights[RTE_SCHED_BE_QUEUES_PER_PIPE]; }; /* - * Pipe configuration parameters. The period and credits_per_period + * Subport configuration parameters. The period and credits_per_period * parameters are measured in bytes, with one byte meaning the time * duration associated with the transmission of one byte on the * physical medium of the output port, with pipe or pipe traffic class @@ -162,7 +148,7 @@ struct rte_sched_subport_stats { * credits_per_period divided by period. One credit represents one * byte. */ -struct rte_sched_pipe_params { +struct rte_sched_subport_params { /** Token bucket rate (measured in bytes per second) */ uint32_t tb_rate; @@ -172,14 +158,58 @@ struct rte_sched_pipe_params { /** Traffic class rates (measured in bytes per second) */ uint32_t tc_rate[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - /** Enforcement period (measured in milliseconds) */ + /** Enforcement period for rates (measured in milliseconds) */ uint32_t tc_period; - /** Best-effort traffic class oversubscription weight */ - uint8_t tc_ov_weight; + /** Number of subport pipes. + * The subport can enable/allocate fewer pipes than the maximum + * number set through struct port_params::n_max_pipes_per_subport, + * as needed, to avoid memory allocation for the queues of the + * pipes that are not really needed. + */ + uint32_t n_pipes_per_subport_enabled; - /** WRR weights of best-effort traffic class queues */ - uint8_t wrr_weights[RTE_SCHED_BE_QUEUES_PER_PIPE]; + /** Packet queue size for each traffic class. + * All the pipes within the same subport share the similar + * configuration for the queues. + */ + uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + + /** Pipe profile table. + * Every pipe is configured using one of the profiles from this table. + */ + struct rte_sched_pipe_params *pipe_profiles; + + /** Profiles in the pipe profile table */ + uint32_t n_pipe_profiles; + + /** Max allowed profiles in the pipe profile table */ + uint32_t n_max_pipe_profiles; + +#ifdef RTE_SCHED_RED + /** RED parameters */ + struct rte_red_params red_params[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; +#endif +}; + +/** Subport statistics */ +struct rte_sched_subport_stats { + /** Number of packets successfully written */ + uint32_t n_pkts_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + + /** Number of packets dropped */ + uint32_t n_pkts_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + + /** Number of bytes successfully written for each traffic class */ + uint32_t n_bytes_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + + /** Number of bytes dropped for each traffic class */ + uint32_t n_bytes_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + +#ifdef RTE_SCHED_RED + /** Number of packets dropped by red */ + uint32_t n_pkts_red_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; +#endif }; /** Queue statistics */ @@ -224,7 +254,11 @@ struct rte_sched_port_params { /** Number of subports */ uint32_t n_subports_per_port; - /** Number of subport_pipes */ + /** 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 + * the subports of the same port. + */ uint32_t n_pipes_per_subport; /** Packet queue size for each traffic class. -- 2.21.0
Update internal structures related to port and subport to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 106 ++++++++++++++++++++++++++--------- 1 file changed, 78 insertions(+), 28 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index d8ab21d64..672412b77 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -47,33 +47,6 @@ */ #define RTE_SCHED_TIME_SHIFT 8 -struct rte_sched_subport { - /* Token bucket (TB) */ - uint64_t tb_time; /* time of last update */ - uint32_t tb_period; - uint32_t tb_credits_per_period; - uint32_t tb_size; - uint32_t tb_credits; - - /* Traffic classes (TCs) */ - uint64_t tc_time; /* time of next update */ - uint32_t tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - uint32_t tc_credits[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - uint32_t tc_period; - - /* TC oversubscription */ - uint32_t tc_ov_wm; - uint32_t tc_ov_wm_min; - uint32_t tc_ov_wm_max; - uint8_t tc_ov_period_id; - uint8_t tc_ov; - uint32_t tc_ov_n; - double tc_ov_rate; - - /* Statistics */ - struct rte_sched_subport_stats stats; -}; - struct rte_sched_pipe_profile { /* Token bucket (TB) */ uint32_t tb_period; @@ -107,7 +80,6 @@ struct rte_sched_pipe { /* TC oversubscription */ uint32_t tc_ov_credits; uint8_t tc_ov_period_id; - uint8_t reserved[3]; } __rte_cache_aligned; struct rte_sched_queue { @@ -166,6 +138,72 @@ struct rte_sched_grinder { uint8_t wrr_cost[RTE_SCHED_BE_QUEUES_PER_PIPE]; }; +struct rte_sched_subport { + /* Token bucket (TB) */ + uint64_t tb_time; /* time of last update */ + uint32_t tb_period; + uint32_t tb_credits_per_period; + uint32_t tb_size; + uint32_t tb_credits; + + /* Traffic classes (TCs) */ + uint64_t tc_time; /* time of next update */ + uint32_t tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + uint32_t tc_credits[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + uint32_t tc_period; + + /* TC oversubscription */ + uint32_t tc_ov_wm; + uint32_t tc_ov_wm_min; + uint32_t tc_ov_wm_max; + uint8_t tc_ov_period_id; + uint8_t tc_ov; + uint32_t tc_ov_n; + double tc_ov_rate; + + /* Statistics */ + struct rte_sched_subport_stats stats; + + /* Subport pipes */ + uint32_t n_pipes_per_subport_enabled; + uint32_t n_pipe_profiles; + uint32_t n_max_pipe_profiles; + + /* Pipe best-effort TC rate */ + uint32_t pipe_tc_be_rate_max; + + /* Pipe queues size */ + uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + +#ifdef RTE_SCHED_RED + struct rte_red_config red_config[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; +#endif + + /* Scheduling loop detection */ + uint32_t pipe_loop; + uint32_t pipe_exhaustion; + + /* Bitmap */ + struct rte_bitmap *bmp; + uint32_t grinder_base_bmp_pos[RTE_SCHED_PORT_N_GRINDERS] __rte_aligned_16; + + /* Grinders */ + struct rte_sched_grinder grinder[RTE_SCHED_PORT_N_GRINDERS]; + uint32_t busy_grinders; + + /* Queue base calculation */ + uint32_t qsize_add[RTE_SCHED_QUEUES_PER_PIPE]; + uint32_t qsize_sum; + + struct rte_sched_pipe *pipe; + struct rte_sched_queue *queue; + struct rte_sched_queue_extra *queue_extra; + struct rte_sched_pipe_profile *pipe_profiles; + uint8_t *bmp_array; + struct rte_mbuf **queue_array; + uint8_t memory[0] __rte_cache_aligned; +} __rte_cache_aligned; + struct rte_sched_port { /* User parameters */ uint32_t n_subports_per_port; @@ -177,6 +215,7 @@ struct rte_sched_port { uint32_t rate; uint32_t mtu; uint32_t frame_overhead; + int socket; uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; uint32_t n_pipe_profiles; uint32_t n_max_pipe_profiles; @@ -210,6 +249,7 @@ struct rte_sched_port { uint32_t qsize_sum; /* Large data structures */ + struct rte_sched_subport *subports[0]; struct rte_sched_subport *subport; struct rte_sched_pipe *pipe; struct rte_sched_queue *queue; @@ -231,6 +271,16 @@ enum rte_sched_port_array { e_RTE_SCHED_PORT_ARRAY_TOTAL, }; +enum rte_sched_subport_array { + e_RTE_SCHED_SUBPORT_ARRAY_PIPE = 0, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_EXTRA, + e_RTE_SCHED_SUBPORT_ARRAY_PIPE_PROFILES, + e_RTE_SCHED_SUBPORT_ARRAY_BMP_ARRAY, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_ARRAY, + e_RTE_SCHED_SUBPORT_ARRAY_TOTAL, +}; + #ifdef RTE_SCHED_COLLECT_STATS static inline uint32_t -- 2.21.0
Remove pipes configuration from the port level to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 254 ++++++++++------------------------- 1 file changed, 71 insertions(+), 183 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 672412b77..952e449f7 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -291,6 +291,31 @@ rte_sched_port_queues_per_subport(struct rte_sched_port *port) #endif +static inline uint32_t +rte_sched_subport_pipe_queues(struct rte_sched_subport *subport) +{ + return RTE_SCHED_QUEUES_PER_PIPE * subport->n_pipes_per_subport_enabled; +} + +static inline struct rte_mbuf ** +rte_sched_subport_pipe_qbase(struct rte_sched_subport *subport, uint32_t qindex) +{ + uint32_t pindex = qindex >> 4; + uint32_t qpos = qindex & (RTE_SCHED_QUEUES_PER_PIPE - 1); + + return (subport->queue_array + pindex * + subport->qsize_sum + subport->qsize_add[qpos]); +} + +static inline uint16_t +rte_sched_subport_pipe_qsize(struct rte_sched_port *port, +struct rte_sched_subport *subport, uint32_t qindex) +{ + uint32_t tc = port->pipe_tc[qindex & (RTE_SCHED_QUEUES_PER_PIPE - 1)]; + + return subport->qsize[tc]; +} + static inline uint32_t rte_sched_port_queues_per_port(struct rte_sched_port *port) { @@ -414,8 +439,6 @@ pipe_profile_check(struct rte_sched_pipe_params *params, 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__); @@ -456,45 +479,10 @@ rte_sched_port_check_params(struct rte_sched_port_params *params) if (params->n_pipes_per_subport == 0 || !rte_is_power_of_2(params->n_pipes_per_subport)) { RTE_LOG(ERR, SCHED, - "%s: Incorrect value for pipes number\n", __func__); - return -EINVAL; - } - - /* qsize: if non-zero, power of 2, - * no bigger than 32K (due to 16-bit read/write pointers) - */ - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - uint16_t qsize = params->qsize[i]; - - if ((qsize != 0 && !rte_is_power_of_2(qsize)) || - ((i == RTE_SCHED_TRAFFIC_CLASS_BE) && (qsize == 0))) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tc rate\n", __func__); - return -EINVAL; - } - } - - /* pipe_profiles and n_pipe_profiles */ - if (params->pipe_profiles == NULL || - params->n_pipe_profiles == 0 || - params->n_pipe_profiles > params->n_max_pipe_profiles) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for number of pipe profiles\n", __func__); + "%s: Incorrect value for maximum pipes number\n", __func__); return -EINVAL; } - for (i = 0; i < params->n_pipe_profiles; i++) { - struct rte_sched_pipe_params *p = params->pipe_profiles + i; - int status; - - status = pipe_profile_check(p, params->rate, ¶ms->qsize[0]); - if (status != 0) { - RTE_LOG(ERR, SCHED, - "%s: Pipe profile check failed(%d)\n", __func__, status); - return -EINVAL; - } - } - return 0; } @@ -582,32 +570,6 @@ rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params) return size0 + size1; } -static void -rte_sched_port_config_qsize(struct rte_sched_port *port) -{ - uint32_t i; - - port->qsize_add[0] = 0; - - /* Strict prority traffic class */ - for (i = 1; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - port->qsize_add[i] = port->qsize_add[i-1] + port->qsize[i-1]; - - /* Best-effort traffic class */ - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 1] = - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE] + - port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 2] = - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 1] + - port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 3] = - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 2] + - port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; - - port->qsize_sum = port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 3] + - port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; -} - static void rte_sched_port_log_pipe_profile(struct rte_sched_port *port, uint32_t i) { @@ -717,56 +679,41 @@ rte_sched_pipe_profile_convert(struct rte_sched_port *port, dst->wrr_cost[3] = (uint8_t) wrr_cost[3]; } -static void -rte_sched_port_config_pipe_profile_table(struct rte_sched_port *port, - struct rte_sched_port_params *params) -{ - uint32_t i; - - for (i = 0; i < port->n_pipe_profiles; i++) { - struct rte_sched_pipe_params *src = params->pipe_profiles + i; - struct rte_sched_pipe_profile *dst = port->pipe_profiles + i; - - rte_sched_pipe_profile_convert(port, src, dst, params->rate); - rte_sched_port_log_pipe_profile(port, i); - } - - port->pipe_tc_be_rate_max = 0; - for (i = 0; i < port->n_pipe_profiles; i++) { - struct rte_sched_pipe_params *src = params->pipe_profiles + i; - uint32_t pipe_tc_be_rate = src->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; - - if (port->pipe_tc_be_rate_max < pipe_tc_be_rate) - port->pipe_tc_be_rate_max = pipe_tc_be_rate; - } -} - struct rte_sched_port * rte_sched_port_config(struct rte_sched_port_params *params) { struct rte_sched_port *port = NULL; - uint32_t mem_size, bmp_mem_size, n_queues_per_port, i, j, cycles_per_byte; + uint32_t size0, size1; + uint32_t cycles_per_byte; + uint32_t i, j; + int status; - /* Check user parameters. Determine the amount of memory to allocate */ - mem_size = rte_sched_port_get_memory_footprint(params); - if (mem_size == 0) + status = rte_sched_port_check_params(params); + if (status != 0) { + RTE_LOG(ERR, SCHED, + "%s: Port scheduler params check failed (%d)\n", + __func__, status); return NULL; + } + + size0 = sizeof(struct rte_sched_port); + size1 = params->n_subports_per_port * sizeof(struct rte_sched_subport *); /* Allocate memory to store the data structures */ - port = rte_zmalloc_socket("qos_params", mem_size, RTE_CACHE_LINE_SIZE, + port = rte_zmalloc_socket("qos_params", size0 + size1, RTE_CACHE_LINE_SIZE, params->socket); - if (port == NULL) - return NULL; + if (port == NULL) { + RTE_LOG(ERR, SCHED, "%s: Memory allocation fails\n", __func__); - /* compile time checks */ - RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS == 0); - RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS & (RTE_SCHED_PORT_N_GRINDERS - 1)); + return NULL; + } /* User parameters */ port->n_subports_per_port = params->n_subports_per_port; port->n_pipes_per_subport = params->n_pipes_per_subport; port->n_pipes_per_subport_log2 = __builtin_ctz(params->n_pipes_per_subport); + port->socket = params->socket; for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) port->pipe_queue[i] = i; @@ -787,32 +734,6 @@ rte_sched_port_config(struct rte_sched_port_params *params) port->rate = params->rate; port->mtu = params->mtu + params->frame_overhead; port->frame_overhead = params->frame_overhead; - memcpy(port->qsize, params->qsize, sizeof(params->qsize)); - port->n_pipe_profiles = params->n_pipe_profiles; - port->n_max_pipe_profiles = params->n_max_pipe_profiles; - -#ifdef RTE_SCHED_RED - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - uint32_t j; - - for (j = 0; j < RTE_COLORS; j++) { - /* if min/max are both zero, then RED is disabled */ - if ((params->red_params[i][j].min_th | - params->red_params[i][j].max_th) == 0) { - continue; - } - - if (rte_red_config_init(&port->red_config[i][j], - params->red_params[i][j].wq_log2, - params->red_params[i][j].min_th, - params->red_params[i][j].max_th, - params->red_params[i][j].maxp_inv) != 0) { - rte_free(port); - return NULL; - } - } - } -#endif /* Timing */ port->time_cpu_cycles = rte_get_tsc_cycles(); @@ -823,79 +744,32 @@ rte_sched_port_config(struct rte_sched_port_params *params) / params->rate; port->inv_cycles_per_byte = rte_reciprocal_value(cycles_per_byte); - /* Scheduling loop detection */ - port->pipe_loop = RTE_SCHED_PIPE_INVALID; - port->pipe_exhaustion = 0; - /* Grinders */ - port->busy_grinders = 0; port->pkts_out = NULL; port->n_pkts_out = 0; - /* Queue base calculation */ - rte_sched_port_config_qsize(port); - - /* Large data structures */ - port->subport = (struct rte_sched_subport *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_SUBPORT)); - port->pipe = (struct rte_sched_pipe *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_PIPE)); - port->queue = (struct rte_sched_queue *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_QUEUE)); - port->queue_extra = (struct rte_sched_queue_extra *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_QUEUE_EXTRA)); - port->pipe_profiles = (struct rte_sched_pipe_profile *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_PIPE_PROFILES)); - port->bmp_array = port->memory - + rte_sched_port_get_array_base(params, e_RTE_SCHED_PORT_ARRAY_BMP_ARRAY); - port->queue_array = (struct rte_mbuf **) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_QUEUE_ARRAY)); - - /* Pipe profile table */ - rte_sched_port_config_pipe_profile_table(port, params); - - /* Bitmap */ - n_queues_per_port = rte_sched_port_queues_per_port(port); - bmp_mem_size = rte_bitmap_get_memory_footprint(n_queues_per_port); - port->bmp = rte_bitmap_init(n_queues_per_port, port->bmp_array, - bmp_mem_size); - if (port->bmp == NULL) { - RTE_LOG(ERR, SCHED, "Bitmap init error\n"); - rte_free(port); - return NULL; - } - - for (i = 0; i < RTE_SCHED_PORT_N_GRINDERS; i++) - port->grinder_base_bmp_pos[i] = RTE_SCHED_PIPE_INVALID; - - return port; } -void -rte_sched_port_free(struct rte_sched_port *port) +static inline void +rte_sched_subport_free(struct rte_sched_port *port, + struct rte_sched_subport *subport) { + uint32_t n_subport_pipe_queues; uint32_t qindex; - uint32_t n_queues_per_port; - /* Check user parameters */ - if (port == NULL) + if (subport == NULL) return; - n_queues_per_port = rte_sched_port_queues_per_port(port); + n_subport_pipe_queues = rte_sched_subport_pipe_queues(subport); /* Free enqueued mbufs */ - for (qindex = 0; qindex < n_queues_per_port; qindex++) { - struct rte_mbuf **mbufs = rte_sched_port_qbase(port, qindex); - uint16_t qsize = rte_sched_port_qsize(port, qindex); + for (qindex = 0; qindex < n_subport_pipe_queues; qindex++) { + struct rte_mbuf **mbufs = + rte_sched_subport_pipe_qbase(subport, qindex); + uint16_t qsize = rte_sched_subport_pipe_qsize(port, subport, qindex); if (qsize != 0) { - struct rte_sched_queue *queue = port->queue + qindex; + struct rte_sched_queue *queue = subport->queue + qindex; uint16_t qr = queue->qr & (qsize - 1); uint16_t qw = queue->qw & (qsize - 1); @@ -904,7 +778,21 @@ rte_sched_port_free(struct rte_sched_port *port) } } - rte_bitmap_free(port->bmp); + rte_bitmap_free(subport->bmp); +} + +void +rte_sched_port_free(struct rte_sched_port *port) +{ + uint32_t i; + + /* Check user parameters */ + if (port == NULL) + return; + + for (i = 0; i < port->n_subports_per_port; i++) + rte_sched_subport_free(port, port->subports[i]); + rte_free(port); } -- 2.21.0
Add pipes configuration from the port level to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 388 ++++++++++++++++++++++++++++++----- 1 file changed, 332 insertions(+), 56 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 952e449f7..60dfc6232 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -550,24 +550,91 @@ rte_sched_port_get_array_base(struct rte_sched_port_params *params, enum rte_sch return base; } -uint32_t -rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params) +static uint32_t +rte_sched_subport_get_array_base(struct rte_sched_subport_params *params, + enum rte_sched_subport_array array) { - uint32_t size0, size1; - int status; + uint32_t n_pipes_per_subport = params->n_pipes_per_subport_enabled; + uint32_t n_subport_pipe_queues = + RTE_SCHED_QUEUES_PER_PIPE * n_pipes_per_subport; - status = rte_sched_port_check_params(params); - if (status != 0) { - RTE_LOG(NOTICE, SCHED, - "Port scheduler params check failed (%d)\n", status); + uint32_t size_pipe = n_pipes_per_subport * sizeof(struct rte_sched_pipe); + uint32_t size_queue = + n_subport_pipe_queues * sizeof(struct rte_sched_queue); + uint32_t size_queue_extra + = n_subport_pipe_queues * sizeof(struct rte_sched_queue_extra); + uint32_t size_pipe_profiles = params->n_max_pipe_profiles * + sizeof(struct rte_sched_pipe_profile); + uint32_t size_bmp_array = + rte_bitmap_get_memory_footprint(n_subport_pipe_queues); + uint32_t size_per_pipe_queue_array, size_queue_array; - return 0; + uint32_t base, i; + + size_per_pipe_queue_array = 0; + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + if (i < RTE_SCHED_TRAFFIC_CLASS_BE) + size_per_pipe_queue_array += + params->qsize[i] * sizeof(struct rte_mbuf *); + else + size_per_pipe_queue_array += RTE_SCHED_MAX_QUEUES_PER_TC * + params->qsize[i] * sizeof(struct rte_mbuf *); } + size_queue_array = n_pipes_per_subport * size_per_pipe_queue_array; - size0 = sizeof(struct rte_sched_port); - size1 = rte_sched_port_get_array_base(params, e_RTE_SCHED_PORT_ARRAY_TOTAL); + base = 0; - return size0 + size1; + if (array == e_RTE_SCHED_SUBPORT_ARRAY_PIPE) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_pipe); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_QUEUE) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_queue); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_EXTRA) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_queue_extra); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_PIPE_PROFILES) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_pipe_profiles); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_BMP_ARRAY) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_bmp_array); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_ARRAY) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_queue_array); + + return base; +} + +static void +rte_sched_subport_config_qsize(struct rte_sched_subport *subport) +{ + uint32_t i; + + subport->qsize_add[0] = 0; + + /* Strict prority traffic class */ + for (i = 1; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) + subport->qsize_add[i] = subport->qsize_add[i-1] + subport->qsize[i-1]; + + /* Best-effort traffic class */ + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 1] = + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE] + + subport->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 2] = + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 1] + + subport->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 3] = + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 2] + + subport->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; + + subport->qsize_sum = subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 3] + + subport->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; } static void @@ -679,6 +746,126 @@ rte_sched_pipe_profile_convert(struct rte_sched_port *port, dst->wrr_cost[3] = (uint8_t) wrr_cost[3]; } +static int +rte_sched_subport_check_params(struct rte_sched_subport_params *params, + uint32_t n_max_pipes_per_subport, + uint32_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; + } + + /* qsize: if non-zero, power of 2, + * no bigger than 32K (due to 16-bit read/write pointers) + */ + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + uint16_t qsize = params->qsize[i]; + + if (qsize != 0 && !rte_is_power_of_2(qsize)) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for qsize\n", __func__); + return -EINVAL; + } + } + + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + uint32_t tc_rate = params->tc_rate[i]; + uint16_t qsize = params->qsize[i]; + + if ((qsize == 0 && tc_rate != 0) || + (qsize != 0 && tc_rate == 0) || + (tc_rate > params->tb_rate)) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for tc rate\n", __func__); + return -EINVAL; + } + } + + if (params->qsize[RTE_SCHED_TRAFFIC_CLASS_BE] == 0 || + params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE] == 0) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect qsize or 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; + } + + /* n_pipes_per_subport: non-zero, power of 2 */ + if (params->n_pipes_per_subport_enabled == 0 || + params->n_pipes_per_subport_enabled > n_max_pipes_per_subport || + !rte_is_power_of_2(params->n_pipes_per_subport_enabled)) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for pipes number\n", __func__); + return -EINVAL; + } + + /* pipe_profiles and n_pipe_profiles */ + if (params->pipe_profiles == NULL || + params->n_pipe_profiles == 0 || + params->n_max_pipe_profiles == 0 || + params->n_pipe_profiles > params->n_max_pipe_profiles) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for pipe profiles\n", __func__); + return -EINVAL; + } + + for (i = 0; i < params->n_pipe_profiles; i++) { + struct rte_sched_pipe_params *p = params->pipe_profiles + i; + int status; + + status = pipe_profile_check(p, rate, ¶ms->qsize[0]); + if (status != 0) { + RTE_LOG(ERR, SCHED, + "%s: Pipe profile check failed(%d)\n", __func__, status); + return -EINVAL; + } + } + + return 0; +} + +uint32_t +rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params) +{ + uint32_t size0, size1; + int status; + + status = rte_sched_port_check_params(params); + if (status != 0) { + RTE_LOG(NOTICE, SCHED, + "Port scheduler params check failed (%d)\n", status); + + return 0; + } + + size0 = sizeof(struct rte_sched_port); + size1 = rte_sched_port_get_array_base(params, + e_RTE_SCHED_PORT_ARRAY_TOTAL); + + return size0 + size1; +} + struct rte_sched_port * rte_sched_port_config(struct rte_sched_port_params *params) { @@ -799,7 +986,7 @@ rte_sched_port_free(struct rte_sched_port *port) static void rte_sched_port_log_subport_config(struct rte_sched_port *port, uint32_t i) { - struct rte_sched_subport *s = port->subport + i; + struct rte_sched_subport *s = port->subports[i]; RTE_LOG(DEBUG, SCHED, "Low level config for subport %u:\n" " Token bucket: period = %u, credits per period = %u, size = %u\n" @@ -834,72 +1021,78 @@ rte_sched_port_log_subport_config(struct rte_sched_port *port, uint32_t i) s->tc_ov_wm_max); } +static void +rte_sched_free_memory(struct rte_sched_port *port, uint32_t n_subports) +{ + uint32_t i; + + for (i = 0; i < n_subports; i++) { + struct rte_sched_subport *subport = port->subports[i]; + + rte_sched_subport_free(port, subport); + } + + rte_free(port); +} + int rte_sched_subport_config(struct rte_sched_port *port, uint32_t subport_id, struct rte_sched_subport_params *params) { - struct rte_sched_subport *s; - uint32_t i; + struct rte_sched_subport *s = NULL; + uint32_t n_subports = subport_id; + uint32_t n_subport_pipe_queues, i; + uint32_t size0, size1, bmp_mem_size; + int status; /* Check user parameters */ if (port == NULL) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for parameter port\n", __func__); - return -EINVAL; + return 0; } if (subport_id >= port->n_subports_per_port) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for subport id\n", __func__); - return -EINVAL; - } - if (params == NULL) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for parameter params\n", __func__); + rte_sched_free_memory(port, n_subports); return -EINVAL; } - if (params->tb_rate == 0 || params->tb_rate > port->rate) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tb rate\n", __func__); - return -EINVAL; - } + status = rte_sched_subport_check_params(params, + port->n_pipes_per_subport, + port->rate); + if (status != 0) { + RTE_LOG(NOTICE, SCHED, + "%s: Port scheduler params check failed (%d)\n", + __func__, status); - if (params->tb_size == 0) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tb size\n", __func__); + rte_sched_free_memory(port, n_subports); return -EINVAL; } - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - uint32_t tc_rate = params->tc_rate[i]; - uint16_t qsize = port->qsize[i]; + /* Determine the amount of memory to allocate */ + size0 = sizeof(struct rte_sched_subport); + size1 = rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_TOTAL); - if ((qsize == 0 && tc_rate != 0) || - (qsize != 0 && tc_rate == 0) || - (tc_rate > params->tb_rate)) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tc rate\n", __func__); - return -EINVAL; - } - } - - if (port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE] == 0 || - params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE] == 0) { + /* Allocate memory to store the data structures */ + s = rte_zmalloc_socket("subport_params", size0 + size1, + RTE_CACHE_LINE_SIZE, port->socket); + if (s == NULL) { RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tc rate(best effort)\n", __func__); - return -EINVAL; - } + "%s: Memory allocation fails\n", __func__); - if (params->tc_period == 0) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tc period\n", __func__); - return -EINVAL; + rte_sched_free_memory(port, n_subports); + return -ENOMEM; } - s = port->subport + subport_id; + n_subports++; + + /* Port */ + port->subports[subport_id] = s; /* Token Bucket (TB) */ if (params->tb_rate == port->rate) { @@ -919,26 +1112,109 @@ rte_sched_subport_config(struct rte_sched_port *port, /* Traffic Classes (TCs) */ s->tc_period = rte_sched_time_ms_to_bytes(params->tc_period, port->rate); for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - if (port->qsize[i]) + if (params->qsize[i]) s->tc_credits_per_period[i] = rte_sched_time_ms_to_bytes(params->tc_period, - params->tc_rate[i]); - + params->tc_rate[i]); } s->tc_time = port->time + s->tc_period; for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - if (port->qsize[i]) + if (params->qsize[i]) s->tc_credits[i] = s->tc_credits_per_period[i]; + /* compile time checks */ + RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS == 0); + RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS & + (RTE_SCHED_PORT_N_GRINDERS - 1)); + + /* User parameters */ + s->n_pipes_per_subport_enabled = params->n_pipes_per_subport_enabled; + memcpy(s->qsize, params->qsize, sizeof(params->qsize)); + s->n_pipe_profiles = params->n_pipe_profiles; + s->n_max_pipe_profiles = params->n_max_pipe_profiles; + +#ifdef RTE_SCHED_RED + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + uint32_t j; + + for (j = 0; j < RTE_COLORS; j++) { + /* if min/max are both zero, then RED is disabled */ + if ((params->red_params[i][j].min_th | + params->red_params[i][j].max_th) == 0) { + continue; + } + + if (rte_red_config_init(&s->red_config[i][j], + params->red_params[i][j].wq_log2, + params->red_params[i][j].min_th, + params->red_params[i][j].max_th, + params->red_params[i][j].maxp_inv) != 0) { + rte_sched_free_memory(port, n_subports); + + RTE_LOG(NOTICE, SCHED, + "%s: RED configuration init fails\n", __func__); + return -EINVAL; + } + } + } +#endif + + /* Scheduling loop detection */ + s->pipe_loop = RTE_SCHED_PIPE_INVALID; + s->pipe_exhaustion = 0; + + /* Grinders */ + s->busy_grinders = 0; + + /* Queue base calculation */ + rte_sched_subport_config_qsize(s); + + /* Large data structures */ + s->pipe = (struct rte_sched_pipe *) + (s->memory + rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_PIPE)); + s->queue = (struct rte_sched_queue *) + (s->memory + rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE)); + s->queue_extra = (struct rte_sched_queue_extra *) + (s->memory + rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_EXTRA)); + s->pipe_profiles = (struct rte_sched_pipe_profile *) + (s->memory + rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_PIPE_PROFILES)); + s->bmp_array = s->memory + rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_BMP_ARRAY); + s->queue_array = (struct rte_mbuf **) + (s->memory + rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_ARRAY)); + + /* Bitmap */ + n_subport_pipe_queues = rte_sched_subport_pipe_queues(s); + bmp_mem_size = rte_bitmap_get_memory_footprint(n_subport_pipe_queues); + s->bmp = rte_bitmap_init(n_subport_pipe_queues, s->bmp_array, + bmp_mem_size); + if (s->bmp == NULL) { + RTE_LOG(ERR, SCHED, + "%s: Subport bitmap init error\n", __func__); + + rte_sched_free_memory(port, n_subports); + return -EINVAL; + } + + for (i = 0; i < RTE_SCHED_PORT_N_GRINDERS; i++) + s->grinder_base_bmp_pos[i] = RTE_SCHED_PIPE_INVALID; + +#ifdef RTE_SCHED_SUBPORT_TC_OV /* TC oversubscription */ s->tc_ov_wm_min = port->mtu; s->tc_ov_wm_max = rte_sched_time_ms_to_bytes(params->tc_period, - port->pipe_tc_be_rate_max); + s->pipe_tc_be_rate_max); s->tc_ov_wm = s->tc_ov_wm_max; s->tc_ov_period_id = 0; s->tc_ov = 0; s->tc_ov_n = 0; s->tc_ov_rate = 0; +#endif rte_sched_port_log_subport_config(port, subport_id); -- 2.21.0
Modify pipe level functions to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 103 +++++++++++++++++-------- lib/librte_sched/rte_sched.h | 7 +- lib/librte_sched/rte_sched_version.map | 2 +- 3 files changed, 76 insertions(+), 36 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 60dfc6232..6b6219e45 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -638,9 +638,9 @@ rte_sched_subport_config_qsize(struct rte_sched_subport *subport) } static void -rte_sched_port_log_pipe_profile(struct rte_sched_port *port, uint32_t i) +rte_sched_port_log_pipe_profile(struct rte_sched_subport *subport, uint32_t i) { - struct rte_sched_pipe_profile *p = port->pipe_profiles + i; + struct rte_sched_pipe_profile *p = subport->pipe_profiles + i; RTE_LOG(DEBUG, SCHED, "Low level config for pipe profile %u:\n" " Token bucket: period = %u, credits per period = %u, size = %u\n" @@ -689,7 +689,7 @@ rte_sched_time_ms_to_bytes(uint32_t time_ms, uint32_t rate) } static void -rte_sched_pipe_profile_convert(struct rte_sched_port *port, +rte_sched_pipe_profile_convert(struct rte_sched_subport *subport, struct rte_sched_pipe_params *src, struct rte_sched_pipe_profile *dst, uint32_t rate) @@ -718,7 +718,7 @@ rte_sched_pipe_profile_convert(struct rte_sched_port *port, rate); for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - if (port->qsize[i]) + if (subport->qsize[i]) dst->tc_credits_per_period[i] = rte_sched_time_ms_to_bytes(src->tc_period, src->tc_rate[i]); @@ -746,6 +746,30 @@ rte_sched_pipe_profile_convert(struct rte_sched_port *port, dst->wrr_cost[3] = (uint8_t) wrr_cost[3]; } +static void +rte_sched_subport_config_pipe_profile_table(struct rte_sched_subport *subport, + struct rte_sched_subport_params *params, uint32_t rate) +{ + uint32_t i; + + for (i = 0; i < subport->n_pipe_profiles; i++) { + struct rte_sched_pipe_params *src = params->pipe_profiles + i; + struct rte_sched_pipe_profile *dst = subport->pipe_profiles + i; + + rte_sched_pipe_profile_convert(subport, src, dst, rate); + rte_sched_port_log_pipe_profile(subport, i); + } + + subport->pipe_tc_be_rate_max = 0; + for (i = 0; i < subport->n_pipe_profiles; i++) { + struct rte_sched_pipe_params *src = params->pipe_profiles + i; + uint32_t pipe_tc_be_rate = src->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; + + if (subport->pipe_tc_be_rate_max < pipe_tc_be_rate) + subport->pipe_tc_be_rate_max = pipe_tc_be_rate; + } +} + static int rte_sched_subport_check_params(struct rte_sched_subport_params *params, uint32_t n_max_pipes_per_subport, @@ -1188,6 +1212,9 @@ rte_sched_subport_config(struct rte_sched_port *port, (s->memory + rte_sched_subport_get_array_base(params, e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_ARRAY)); + /* Pipe profile table */ + rte_sched_subport_config_pipe_profile_table(s, params, port->rate); + /* Bitmap */ n_subport_pipe_queues = rte_sched_subport_pipe_queues(s); bmp_mem_size = rte_bitmap_get_memory_footprint(n_subport_pipe_queues); @@ -1230,6 +1257,7 @@ rte_sched_pipe_config(struct rte_sched_port *port, struct rte_sched_subport *s; struct rte_sched_pipe *p; struct rte_sched_pipe_profile *params; + uint32_t n_subports = subport_id + 1; uint32_t deactivate, profile, i; /* Check user parameters */ @@ -1245,34 +1273,32 @@ rte_sched_pipe_config(struct rte_sched_port *port, if (subport_id >= port->n_subports_per_port) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for parameter subport id\n", __func__); + + rte_sched_free_memory(port, n_subports); return -EINVAL; } - if (pipe_id >= port->n_pipes_per_subport) { + s = port->subports[subport_id]; + if (pipe_id >= s->n_pipes_per_subport_enabled) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for parameter pipe id\n", __func__); + + rte_sched_free_memory(port, n_subports); return -EINVAL; } - if (!deactivate && profile >= port->n_pipe_profiles) { + if (!deactivate && profile >= s->n_pipe_profiles) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for parameter pipe profile\n", __func__); - return -EINVAL; - } - /* Check that subport configuration is valid */ - s = port->subport + subport_id; - if (s->tb_period == 0) { - RTE_LOG(ERR, SCHED, - "%s: Subport configuration invalid\n", __func__); + rte_sched_free_memory(port, n_subports); return -EINVAL; } - p = port->pipe + (subport_id * port->n_pipes_per_subport + pipe_id); - /* Handle the case when pipe already has a valid configuration */ + p = s->pipe + pipe_id; if (p->tb_time) { - params = port->pipe_profiles + p->profile; + params = s->pipe_profiles + p->profile; double subport_tc_be_rate = (double) s->tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASS_BE] @@ -1302,7 +1328,7 @@ rte_sched_pipe_config(struct rte_sched_port *port, /* Apply the new pipe configuration */ p->profile = profile; - params = port->pipe_profiles + p->profile; + params = s->pipe_profiles + p->profile; /* Token Bucket (TB) */ p->tb_time = port->time; @@ -1312,7 +1338,7 @@ rte_sched_pipe_config(struct rte_sched_port *port, p->tc_time = port->time + params->tc_period; for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - if (port->qsize[i]) + if (s->qsize[i]) p->tc_credits[i] = params->tc_credits_per_period[i]; { @@ -1342,10 +1368,12 @@ rte_sched_pipe_config(struct rte_sched_port *port, } int -rte_sched_port_pipe_profile_add(struct rte_sched_port *port, +rte_sched_subport_pipe_profile_add(struct rte_sched_port *port, + uint32_t subport_id, struct rte_sched_pipe_params *params, uint32_t *pipe_profile_id) { + struct rte_sched_subport *s; struct rte_sched_pipe_profile *pp; uint32_t i; int status; @@ -1357,40 +1385,49 @@ rte_sched_port_pipe_profile_add(struct rte_sched_port *port, return -EINVAL; } - /* Pipe profiles not exceeds the max limit */ - if (port->n_pipe_profiles >= port->n_max_pipe_profiles) { + /* Subport id not exceeds the max limit */ + if (subport_id > port->n_subports_per_port) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for subport id\n", __func__); + return -EINVAL; + } + + s = port->subports[subport_id]; + + /* Pipe profiles exceeds the max limit */ + if (s->n_pipe_profiles >= s->n_max_pipe_profiles) { RTE_LOG(ERR, SCHED, "%s: Number of pipe profiles exceeds the max limit\n", __func__); return -EINVAL; } /* Pipe params */ - status = pipe_profile_check(params, port->rate, &port->qsize[0]); + status = pipe_profile_check(params, port->rate, &s->qsize[0]); if (status != 0) { RTE_LOG(ERR, SCHED, "%s: Pipe profile check failed(%d)\n", __func__, status); return -EINVAL; } - pp = &port->pipe_profiles[port->n_pipe_profiles]; - rte_sched_pipe_profile_convert(port, params, pp, port->rate); + pp = &s->pipe_profiles[s->n_pipe_profiles]; + rte_sched_pipe_profile_convert(s, params, pp, port->rate); - /* Pipe profile not exists */ - for (i = 0; i < port->n_pipe_profiles; i++) - if (memcmp(port->pipe_profiles + i, pp, sizeof(*pp)) == 0) { + /* Pipe profile should not exists */ + for (i = 0; i < s->n_pipe_profiles; i++) + if (memcmp(s->pipe_profiles + i, pp, sizeof(*pp)) == 0) { RTE_LOG(ERR, SCHED, - "%s: Pipe profile doesn't exist\n", __func__); + "%s: Pipe profile exists\n", __func__); return -EINVAL; } /* Pipe profile commit */ - *pipe_profile_id = port->n_pipe_profiles; - port->n_pipe_profiles++; + *pipe_profile_id = s->n_pipe_profiles; + s->n_pipe_profiles++; - if (port->pipe_tc_be_rate_max < params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]) - port->pipe_tc_be_rate_max = params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; + if (s->pipe_tc_be_rate_max < params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]) + s->pipe_tc_be_rate_max = params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; - rte_sched_port_log_pipe_profile(port, *pipe_profile_id); + rte_sched_port_log_pipe_profile(s, *pipe_profile_id); return 0; } diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index fbb0e23fa..5001f09ed 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -317,6 +317,8 @@ rte_sched_port_free(struct rte_sched_port *port); * * @param port * Handle to port scheduler instance + * @param subport_id + * Subport ID * @param params * Pipe profile parameters * @param pipe_profile_id @@ -326,7 +328,8 @@ rte_sched_port_free(struct rte_sched_port *port); */ __rte_experimental int -rte_sched_port_pipe_profile_add(struct rte_sched_port *port, +rte_sched_subport_pipe_profile_add(struct rte_sched_port *port, + uint32_t subport_id, struct rte_sched_pipe_params *params, uint32_t *pipe_profile_id); @@ -357,7 +360,7 @@ rte_sched_subport_config(struct rte_sched_port *port, * @param pipe_id * Pipe ID within subport * @param pipe_profile - * ID of port-level pre-configured pipe profile + * ID of subport-level pre-configured pipe profile * @return * 0 upon success, error code otherwise */ diff --git a/lib/librte_sched/rte_sched_version.map b/lib/librte_sched/rte_sched_version.map index 729588794..f33761e63 100644 --- a/lib/librte_sched/rte_sched_version.map +++ b/lib/librte_sched/rte_sched_version.map @@ -33,5 +33,5 @@ DPDK_2.1 { EXPERIMENTAL { global: - rte_sched_port_pipe_profile_add; + rte_sched_subport_pipe_profile_add; }; -- 2.21.0
Modify scheduler packet enqueue operation of the scheduler to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 277 ++++++++++++++++++++++------------- 1 file changed, 178 insertions(+), 99 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 6b6219e45..a8174afad 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -1440,10 +1440,11 @@ rte_sched_port_qindex(struct rte_sched_port *port, 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) | - ((rte_sched_port_pipe_queue(port, traffic_class) + queue) & - (RTE_SCHED_QUEUES_PER_PIPE - 1)); + (port->n_pipes_per_subport_log2 + 4)) | + ((pipe & + (port->subports[subport]->n_pipes_per_subport_enabled - 1)) << 4) | + ((rte_sched_port_pipe_queue(port, traffic_class) + queue) & + (RTE_SCHED_QUEUES_PER_PIPE - 1)); } void @@ -1468,7 +1469,8 @@ rte_sched_port_pkt_read_tree_path(struct rte_sched_port *port, uint32_t queue_id = rte_mbuf_sched_queue_get(pkt); *subport = queue_id >> (port->n_pipes_per_subport_log2 + 4); - *pipe = (queue_id >> 4) & (port->n_pipes_per_subport - 1); + *pipe = (queue_id >> 4) & + (port->subports[*subport]->n_pipes_per_subport_enabled - 1); *traffic_class = rte_sched_port_pipe_tc(port, queue_id); *queue = rte_sched_port_tc_queue(port, queue_id); } @@ -1512,7 +1514,7 @@ rte_sched_subport_read_stats(struct rte_sched_port *port, return -EINVAL; } - s = port->subport + subport_id; + s = port->subports[subport_id]; /* Copy subport stats and clear */ memcpy(stats, &s->stats, sizeof(struct rte_sched_subport_stats)); @@ -1585,43 +1587,50 @@ rte_sched_port_queue_is_empty(struct rte_sched_port *port, uint32_t qindex) #ifdef RTE_SCHED_COLLECT_STATS static inline void -rte_sched_port_update_subport_stats(struct rte_sched_port *port, uint32_t qindex, struct rte_mbuf *pkt) +rte_sched_port_update_subport_stats(struct rte_sched_port *port, + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt) { - struct rte_sched_subport *s = port->subport + (qindex / rte_sched_port_queues_per_subport(port)); uint32_t tc_index = rte_sched_port_pipe_tc(port, qindex); uint32_t pkt_len = pkt->pkt_len; - s->stats.n_pkts_tc[tc_index] += 1; - s->stats.n_bytes_tc[tc_index] += pkt_len; + subport->stats.n_pkts_tc[tc_index] += 1; + subport->stats.n_bytes_tc[tc_index] += pkt_len; } #ifdef RTE_SCHED_RED static inline void rte_sched_port_update_subport_stats_on_drop(struct rte_sched_port *port, - uint32_t qindex, - struct rte_mbuf *pkt, uint32_t red) + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt, + uint32_t red) #else static inline void rte_sched_port_update_subport_stats_on_drop(struct rte_sched_port *port, - uint32_t qindex, - struct rte_mbuf *pkt, __rte_unused uint32_t red) + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt, + __rte_unused uint32_t red) #endif { - struct rte_sched_subport *s = port->subport + (qindex / rte_sched_port_queues_per_subport(port)); uint32_t tc_index = rte_sched_port_pipe_tc(port, qindex); uint32_t pkt_len = pkt->pkt_len; - s->stats.n_pkts_tc_dropped[tc_index] += 1; - s->stats.n_bytes_tc_dropped[tc_index] += pkt_len; + subport->stats.n_pkts_tc_dropped[tc_index] += 1; + subport->stats.n_bytes_tc_dropped[tc_index] += pkt_len; #ifdef RTE_SCHED_RED - s->stats.n_pkts_red_dropped[tc_index] += red; + subport->stats.n_pkts_red_dropped[tc_index] += red; #endif } static inline void -rte_sched_port_update_queue_stats(struct rte_sched_port *port, uint32_t qindex, struct rte_mbuf *pkt) +rte_sched_port_update_queue_stats(struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt) { - struct rte_sched_queue_extra *qe = port->queue_extra + qindex; + struct rte_sched_queue_extra *qe = subport->queue_extra + qindex; uint32_t pkt_len = pkt->pkt_len; qe->stats.n_pkts += 1; @@ -1630,17 +1639,19 @@ rte_sched_port_update_queue_stats(struct rte_sched_port *port, uint32_t qindex, #ifdef RTE_SCHED_RED static inline void -rte_sched_port_update_queue_stats_on_drop(struct rte_sched_port *port, - uint32_t qindex, - struct rte_mbuf *pkt, uint32_t red) +rte_sched_port_update_queue_stats_on_drop(struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt, + uint32_t red) #else static inline void -rte_sched_port_update_queue_stats_on_drop(struct rte_sched_port *port, - uint32_t qindex, - struct rte_mbuf *pkt, __rte_unused uint32_t red) +rte_sched_port_update_queue_stats_on_drop(struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt, + __rte_unused uint32_t red) #endif { - struct rte_sched_queue_extra *qe = port->queue_extra + qindex; + struct rte_sched_queue_extra *qe = subport->queue_extra + qindex; uint32_t pkt_len = pkt->pkt_len; qe->stats.n_pkts_dropped += 1; @@ -1655,7 +1666,11 @@ rte_sched_port_update_queue_stats_on_drop(struct rte_sched_port *port, #ifdef RTE_SCHED_RED static inline int -rte_sched_port_red_drop(struct rte_sched_port *port, struct rte_mbuf *pkt, uint32_t qindex, uint16_t qlen) +rte_sched_port_red_drop(struct rte_sched_port *port, + struct rte_sched_subport *subport, + struct rte_mbuf *pkt, + uint32_t qindex, + uint16_t qlen) { struct rte_sched_queue_extra *qe; struct rte_red_config *red_cfg; @@ -1665,12 +1680,12 @@ rte_sched_port_red_drop(struct rte_sched_port *port, struct rte_mbuf *pkt, uint3 tc_index = rte_sched_port_pipe_tc(port, qindex); color = rte_sched_port_pkt_read_color(pkt); - red_cfg = &port->red_config[tc_index][color]; + red_cfg = &subport->red_config[tc_index][color]; if ((red_cfg->min_th | red_cfg->max_th) == 0) return 0; - qe = port->queue_extra + qindex; + qe = subport->queue_extra + qindex; red = &qe->red; return rte_red_enqueue(red_cfg, red, qlen, port->time); @@ -1687,7 +1702,14 @@ rte_sched_port_set_queue_empty_timestamp(struct rte_sched_port *port, uint32_t q #else -#define rte_sched_port_red_drop(port, pkt, qindex, qlen) 0 +static inline int rte_sched_port_red_drop(struct rte_sched_port *port __rte_unused, + struct rte_sched_subport *subport __rte_unused, + struct rte_mbuf *pkt __rte_unused, + uint32_t qindex __rte_unused, + uint16_t qlen __rte_unused) +{ + return 0; +} #define rte_sched_port_set_queue_empty_timestamp(port, qindex) @@ -1722,63 +1744,79 @@ debug_check_queue_slab(struct rte_sched_port *port, uint32_t bmp_pos, #endif /* RTE_SCHED_DEBUG */ +static inline struct rte_sched_subport * +rte_sched_port_subport(struct rte_sched_port *port, + struct rte_mbuf *pkt) +{ + uint32_t queue_id = rte_mbuf_sched_queue_get(pkt); + uint32_t subport_id = queue_id >> (port->n_pipes_per_subport_log2 + 4); + + return port->subports[subport_id]; +} + static inline uint32_t -rte_sched_port_enqueue_qptrs_prefetch0(struct rte_sched_port *port, - struct rte_mbuf *pkt) +rte_sched_port_enqueue_qptrs_prefetch0(struct rte_sched_subport *subport, + struct rte_mbuf *pkt, uint32_t subport_qmask) { struct rte_sched_queue *q; #ifdef RTE_SCHED_COLLECT_STATS struct rte_sched_queue_extra *qe; #endif uint32_t qindex = rte_mbuf_sched_queue_get(pkt); + uint32_t subport_queue_id = subport_qmask & qindex; - q = port->queue + qindex; + q = subport->queue + subport_queue_id; rte_prefetch0(q); #ifdef RTE_SCHED_COLLECT_STATS - qe = port->queue_extra + qindex; + qe = subport->queue_extra + subport_queue_id; rte_prefetch0(qe); #endif - return qindex; + return subport_queue_id; } static inline void rte_sched_port_enqueue_qwa_prefetch0(struct rte_sched_port *port, - uint32_t qindex, struct rte_mbuf **qbase) + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf **qbase) { struct rte_sched_queue *q; struct rte_mbuf **q_qw; uint16_t qsize; - q = port->queue + qindex; - qsize = rte_sched_port_qsize(port, qindex); + q = subport->queue + qindex; + qsize = rte_sched_subport_pipe_qsize(port, subport, qindex); q_qw = qbase + (q->qw & (qsize - 1)); rte_prefetch0(q_qw); - rte_bitmap_prefetch0(port->bmp, qindex); + rte_bitmap_prefetch0(subport->bmp, qindex); } static inline int -rte_sched_port_enqueue_qwa(struct rte_sched_port *port, uint32_t qindex, - struct rte_mbuf **qbase, struct rte_mbuf *pkt) +rte_sched_port_enqueue_qwa(struct rte_sched_port *port, + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf **qbase, + struct rte_mbuf *pkt) { struct rte_sched_queue *q; uint16_t qsize; uint16_t qlen; - q = port->queue + qindex; - qsize = rte_sched_port_qsize(port, qindex); + q = subport->queue + qindex; + qsize = rte_sched_subport_pipe_qsize(port, subport, qindex); qlen = q->qw - q->qr; /* Drop the packet (and update drop stats) when queue is full */ - if (unlikely(rte_sched_port_red_drop(port, pkt, qindex, qlen) || + if (unlikely(rte_sched_port_red_drop(port, subport, pkt, qindex, qlen) || (qlen >= qsize))) { rte_pktmbuf_free(pkt); #ifdef RTE_SCHED_COLLECT_STATS - rte_sched_port_update_subport_stats_on_drop(port, qindex, pkt, - qlen < qsize); - rte_sched_port_update_queue_stats_on_drop(port, qindex, pkt, - qlen < qsize); + rte_sched_port_update_subport_stats_on_drop(port, subport, + qindex, pkt, qlen < qsize); + rte_sched_port_update_queue_stats_on_drop(subport, qindex, pkt, + qlen < qsize); #endif return 0; } @@ -1787,13 +1825,13 @@ rte_sched_port_enqueue_qwa(struct rte_sched_port *port, uint32_t qindex, qbase[q->qw & (qsize - 1)] = pkt; q->qw++; - /* Activate queue in the port bitmap */ - rte_bitmap_set(port->bmp, qindex); + /* Activate queue in the subport bitmap */ + rte_bitmap_set(subport->bmp, qindex); /* Statistics */ #ifdef RTE_SCHED_COLLECT_STATS - rte_sched_port_update_subport_stats(port, qindex, pkt); - rte_sched_port_update_queue_stats(port, qindex, pkt); + rte_sched_port_update_subport_stats(port, subport, qindex, pkt); + rte_sched_port_update_queue_stats(subport, qindex, pkt); #endif return 1; @@ -1821,17 +1859,22 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, *pkt30, *pkt31, *pkt_last; struct rte_mbuf **q00_base, **q01_base, **q10_base, **q11_base, **q20_base, **q21_base, **q30_base, **q31_base, **q_last_base; + struct rte_sched_subport *subport00, *subport01, *subport10, *subport11, + *subport20, *subport21, *subport30, *subport31, *subport_last; uint32_t q00, q01, q10, q11, q20, q21, q30, q31, q_last; uint32_t r00, r01, r10, r11, r20, r21, r30, r31, r_last; + uint32_t subport_qmask; uint32_t result, i; result = 0; + subport_qmask = (1 << (port->n_pipes_per_subport_log2 + 4)) - 1; /* * Less then 6 input packets available, which is not enough to * feed the pipeline */ if (unlikely(n_pkts < 6)) { + struct rte_sched_subport *subports[5]; struct rte_mbuf **q_base[5]; uint32_t q[5]; @@ -1839,22 +1882,26 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, for (i = 0; i < n_pkts; i++) rte_prefetch0(pkts[i]); + /* Prefetch the subport structure for each packet */ + for (i = 0; i < n_pkts; i++) + subports[i] = rte_sched_port_subport(port, pkts[i]); + /* Prefetch the queue structure for each queue */ for (i = 0; i < n_pkts; i++) - q[i] = rte_sched_port_enqueue_qptrs_prefetch0(port, - pkts[i]); + q[i] = rte_sched_port_enqueue_qptrs_prefetch0(subports[i], + pkts[i], subport_qmask); /* Prefetch the write pointer location of each queue */ for (i = 0; i < n_pkts; i++) { - q_base[i] = rte_sched_port_qbase(port, q[i]); - rte_sched_port_enqueue_qwa_prefetch0(port, q[i], - q_base[i]); + q_base[i] = rte_sched_subport_pipe_qbase(subports[i], q[i]); + rte_sched_port_enqueue_qwa_prefetch0(port, subports[i], + q[i], q_base[i]); } /* Write each packet to its queue */ for (i = 0; i < n_pkts; i++) - result += rte_sched_port_enqueue_qwa(port, q[i], - q_base[i], pkts[i]); + result += rte_sched_port_enqueue_qwa(port, subports[i], + q[i], q_base[i], pkts[i]); return result; } @@ -1870,21 +1917,29 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, rte_prefetch0(pkt10); rte_prefetch0(pkt11); - q20 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt20); - q21 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt21); + subport20 = rte_sched_port_subport(port, pkt20); + subport21 = rte_sched_port_subport(port, pkt21); + q20 = rte_sched_port_enqueue_qptrs_prefetch0(subport20, + pkt20, subport_qmask); + q21 = rte_sched_port_enqueue_qptrs_prefetch0(subport21, + pkt21, subport_qmask); pkt00 = pkts[4]; pkt01 = pkts[5]; rte_prefetch0(pkt00); rte_prefetch0(pkt01); - q10 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt10); - q11 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt11); + subport10 = rte_sched_port_subport(port, pkt10); + subport11 = rte_sched_port_subport(port, pkt11); + q10 = rte_sched_port_enqueue_qptrs_prefetch0(subport10, + pkt10, subport_qmask); + q11 = rte_sched_port_enqueue_qptrs_prefetch0(subport11, + pkt11, subport_qmask); - q20_base = rte_sched_port_qbase(port, q20); - q21_base = rte_sched_port_qbase(port, q21); - rte_sched_port_enqueue_qwa_prefetch0(port, q20, q20_base); - rte_sched_port_enqueue_qwa_prefetch0(port, q21, q21_base); + q20_base = rte_sched_subport_pipe_qbase(subport20, q20); + q21_base = rte_sched_subport_pipe_qbase(subport21, q21); + rte_sched_port_enqueue_qwa_prefetch0(port, subport20, q20, q20_base); + rte_sched_port_enqueue_qwa_prefetch0(port, subport21, q21, q21_base); /* Run the pipeline */ for (i = 6; i < (n_pkts & (~1)); i += 2) { @@ -1899,6 +1954,10 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, q31 = q21; q20 = q10; q21 = q11; + subport30 = subport20; + subport31 = subport21; + subport20 = subport10; + subport21 = subport11; q30_base = q20_base; q31_base = q21_base; @@ -1908,19 +1967,25 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, rte_prefetch0(pkt00); rte_prefetch0(pkt01); - /* Stage 1: Prefetch queue structure storing queue pointers */ - q10 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt10); - q11 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt11); + /* Stage 1: Prefetch subport and queue structure storing queue pointers */ + subport10 = rte_sched_port_subport(port, pkt10); + subport11 = rte_sched_port_subport(port, pkt11); + q10 = rte_sched_port_enqueue_qptrs_prefetch0(subport10, + pkt10, subport_qmask); + q11 = rte_sched_port_enqueue_qptrs_prefetch0(subport11, + pkt11, subport_qmask); /* Stage 2: Prefetch queue write location */ - q20_base = rte_sched_port_qbase(port, q20); - q21_base = rte_sched_port_qbase(port, q21); - rte_sched_port_enqueue_qwa_prefetch0(port, q20, q20_base); - rte_sched_port_enqueue_qwa_prefetch0(port, q21, q21_base); + q20_base = rte_sched_subport_pipe_qbase(subport20, q20); + q21_base = rte_sched_subport_pipe_qbase(subport21, q21); + rte_sched_port_enqueue_qwa_prefetch0(port, subport20, q20, q20_base); + rte_sched_port_enqueue_qwa_prefetch0(port, subport21, q21, q21_base); /* Stage 3: Write packet to queue and activate queue */ - r30 = rte_sched_port_enqueue_qwa(port, q30, q30_base, pkt30); - r31 = rte_sched_port_enqueue_qwa(port, q31, q31_base, pkt31); + r30 = rte_sched_port_enqueue_qwa(port, subport30, + q30, q30_base, pkt30); + r31 = rte_sched_port_enqueue_qwa(port, subport31, + q31, q31_base, pkt31); result += r30 + r31; } @@ -1932,38 +1997,52 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, pkt_last = pkts[n_pkts - 1]; rte_prefetch0(pkt_last); - q00 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt00); - q01 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt01); - - q10_base = rte_sched_port_qbase(port, q10); - q11_base = rte_sched_port_qbase(port, q11); - rte_sched_port_enqueue_qwa_prefetch0(port, q10, q10_base); - rte_sched_port_enqueue_qwa_prefetch0(port, q11, q11_base); - - r20 = rte_sched_port_enqueue_qwa(port, q20, q20_base, pkt20); - r21 = rte_sched_port_enqueue_qwa(port, q21, q21_base, pkt21); + subport00 = rte_sched_port_subport(port, pkt00); + subport01 = rte_sched_port_subport(port, pkt01); + q00 = rte_sched_port_enqueue_qptrs_prefetch0(subport00, + pkt00, subport_qmask); + q01 = rte_sched_port_enqueue_qptrs_prefetch0(subport01, + pkt01, subport_qmask); + + q10_base = rte_sched_subport_pipe_qbase(subport10, q10); + q11_base = rte_sched_subport_pipe_qbase(subport11, q11); + rte_sched_port_enqueue_qwa_prefetch0(port, subport10, q10, q10_base); + rte_sched_port_enqueue_qwa_prefetch0(port, subport11, q11, q11_base); + + r20 = rte_sched_port_enqueue_qwa(port, subport20, + q20, q20_base, pkt20); + r21 = rte_sched_port_enqueue_qwa(port, subport21, + q21, q21_base, pkt21); result += r20 + r21; - q_last = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt_last); + subport_last = rte_sched_port_subport(port, pkt_last); + q_last = rte_sched_port_enqueue_qptrs_prefetch0(subport_last, + pkt_last, subport_qmask); - q00_base = rte_sched_port_qbase(port, q00); - q01_base = rte_sched_port_qbase(port, q01); - rte_sched_port_enqueue_qwa_prefetch0(port, q00, q00_base); - rte_sched_port_enqueue_qwa_prefetch0(port, q01, q01_base); + q00_base = rte_sched_subport_pipe_qbase(subport00, q00); + q01_base = rte_sched_subport_pipe_qbase(subport01, q01); + rte_sched_port_enqueue_qwa_prefetch0(port, subport00, q00, q00_base); + rte_sched_port_enqueue_qwa_prefetch0(port, subport01, q01, q01_base); - r10 = rte_sched_port_enqueue_qwa(port, q10, q10_base, pkt10); - r11 = rte_sched_port_enqueue_qwa(port, q11, q11_base, pkt11); + r10 = rte_sched_port_enqueue_qwa(port, subport10, q10, + q10_base, pkt10); + r11 = rte_sched_port_enqueue_qwa(port, subport11, q11, + q11_base, pkt11); result += r10 + r11; - q_last_base = rte_sched_port_qbase(port, q_last); - rte_sched_port_enqueue_qwa_prefetch0(port, q_last, q_last_base); + q_last_base = rte_sched_subport_pipe_qbase(subport_last, q_last); + rte_sched_port_enqueue_qwa_prefetch0(port, subport_last, + q_last, q_last_base); - r00 = rte_sched_port_enqueue_qwa(port, q00, q00_base, pkt00); - r01 = rte_sched_port_enqueue_qwa(port, q01, q01_base, pkt01); + r00 = rte_sched_port_enqueue_qwa(port, subport00, q00, + q00_base, pkt00); + r01 = rte_sched_port_enqueue_qwa(port, subport01, q01, + q01_base, pkt01); result += r00 + r01; if (n_pkts & 1) { - r_last = rte_sched_port_enqueue_qwa(port, q_last, q_last_base, pkt_last); + r_last = rte_sched_port_enqueue_qwa(port, subport_last, + q_last, q_last_base, pkt_last); result += r_last; } -- 2.21.0
Update memory footprint compute function for allowing subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 100 ++++++++++------------------------- lib/librte_sched/rte_sched.h | 8 +-- 2 files changed, 34 insertions(+), 74 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index a8174afad..58f34359c 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -486,70 +486,6 @@ rte_sched_port_check_params(struct rte_sched_port_params *params) return 0; } -static uint32_t -rte_sched_port_get_array_base(struct rte_sched_port_params *params, enum rte_sched_port_array array) -{ - uint32_t n_subports_per_port = params->n_subports_per_port; - uint32_t n_pipes_per_subport = params->n_pipes_per_subport; - uint32_t n_pipes_per_port = n_pipes_per_subport * n_subports_per_port; - uint32_t n_queues_per_port = RTE_SCHED_QUEUES_PER_PIPE * n_pipes_per_subport * n_subports_per_port; - - uint32_t size_subport = n_subports_per_port * sizeof(struct rte_sched_subport); - uint32_t size_pipe = n_pipes_per_port * sizeof(struct rte_sched_pipe); - uint32_t size_queue = n_queues_per_port * sizeof(struct rte_sched_queue); - uint32_t size_queue_extra - = n_queues_per_port * sizeof(struct rte_sched_queue_extra); - uint32_t size_pipe_profiles - = params->n_max_pipe_profiles * sizeof(struct rte_sched_pipe_profile); - uint32_t size_bmp_array = rte_bitmap_get_memory_footprint(n_queues_per_port); - uint32_t size_per_pipe_queue_array, size_queue_array; - - uint32_t base, i; - - size_per_pipe_queue_array = 0; - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - if (i < RTE_SCHED_TRAFFIC_CLASS_BE) - size_per_pipe_queue_array += - params->qsize[i] * sizeof(struct rte_mbuf *); - else - size_per_pipe_queue_array += RTE_SCHED_MAX_QUEUES_PER_TC * - params->qsize[i] * sizeof(struct rte_mbuf *); - } - size_queue_array = n_pipes_per_port * size_per_pipe_queue_array; - - base = 0; - - if (array == e_RTE_SCHED_PORT_ARRAY_SUBPORT) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_subport); - - if (array == e_RTE_SCHED_PORT_ARRAY_PIPE) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_pipe); - - if (array == e_RTE_SCHED_PORT_ARRAY_QUEUE) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_queue); - - if (array == e_RTE_SCHED_PORT_ARRAY_QUEUE_EXTRA) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_queue_extra); - - if (array == e_RTE_SCHED_PORT_ARRAY_PIPE_PROFILES) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_pipe_profiles); - - if (array == e_RTE_SCHED_PORT_ARRAY_BMP_ARRAY) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_bmp_array); - - if (array == e_RTE_SCHED_PORT_ARRAY_QUEUE_ARRAY) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_queue_array); - - return base; -} - static uint32_t rte_sched_subport_get_array_base(struct rte_sched_subport_params *params, enum rte_sched_subport_array array) @@ -870,22 +806,44 @@ rte_sched_subport_check_params(struct rte_sched_subport_params *params, } uint32_t -rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params) +rte_sched_port_get_memory_footprint(struct rte_sched_port_params *port_params, + struct rte_sched_subport_params **subport_params) { - uint32_t size0, size1; + uint32_t size0 = 0, size1 = 0, i; int status; - status = rte_sched_port_check_params(params); + status = rte_sched_port_check_params(port_params); if (status != 0) { - RTE_LOG(NOTICE, SCHED, - "Port scheduler params check failed (%d)\n", status); + RTE_LOG(ERR, SCHED, + "%s: Port scheduler port params check failed (%d)\n", + __func__, status); return 0; } + for (i = 0; i < port_params->n_subports_per_port; i++) { + struct rte_sched_subport_params *sp = subport_params[i]; + + status = rte_sched_subport_check_params(sp, + port_params->n_pipes_per_subport, + port_params->rate); + if (status != 0) { + RTE_LOG(ERR, SCHED, + "%s: Port scheduler subport params check failed (%d)\n", + __func__, status); + + return 0; + } + } + size0 = sizeof(struct rte_sched_port); - size1 = rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_TOTAL); + + for (i = 0; i < port_params->n_subports_per_port; i++) { + struct rte_sched_subport_params *sp = subport_params[i]; + + size1 += rte_sched_subport_get_array_base(sp, + e_RTE_SCHED_SUBPORT_ARRAY_TOTAL); + } return size0 + size1; } diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index 5001f09ed..40f02f124 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -373,14 +373,16 @@ rte_sched_pipe_config(struct rte_sched_port *port, /** * Hierarchical scheduler memory footprint size per port * - * @param params + * @param port_params * Port scheduler configuration parameter structure + * @param subport_params + * Array of subport parameter structures * @return * Memory footprint size in bytes upon success, 0 otherwise */ uint32_t -rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params); - +rte_sched_port_get_memory_footprint(struct rte_sched_port_params *port_params, + struct rte_sched_subport_params **subport_params); /* * Statistics * -- 2.21.0
Modify packet grinder functions of the schedule to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 223 +++++++++++++++++------------------ 1 file changed, 106 insertions(+), 117 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 58f34359c..d7abe9661 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -322,24 +322,6 @@ rte_sched_port_queues_per_port(struct rte_sched_port *port) return RTE_SCHED_QUEUES_PER_PIPE * port->n_pipes_per_subport * port->n_subports_per_port; } -static inline struct rte_mbuf ** -rte_sched_port_qbase(struct rte_sched_port *port, uint32_t qindex) -{ - uint32_t pindex = qindex >> 4; - uint32_t qpos = qindex & 0xF; - - return (port->queue_array + pindex * - port->qsize_sum + port->qsize_add[qpos]); -} - -static inline uint16_t -rte_sched_port_qsize(struct rte_sched_port *port, uint32_t qindex) -{ - uint32_t tc = port->pipe_tc[qindex & (RTE_SCHED_QUEUES_PER_PIPE - 1)]; - - return port->qsize[tc]; -} - static inline uint16_t rte_sched_port_pipe_queue(struct rte_sched_port *port, uint32_t traffic_class) { @@ -1533,9 +1515,10 @@ rte_sched_queue_read_stats(struct rte_sched_port *port, #ifdef RTE_SCHED_DEBUG static inline int -rte_sched_port_queue_is_empty(struct rte_sched_port *port, uint32_t qindex) +rte_sched_port_queue_is_empty(struct rte_sched_subport *subport, + uint32_t qindex) { - struct rte_sched_queue *queue = port->queue + qindex; + struct rte_sched_queue *queue = subport->queue + qindex; return queue->qr == queue->qw; } @@ -1650,9 +1633,10 @@ rte_sched_port_red_drop(struct rte_sched_port *port, } static inline void -rte_sched_port_set_queue_empty_timestamp(struct rte_sched_port *port, uint32_t qindex) +rte_sched_port_set_queue_empty_timestamp(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t qindex) { - struct rte_sched_queue_extra *qe = port->queue_extra + qindex; + struct rte_sched_queue_extra *qe = subport->queue_extra + qindex; struct rte_red *red = &qe->red; rte_red_mark_queue_empty(red, port->time); @@ -1669,14 +1653,14 @@ static inline int rte_sched_port_red_drop(struct rte_sched_port *port __rte_unus return 0; } -#define rte_sched_port_set_queue_empty_timestamp(port, qindex) +#define rte_sched_port_set_queue_empty_timestamp(port, subport, qindex) #endif /* RTE_SCHED_RED */ #ifdef RTE_SCHED_DEBUG static inline void -debug_check_queue_slab(struct rte_sched_port *port, uint32_t bmp_pos, +debug_check_queue_slab(struct rte_sched_subport *subport, uint32_t bmp_pos, uint64_t bmp_slab) { uint64_t mask; @@ -1688,7 +1672,7 @@ debug_check_queue_slab(struct rte_sched_port *port, uint32_t bmp_pos, panic = 0; for (i = 0, mask = 1; i < 64; i++, mask <<= 1) { if (mask & bmp_slab) { - if (rte_sched_port_queue_is_empty(port, bmp_pos + i)) { + if (rte_sched_port_queue_is_empty(subport, bmp_pos + i)) { printf("Queue %u (slab offset %u) is empty\n", bmp_pos + i, i); panic = 1; } @@ -2010,10 +1994,10 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, #ifndef RTE_SCHED_SUBPORT_TC_OV static inline void -grinder_credits_update(struct rte_sched_port *port, uint32_t pos) +grinder_credits_update(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; struct rte_sched_pipe_profile *params = grinder->pipe_params; uint64_t n_periods; @@ -2051,10 +2035,9 @@ grinder_credits_update(struct rte_sched_port *port, uint32_t pos) #else static inline uint32_t -grinder_tc_ov_credits_update(struct rte_sched_port *port, uint32_t pos) +grinder_tc_ov_credits_update(struct rte_sched_port *port, + struct rte_sched_subport *subport) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; uint32_t tc_ov_consumption[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; uint32_t tc_consumption = 0, tc_ov_consumption_max; uint32_t tc_ov_wm = subport->tc_ov_wm; @@ -2094,10 +2077,10 @@ grinder_tc_ov_credits_update(struct rte_sched_port *port, uint32_t pos) } static inline void -grinder_credits_update(struct rte_sched_port *port, uint32_t pos) +grinder_credits_update(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; struct rte_sched_pipe_profile *params = grinder->pipe_params; uint64_t n_periods; @@ -2117,7 +2100,7 @@ grinder_credits_update(struct rte_sched_port *port, uint32_t pos) /* Subport TCs */ if (unlikely(port->time >= subport->tc_time)) { - subport->tc_ov_wm = grinder_tc_ov_credits_update(port, pos); + subport->tc_ov_wm = grinder_tc_ov_credits_update(port, subport); for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) subport->tc_credits[i] = subport->tc_credits_per_period[i]; @@ -2147,10 +2130,10 @@ grinder_credits_update(struct rte_sched_port *port, uint32_t pos) #ifndef RTE_SCHED_SUBPORT_TC_OV static inline int -grinder_credits_check(struct rte_sched_port *port, uint32_t pos) +grinder_credits_check(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; + 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; @@ -2182,10 +2165,10 @@ grinder_credits_check(struct rte_sched_port *port, uint32_t pos) #else static inline int -grinder_credits_check(struct rte_sched_port *port, uint32_t pos) +grinder_credits_check(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; + 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; @@ -2230,15 +2213,16 @@ grinder_credits_check(struct rte_sched_port *port, uint32_t pos) static inline int -grinder_schedule(struct rte_sched_port *port, uint32_t pos) +grinder_schedule(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_queue *queue = grinder->queue[grinder->qpos]; struct rte_mbuf *pkt = grinder->pkt; uint32_t pkt_len = pkt->pkt_len + port->frame_overhead; uint32_t be_tc_active; - if (!grinder_credits_check(port, pos)) + if (!grinder_credits_check(port, subport, pos)) return 0; /* Advance port time */ @@ -2255,15 +2239,15 @@ grinder_schedule(struct rte_sched_port *port, uint32_t pos) if (queue->qr == queue->qw) { uint32_t qindex = grinder->qindex[grinder->qpos]; - rte_bitmap_clear(port->bmp, qindex); + rte_bitmap_clear(subport->bmp, qindex); grinder->qmask &= ~(1 << grinder->qpos); if (be_tc_active) grinder->wrr_mask[grinder->qpos] = 0; - rte_sched_port_set_queue_empty_timestamp(port, qindex); + rte_sched_port_set_queue_empty_timestamp(port, subport, qindex); } /* Reset pipe loop detection */ - port->pipe_loop = RTE_SCHED_PIPE_INVALID; + subport->pipe_loop = RTE_SCHED_PIPE_INVALID; grinder->productive = 1; return 1; @@ -2272,13 +2256,13 @@ grinder_schedule(struct rte_sched_port *port, uint32_t pos) #ifdef SCHED_VECTOR_SSE4 static inline int -grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) +grinder_pipe_exists(struct rte_sched_subport *subport, uint32_t base_pipe) { __m128i index = _mm_set1_epi32(base_pipe); - __m128i pipes = _mm_load_si128((__m128i *)port->grinder_base_bmp_pos); + __m128i pipes = _mm_load_si128((__m128i *)subport->grinder_base_bmp_pos); __m128i res = _mm_cmpeq_epi32(pipes, index); - pipes = _mm_load_si128((__m128i *)(port->grinder_base_bmp_pos + 4)); + pipes = _mm_load_si128((__m128i *)(subport->grinder_base_bmp_pos + 4)); pipes = _mm_cmpeq_epi32(pipes, index); res = _mm_or_si128(res, pipes); @@ -2291,10 +2275,10 @@ grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) #elif defined(SCHED_VECTOR_NEON) static inline int -grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) +grinder_pipe_exists(struct rte_sched_subport *subport, uint32_t base_pipe) { uint32x4_t index, pipes; - uint32_t *pos = (uint32_t *)port->grinder_base_bmp_pos; + uint32_t *pos = (uint32_t *)subport->grinder_base_bmp_pos; index = vmovq_n_u32(base_pipe); pipes = vld1q_u32(pos); @@ -2311,12 +2295,12 @@ grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) #else static inline int -grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) +grinder_pipe_exists(struct rte_sched_subport *subport, uint32_t base_pipe) { uint32_t i; for (i = 0; i < RTE_SCHED_PORT_N_GRINDERS; i++) { - if (port->grinder_base_bmp_pos[i] == base_pipe) + if (subport->grinder_base_bmp_pos[i] == base_pipe) return 1; } @@ -2326,9 +2310,10 @@ grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) #endif /* RTE_SCHED_OPTIMIZATIONS */ static inline void -grinder_pcache_populate(struct rte_sched_port *port, uint32_t pos, uint32_t bmp_pos, uint64_t bmp_slab) +grinder_pcache_populate(struct rte_sched_subport *subport, + uint32_t pos, uint32_t bmp_pos, uint64_t bmp_slab) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint16_t w[4]; grinder->pcache_w = 0; @@ -2357,9 +2342,10 @@ grinder_pcache_populate(struct rte_sched_port *port, uint32_t pos, uint32_t bmp_ } static inline void -grinder_tccache_populate(struct rte_sched_port *port, uint32_t pos, uint32_t qindex, uint16_t qmask) +grinder_tccache_populate(struct rte_sched_subport *subport, + uint32_t pos, uint32_t qindex, uint16_t qmask) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint8_t b, i; grinder->tccache_w = 0; @@ -2380,9 +2366,10 @@ grinder_tccache_populate(struct rte_sched_port *port, uint32_t pos, uint32_t qin } static inline int -grinder_next_tc(struct rte_sched_port *port, uint32_t pos) +grinder_next_tc(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_mbuf **qbase; uint32_t qindex; uint16_t qsize; @@ -2391,15 +2378,15 @@ grinder_next_tc(struct rte_sched_port *port, uint32_t pos) return 0; qindex = grinder->tccache_qindex[grinder->tccache_r]; - qbase = rte_sched_port_qbase(port, qindex); - qsize = rte_sched_port_qsize(port, qindex); + qbase = rte_sched_subport_pipe_qbase(subport, qindex); + qsize = rte_sched_subport_pipe_qsize(port, subport, qindex); grinder->tc_index = rte_sched_port_pipe_tc(port, qindex); grinder->qmask = grinder->tccache_qmask[grinder->tccache_r]; grinder->qsize = qsize; if (grinder->tc_index < RTE_SCHED_TRAFFIC_CLASS_BE) { - grinder->queue[0] = port->queue + qindex; + grinder->queue[0] = subport->queue + qindex; grinder->qbase[0] = qbase; grinder->qindex[0] = qindex; grinder->tccache_r++; @@ -2407,10 +2394,10 @@ grinder_next_tc(struct rte_sched_port *port, uint32_t pos) return 1; } - grinder->queue[0] = port->queue + qindex; - grinder->queue[1] = port->queue + qindex + 1; - grinder->queue[2] = port->queue + qindex + 2; - grinder->queue[3] = port->queue + qindex + 3; + grinder->queue[0] = subport->queue + qindex; + grinder->queue[1] = subport->queue + qindex + 1; + grinder->queue[2] = subport->queue + qindex + 2; + grinder->queue[3] = subport->queue + qindex + 3; grinder->qbase[0] = qbase; grinder->qbase[1] = qbase + qsize; @@ -2427,9 +2414,10 @@ grinder_next_tc(struct rte_sched_port *port, uint32_t pos) } static inline int -grinder_next_pipe(struct rte_sched_port *port, uint32_t pos) +grinder_next_pipe(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint32_t pipe_qindex; uint16_t pipe_qmask; @@ -2442,22 +2430,22 @@ grinder_next_pipe(struct rte_sched_port *port, uint32_t pos) uint32_t bmp_pos = 0; /* Get another non-empty pipe group */ - if (unlikely(rte_bitmap_scan(port->bmp, &bmp_pos, &bmp_slab) <= 0)) + if (unlikely(rte_bitmap_scan(subport->bmp, &bmp_pos, &bmp_slab) <= 0)) return 0; #ifdef RTE_SCHED_DEBUG - debug_check_queue_slab(port, bmp_pos, bmp_slab); + debug_check_queue_slab(subport, bmp_pos, bmp_slab); #endif /* Return if pipe group already in one of the other grinders */ - port->grinder_base_bmp_pos[pos] = RTE_SCHED_BMP_POS_INVALID; - if (unlikely(grinder_pipe_exists(port, bmp_pos))) + subport->grinder_base_bmp_pos[pos] = RTE_SCHED_BMP_POS_INVALID; + if (unlikely(grinder_pipe_exists(subport, bmp_pos))) return 0; - port->grinder_base_bmp_pos[pos] = bmp_pos; + subport->grinder_base_bmp_pos[pos] = bmp_pos; /* Install new pipe group into grinder's pipe cache */ - grinder_pcache_populate(port, pos, bmp_pos, bmp_slab); + grinder_pcache_populate(subport, pos, bmp_pos, bmp_slab); pipe_qmask = grinder->pcache_qmask[0]; pipe_qindex = grinder->pcache_qindex[0]; @@ -2466,18 +2454,18 @@ grinder_next_pipe(struct rte_sched_port *port, uint32_t pos) /* Install new pipe in the grinder */ grinder->pindex = pipe_qindex >> 4; - grinder->subport = port->subport + (grinder->pindex / port->n_pipes_per_subport); - grinder->pipe = port->pipe + grinder->pindex; + grinder->subport = subport; + grinder->pipe = subport->pipe + grinder->pindex; grinder->pipe_params = NULL; /* to be set after the pipe structure is prefetched */ grinder->productive = 0; - grinder_tccache_populate(port, pos, pipe_qindex, pipe_qmask); - grinder_next_tc(port, pos); + grinder_tccache_populate(subport, pos, pipe_qindex, pipe_qmask); + grinder_next_tc(port, subport, pos); /* Check for pipe exhaustion */ - if (grinder->pindex == port->pipe_loop) { - port->pipe_exhaustion = 1; - port->pipe_loop = RTE_SCHED_PIPE_INVALID; + if (grinder->pindex == subport->pipe_loop) { + subport->pipe_exhaustion = 1; + subport->pipe_loop = RTE_SCHED_PIPE_INVALID; } return 1; @@ -2485,9 +2473,9 @@ grinder_next_pipe(struct rte_sched_port *port, uint32_t pos) static inline void -grinder_wrr_load(struct rte_sched_port *port, uint32_t pos) +grinder_wrr_load(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; struct rte_sched_pipe_profile *pipe_params = grinder->pipe_params; uint32_t qmask = grinder->qmask; @@ -2513,9 +2501,9 @@ grinder_wrr_load(struct rte_sched_port *port, uint32_t pos) } static inline void -grinder_wrr_store(struct rte_sched_port *port, uint32_t pos) +grinder_wrr_store(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; pipe->wrr_tokens[0] = @@ -2533,9 +2521,9 @@ grinder_wrr_store(struct rte_sched_port *port, uint32_t pos) } static inline void -grinder_wrr(struct rte_sched_port *port, uint32_t pos) +grinder_wrr(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint16_t wrr_tokens_min; grinder->wrr_tokens[0] |= ~grinder->wrr_mask[0]; @@ -2553,21 +2541,21 @@ grinder_wrr(struct rte_sched_port *port, uint32_t pos) } -#define grinder_evict(port, pos) +#define grinder_evict(subport, pos) static inline void -grinder_prefetch_pipe(struct rte_sched_port *port, uint32_t pos) +grinder_prefetch_pipe(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; rte_prefetch0(grinder->pipe); rte_prefetch0(grinder->queue[0]); } static inline void -grinder_prefetch_tc_queue_arrays(struct rte_sched_port *port, uint32_t pos) +grinder_prefetch_tc_queue_arrays(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint16_t qsize, qr[RTE_SCHED_MAX_QUEUES_PER_TC]; qsize = grinder->qsize; @@ -2588,17 +2576,17 @@ grinder_prefetch_tc_queue_arrays(struct rte_sched_port *port, uint32_t pos) rte_prefetch0(grinder->qbase[0] + qr[0]); rte_prefetch0(grinder->qbase[1] + qr[1]); - grinder_wrr_load(port, pos); - grinder_wrr(port, pos); + grinder_wrr_load(subport, pos); + grinder_wrr(subport, pos); rte_prefetch0(grinder->qbase[2] + qr[2]); rte_prefetch0(grinder->qbase[3] + qr[3]); } static inline void -grinder_prefetch_mbuf(struct rte_sched_port *port, uint32_t pos) +grinder_prefetch_mbuf(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint32_t qpos = grinder->qpos; struct rte_mbuf **qbase = grinder->qbase[qpos]; uint16_t qsize = grinder->qsize; @@ -2617,14 +2605,15 @@ grinder_prefetch_mbuf(struct rte_sched_port *port, uint32_t pos) static inline uint32_t grinder_handle(struct rte_sched_port *port, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_subport *subport = port->subport; + struct rte_sched_grinder *grinder = subport->grinder + pos; switch (grinder->state) { case e_GRINDER_PREFETCH_PIPE: { - if (grinder_next_pipe(port, pos)) { - grinder_prefetch_pipe(port, pos); - port->busy_grinders++; + if (grinder_next_pipe(port, subport, pos)) { + grinder_prefetch_pipe(subport, pos); + subport->busy_grinders++; grinder->state = e_GRINDER_PREFETCH_TC_QUEUE_ARRAYS; return 0; @@ -2637,9 +2626,9 @@ grinder_handle(struct rte_sched_port *port, uint32_t pos) { struct rte_sched_pipe *pipe = grinder->pipe; - grinder->pipe_params = port->pipe_profiles + pipe->profile; - grinder_prefetch_tc_queue_arrays(port, pos); - grinder_credits_update(port, pos); + grinder->pipe_params = subport->pipe_profiles + pipe->profile; + grinder_prefetch_tc_queue_arrays(subport, pos); + grinder_credits_update(port, subport, pos); grinder->state = e_GRINDER_PREFETCH_MBUF; return 0; @@ -2647,7 +2636,7 @@ grinder_handle(struct rte_sched_port *port, uint32_t pos) case e_GRINDER_PREFETCH_MBUF: { - grinder_prefetch_mbuf(port, pos); + grinder_prefetch_mbuf(subport, pos); grinder->state = e_GRINDER_READ_MBUF; return 0; @@ -2657,47 +2646,47 @@ grinder_handle(struct rte_sched_port *port, uint32_t pos) { uint32_t wrr_active, result = 0; - result = grinder_schedule(port, pos); + result = grinder_schedule(port, subport, pos); wrr_active = (grinder->tc_index == RTE_SCHED_TRAFFIC_CLASS_BE); /* Look for next packet within the same TC */ if (result && grinder->qmask) { if (wrr_active) - grinder_wrr(port, pos); + grinder_wrr(subport, pos); - grinder_prefetch_mbuf(port, pos); + grinder_prefetch_mbuf(subport, pos); return 1; } if (wrr_active) - grinder_wrr_store(port, pos); + grinder_wrr_store(subport, pos); /* Look for another active TC within same pipe */ - if (grinder_next_tc(port, pos)) { - grinder_prefetch_tc_queue_arrays(port, pos); + if (grinder_next_tc(port, subport, pos)) { + grinder_prefetch_tc_queue_arrays(subport, pos); grinder->state = e_GRINDER_PREFETCH_MBUF; return result; } if (grinder->productive == 0 && - port->pipe_loop == RTE_SCHED_PIPE_INVALID) - port->pipe_loop = grinder->pindex; + subport->pipe_loop == RTE_SCHED_PIPE_INVALID) + subport->pipe_loop = grinder->pindex; - grinder_evict(port, pos); + grinder_evict(subport, pos); /* Look for another active pipe */ - if (grinder_next_pipe(port, pos)) { - grinder_prefetch_pipe(port, pos); + if (grinder_next_pipe(port, subport, pos)) { + grinder_prefetch_pipe(subport, pos); grinder->state = e_GRINDER_PREFETCH_TC_QUEUE_ARRAYS; return result; } /* No active pipe found */ - port->busy_grinders--; + subport->busy_grinders--; grinder->state = e_GRINDER_PREFETCH_PIPE; return result; -- 2.21.0
Modify scheduler packet dequeue operation to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 51 ++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index d7abe9661..e14506b2d 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -243,6 +243,7 @@ struct rte_sched_port { uint32_t busy_grinders; struct rte_mbuf **pkts_out; uint32_t n_pkts_out; + uint32_t subport_id; /* Queue base calculation */ uint32_t qsize_add[RTE_SCHED_QUEUES_PER_PIPE]; @@ -898,6 +899,7 @@ rte_sched_port_config(struct rte_sched_port_params *params) /* Grinders */ port->pkts_out = NULL; port->n_pkts_out = 0; + port->subport_id = 0; return port; } @@ -2603,9 +2605,9 @@ grinder_prefetch_mbuf(struct rte_sched_subport *subport, uint32_t pos) } static inline uint32_t -grinder_handle(struct rte_sched_port *port, uint32_t pos) +grinder_handle(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_subport *subport = port->subport; struct rte_sched_grinder *grinder = subport->grinder + pos; switch (grinder->state) { @@ -2704,6 +2706,7 @@ rte_sched_port_time_resync(struct rte_sched_port *port) uint64_t cycles = rte_get_tsc_cycles(); uint64_t cycles_diff = cycles - port->time_cpu_cycles; uint64_t bytes_diff; + uint32_t i; /* Compute elapsed time in bytes */ bytes_diff = rte_reciprocal_divide(cycles_diff << RTE_SCHED_TIME_SHIFT, @@ -2716,20 +2719,21 @@ rte_sched_port_time_resync(struct rte_sched_port *port) port->time = port->time_cpu_bytes; /* Reset pipe loop detection */ - port->pipe_loop = RTE_SCHED_PIPE_INVALID; + for (i = 0; i < port->n_subports_per_port; i++) + port->subports[i]->pipe_loop = RTE_SCHED_PIPE_INVALID; } static inline int -rte_sched_port_exceptions(struct rte_sched_port *port, int second_pass) +rte_sched_port_exceptions(struct rte_sched_subport *subport, int second_pass) { int exceptions; /* Check if any exception flag is set */ - exceptions = (second_pass && port->busy_grinders == 0) || - (port->pipe_exhaustion == 1); + exceptions = (second_pass && subport->busy_grinders == 0) || + (subport->pipe_exhaustion == 1); /* Clear exception flags */ - port->pipe_exhaustion = 0; + subport->pipe_exhaustion = 0; return exceptions; } @@ -2737,7 +2741,9 @@ rte_sched_port_exceptions(struct rte_sched_port *port, int second_pass) int rte_sched_port_dequeue(struct rte_sched_port *port, struct rte_mbuf **pkts, uint32_t n_pkts) { - uint32_t i, count; + struct rte_sched_subport *subport; + uint32_t subport_id = port->subport_id; + uint32_t i, n_subports = 0, count; port->pkts_out = pkts; port->n_pkts_out = 0; @@ -2746,9 +2752,32 @@ rte_sched_port_dequeue(struct rte_sched_port *port, struct rte_mbuf **pkts, uint /* Take each queue in the grinder one step further */ for (i = 0, count = 0; ; i++) { - count += grinder_handle(port, i & (RTE_SCHED_PORT_N_GRINDERS - 1)); - if ((count == n_pkts) || - rte_sched_port_exceptions(port, i >= RTE_SCHED_PORT_N_GRINDERS)) { + subport = port->subports[subport_id]; + + count += grinder_handle(port, subport, + i & (RTE_SCHED_PORT_N_GRINDERS - 1)); + + if (count == n_pkts) { + subport_id++; + + if (subport_id == port->n_subports_per_port) + subport_id = 0; + + port->subport_id = subport_id; + break; + } + + if (rte_sched_port_exceptions(subport, i >= RTE_SCHED_PORT_N_GRINDERS)) { + i = 0; + subport_id++; + n_subports++; + } + + if (subport_id == port->n_subports_per_port) + subport_id = 0; + + if (n_subports == port->n_subports_per_port) { + port->subport_id = subport_id; break; } } -- 2.21.0
Modify pipe queue stats read function to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index e14506b2d..1faa580d0 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -282,16 +282,6 @@ enum rte_sched_subport_array { e_RTE_SCHED_SUBPORT_ARRAY_TOTAL, }; -#ifdef RTE_SCHED_COLLECT_STATS - -static inline uint32_t -rte_sched_port_queues_per_subport(struct rte_sched_port *port) -{ - return RTE_SCHED_QUEUES_PER_PIPE * port->n_pipes_per_subport; -} - -#endif - static inline uint32_t rte_sched_subport_pipe_queues(struct rte_sched_subport *subport) { @@ -320,7 +310,12 @@ struct rte_sched_subport *subport, uint32_t qindex) static inline uint32_t rte_sched_port_queues_per_port(struct rte_sched_port *port) { - return RTE_SCHED_QUEUES_PER_PIPE * port->n_pipes_per_subport * port->n_subports_per_port; + uint32_t n_queues = 0, i; + + for (i = 0; i < port->n_subports_per_port; i++) + n_queues += rte_sched_subport_pipe_queues(port->subports[i]); + + return n_queues; } static inline uint16_t @@ -1474,8 +1469,10 @@ rte_sched_queue_read_stats(struct rte_sched_port *port, struct rte_sched_queue_stats *stats, uint16_t *qlen) { + struct rte_sched_subport *s; struct rte_sched_queue *q; struct rte_sched_queue_extra *qe; + uint32_t subport_id, subport_qmask, subport_qindex; /* Check user parameters */ if (port == NULL) { @@ -1501,8 +1498,13 @@ rte_sched_queue_read_stats(struct rte_sched_port *port, "%s: Incorrect value for parameter qlen\n", __func__); return -EINVAL; } - q = port->queue + queue_id; - qe = port->queue_extra + queue_id; + subport_qmask = port->n_pipes_per_subport_log2 + 4; + subport_id = (queue_id >> subport_qmask) & (port->n_subports_per_port - 1); + + s = port->subports[subport_id]; + subport_qindex = ((1 << subport_qmask) - 1) & queue_id; + q = s->queue + subport_qindex; + qe = s->queue_extra + subport_qindex; /* Copy queue stats and clear */ memcpy(stats, &qe->stats, sizeof(struct rte_sched_queue_stats)); -- 2.21.0
Modify tests function to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- app/test/test_sched.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/app/test/test_sched.c b/app/test/test_sched.c index afe0b0765..fc31080ef 100644 --- a/app/test/test_sched.c +++ b/app/test/test_sched.c @@ -22,18 +22,6 @@ #define TC 2 #define QUEUE 0 -static struct rte_sched_subport_params subport_param[] = { - { - .tb_rate = 1250000000, - .tb_size = 1000000, - - .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000, - 1250000000, 1250000000, 1250000000, 1250000000, 1250000000, - 1250000000, 1250000000, 1250000000, 1250000000}, - .tc_period = 10, - }, -}; - static struct rte_sched_pipe_params pipe_profile[] = { { /* Profile #0 */ .tb_rate = 305175, @@ -48,6 +36,23 @@ static struct rte_sched_pipe_params pipe_profile[] = { }, }; +static struct rte_sched_subport_params subport_param[] = { + { + .tb_rate = 1250000000, + .tb_size = 1000000, + + .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000, + 1250000000, 1250000000, 1250000000, 1250000000, 1250000000, + 1250000000, 1250000000, 1250000000, 1250000000}, + .tc_period = 10, + .n_pipes_per_subport_enabled = 1024, + .qsize = {32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}, + .pipe_profiles = pipe_profile, + .n_pipe_profiles = 1, + .n_max_pipe_profiles = 1, + }, +}; + static struct rte_sched_port_params port_param = { .socket = 0, /* computed */ .rate = 0, /* computed */ @@ -55,10 +60,6 @@ static struct rte_sched_port_params port_param = { .frame_overhead = RTE_SCHED_FRAME_OVERHEAD_DEFAULT, .n_subports_per_port = 1, .n_pipes_per_subport = 1024, - .qsize = {32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}, - .pipe_profiles = pipe_profile, - .n_pipe_profiles = 1, - .n_max_pipe_profiles = 1, }; #define NB_MBUF 32 @@ -140,7 +141,7 @@ test_sched(void) err = rte_sched_subport_config(port, SUBPORT, subport_param); TEST_ASSERT_SUCCESS(err, "Error config sched, err=%d\n", err); - for (pipe = 0; pipe < port_param.n_pipes_per_subport; pipe ++) { + for (pipe = 0; pipe < subport_param[0].n_pipes_per_subport_enabled; pipe++) { err = rte_sched_pipe_config(port, SUBPORT, pipe, 0); TEST_ASSERT_SUCCESS(err, "Error config sched pipe %u, err=%d\n", pipe, err); } -- 2.21.0
Modify softnic traffic management function to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- drivers/net/softnic/rte_eth_softnic_tm.c | 54 ++++++++++++------------ 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/drivers/net/softnic/rte_eth_softnic_tm.c b/drivers/net/softnic/rte_eth_softnic_tm.c index 61c3adc82..80a470c9e 100644 --- a/drivers/net/softnic/rte_eth_softnic_tm.c +++ b/drivers/net/softnic/rte_eth_softnic_tm.c @@ -85,7 +85,8 @@ softnic_tmgr_port_create(struct pmd_internals *p, /* Subport */ n_subports = t->port_params.n_subports_per_port; for (subport_id = 0; subport_id < n_subports; subport_id++) { - uint32_t n_pipes_per_subport = t->port_params.n_pipes_per_subport; + uint32_t n_pipes_per_subport = + t->subport_params[subport_id].n_pipes_per_subport_enabled; uint32_t pipe_id; int status; @@ -2211,10 +2212,11 @@ tm_tc_wred_profile_get(struct rte_eth_dev *dev, uint32_t tc_id) #ifdef RTE_SCHED_RED static void -wred_profiles_set(struct rte_eth_dev *dev) +wred_profiles_set(struct rte_eth_dev *dev, uint32_t subport_id) { struct pmd_internals *p = dev->data->dev_private; - struct rte_sched_port_params *pp = &p->soft.tm.params.port_params; + struct rte_sched_subport_params *pp = + &p->soft.tm.params.subport_params[subport_id]; uint32_t tc_id; enum rte_color color; @@ -2234,7 +2236,7 @@ wred_profiles_set(struct rte_eth_dev *dev) #else -#define wred_profiles_set(dev) +#define wred_profiles_set(dev, subport_id) #endif @@ -2526,29 +2528,9 @@ hierarchy_blueprints_create(struct rte_eth_dev *dev) .frame_overhead = root->shaper_profile->params.pkt_length_adjust, .n_subports_per_port = root->n_children, - .n_pipes_per_subport = h->n_tm_nodes[TM_NODE_LEVEL_PIPE] / - h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT], - .qsize = {p->params.tm.qsize[0], - p->params.tm.qsize[1], - p->params.tm.qsize[2], - p->params.tm.qsize[3], - p->params.tm.qsize[4], - p->params.tm.qsize[5], - p->params.tm.qsize[6], - p->params.tm.qsize[7], - p->params.tm.qsize[8], - p->params.tm.qsize[9], - p->params.tm.qsize[10], - p->params.tm.qsize[11], - p->params.tm.qsize[12], - }, - .pipe_profiles = t->pipe_profiles, - .n_pipe_profiles = t->n_pipe_profiles, - .n_max_pipe_profiles = TM_MAX_PIPE_PROFILE, + .n_pipes_per_subport = TM_MAX_PIPES_PER_SUBPORT, }; - wred_profiles_set(dev); - subport_id = 0; TAILQ_FOREACH(n, nl, node) { uint64_t tc_rate[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; @@ -2588,8 +2570,28 @@ hierarchy_blueprints_create(struct rte_eth_dev *dev) tc_rate[12], }, .tc_period = SUBPORT_TC_PERIOD, + .n_pipes_per_subport_enabled = + h->n_tm_nodes[TM_NODE_LEVEL_PIPE] / + h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT], + .qsize = {p->params.tm.qsize[0], + p->params.tm.qsize[1], + p->params.tm.qsize[2], + p->params.tm.qsize[3], + p->params.tm.qsize[4], + p->params.tm.qsize[5], + p->params.tm.qsize[6], + p->params.tm.qsize[7], + p->params.tm.qsize[8], + p->params.tm.qsize[9], + p->params.tm.qsize[10], + p->params.tm.qsize[11], + p->params.tm.qsize[12], + }, + .pipe_profiles = t->pipe_profiles, + .n_pipe_profiles = t->n_pipe_profiles, + .n_max_pipe_profiles = TM_MAX_PIPE_PROFILE, }; - + wred_profiles_set(dev, subport_id); subport_id++; } } -- 2.21.0
Modify ip pipeline traffic management function to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- examples/ip_pipeline/cli.c | 71 ++++++++++++++++++------------------- examples/ip_pipeline/tmgr.c | 25 +++++++------ examples/ip_pipeline/tmgr.h | 7 ++-- 3 files changed, 51 insertions(+), 52 deletions(-) diff --git a/examples/ip_pipeline/cli.c b/examples/ip_pipeline/cli.c index 02dc11495..c72030682 100644 --- a/examples/ip_pipeline/cli.c +++ b/examples/ip_pipeline/cli.c @@ -393,7 +393,12 @@ static const char cmd_tmgr_subport_profile_help[] = " <tc0_rate> <tc1_rate> <tc2_rate> <tc3_rate> <tc4_rate>" " <tc5_rate> <tc6_rate> <tc7_rate> <tc8_rate>" " <tc9_rate> <tc10_rate> <tc11_rate> <tc12_rate>\n" -" <tc_period>\n"; +" <tc_period>\n" +" pps <n_pipes_per_subport>\n" +" qsize <qsize_tc0> <qsize_tc1> <qsize_tc2>" +" <qsize_tc3> <qsize_tc4> <qsize_tc5> <qsize_tc6>" +" <qsize_tc7> <qsize_tc8> <qsize_tc9> <qsize_tc10>" +" <qsize_tc11> <qsize_tc12>"; static void cmd_tmgr_subport_profile(char **tokens, @@ -404,7 +409,7 @@ cmd_tmgr_subport_profile(char **tokens, struct rte_sched_subport_params p; int status, i; - if (n_tokens != 19) { + if (n_tokens != 35) { snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); return; } @@ -430,6 +435,27 @@ cmd_tmgr_subport_profile(char **tokens, return; } + if (strcmp(tokens[19], "pps") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps"); + return; + } + + if (parser_read_uint32(&p.n_pipes_per_subport_enabled, tokens[20]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "n_pipes_per_subport"); + return; + } + + if (strcmp(tokens[21], "qsize") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "qsize"); + return; + } + + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) + if (parser_read_uint16(&p.qsize[i], tokens[22 + i]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "qsize"); + return; + } + status = tmgr_subport_profile_add(&p); if (status != 0) { snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); @@ -504,11 +530,6 @@ static const char cmd_tmgr_help[] = "tmgr <tmgr_name>\n" " rate <rate>\n" " spp <n_subports_per_port>\n" -" pps <n_pipes_per_subport>\n" -" qsize <qsize_tc0> <qsize_tc1> <qsize_tc2>" -" <qsize_tc3> <qsize_tc4> <qsize_tc5> <qsize_tc6>" -" <qsize_tc7> <qsize_tc8> <qsize_tc9> <qsize_tc10>" -" <qsize_tc11> <qsize_tc12>\n" " fo <frame_overhead>\n" " mtu <mtu>\n" " cpu <cpu_id>\n"; @@ -522,9 +543,8 @@ cmd_tmgr(char **tokens, struct tmgr_port_params p; char *name; struct tmgr_port *tmgr_port; - int i; - if (n_tokens != 28) { + if (n_tokens != 12) { snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); return; } @@ -551,53 +571,32 @@ cmd_tmgr(char **tokens, return; } - if (strcmp(tokens[6], "pps") != 0) { - snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps"); - return; - } - - if (parser_read_uint32(&p.n_pipes_per_subport, tokens[7]) != 0) { - snprintf(out, out_size, MSG_ARG_INVALID, "n_pipes_per_subport"); - return; - } - - if (strcmp(tokens[8], "qsize") != 0) { - snprintf(out, out_size, MSG_ARG_NOT_FOUND, "qsize"); - return; - } - - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - if (parser_read_uint16(&p.qsize[i], tokens[9 + i]) != 0) { - snprintf(out, out_size, MSG_ARG_INVALID, "qsize"); - return; - } - - if (strcmp(tokens[22], "fo") != 0) { + if (strcmp(tokens[6], "fo") != 0) { snprintf(out, out_size, MSG_ARG_NOT_FOUND, "fo"); return; } - if (parser_read_uint32(&p.frame_overhead, tokens[23]) != 0) { + if (parser_read_uint32(&p.frame_overhead, tokens[7]) != 0) { snprintf(out, out_size, MSG_ARG_INVALID, "frame_overhead"); return; } - if (strcmp(tokens[24], "mtu") != 0) { + if (strcmp(tokens[8], "mtu") != 0) { snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mtu"); return; } - if (parser_read_uint32(&p.mtu, tokens[25]) != 0) { + if (parser_read_uint32(&p.mtu, tokens[9]) != 0) { snprintf(out, out_size, MSG_ARG_INVALID, "mtu"); return; } - if (strcmp(tokens[26], "cpu") != 0) { + if (strcmp(tokens[10], "cpu") != 0) { snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu"); return; } - if (parser_read_uint32(&p.cpu_id, tokens[27]) != 0) { + if (parser_read_uint32(&p.cpu_id, tokens[11]) != 0) { snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id"); return; } diff --git a/examples/ip_pipeline/tmgr.c b/examples/ip_pipeline/tmgr.c index 40cbf1d0a..91ccbf60f 100644 --- a/examples/ip_pipeline/tmgr.c +++ b/examples/ip_pipeline/tmgr.c @@ -47,7 +47,8 @@ int tmgr_subport_profile_add(struct rte_sched_subport_params *p) { /* Check input params */ - if (p == NULL) + if (p == NULL || + p->n_pipes_per_subport_enabled == 0) return -1; /* Save profile */ @@ -90,7 +91,6 @@ tmgr_port_create(const char *name, struct tmgr_port_params *params) tmgr_port_find(name) || (params == NULL) || (params->n_subports_per_port == 0) || - (params->n_pipes_per_subport == 0) || (params->cpu_id >= RTE_MAX_NUMA_NODES) || (n_subport_profiles == 0) || (n_pipe_profiles == 0)) @@ -103,18 +103,16 @@ tmgr_port_create(const char *name, struct tmgr_port_params *params) p.mtu = params->mtu; p.frame_overhead = params->frame_overhead; p.n_subports_per_port = params->n_subports_per_port; - p.n_pipes_per_subport = params->n_pipes_per_subport; - - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - p.qsize[i] = params->qsize[i]; - - p.pipe_profiles = pipe_profile; - p.n_pipe_profiles = n_pipe_profiles; + p.n_pipes_per_subport = TMGR_PIPE_SUBPORT_MAX; s = rte_sched_port_config(&p); if (s == NULL) return NULL; + subport_profile[0].pipe_profiles = pipe_profile; + subport_profile[0].n_pipe_profiles = n_pipe_profiles; + subport_profile[0].n_max_pipe_profiles = TMGR_PIPE_PROFILE_MAX; + for (i = 0; i < params->n_subports_per_port; i++) { int status; @@ -128,7 +126,7 @@ tmgr_port_create(const char *name, struct tmgr_port_params *params) return NULL; } - for (j = 0; j < params->n_pipes_per_subport; j++) { + for (j = 0; j < subport_profile[0].n_pipes_per_subport_enabled; j++) { status = rte_sched_pipe_config( s, i, @@ -153,7 +151,6 @@ tmgr_port_create(const char *name, struct tmgr_port_params *params) strlcpy(tmgr_port->name, name, sizeof(tmgr_port->name)); tmgr_port->s = s; tmgr_port->n_subports_per_port = params->n_subports_per_port; - tmgr_port->n_pipes_per_subport = params->n_pipes_per_subport; /* Node add to list */ TAILQ_INSERT_TAIL(&tmgr_port_list, tmgr_port, node); @@ -205,8 +202,10 @@ tmgr_pipe_config(const char *port_name, port = tmgr_port_find(port_name); if ((port == NULL) || (subport_id >= port->n_subports_per_port) || - (pipe_id_first >= port->n_pipes_per_subport) || - (pipe_id_last >= port->n_pipes_per_subport) || + (pipe_id_first >= + subport_profile[subport_id].n_pipes_per_subport_enabled) || + (pipe_id_last >= + subport_profile[subport_id].n_pipes_per_subport_enabled) || (pipe_id_first > pipe_id_last) || (pipe_profile_id >= n_pipe_profiles)) return -1; diff --git a/examples/ip_pipeline/tmgr.h b/examples/ip_pipeline/tmgr.h index 8703a2e00..1fcf66ee1 100644 --- a/examples/ip_pipeline/tmgr.h +++ b/examples/ip_pipeline/tmgr.h @@ -12,6 +12,10 @@ #include "common.h" +#ifndef TMGR_PIPE_SUBPORT_MAX +#define TMGR_PIPE_SUBPORT_MAX 4096 +#endif + #ifndef TMGR_SUBPORT_PROFILE_MAX #define TMGR_SUBPORT_PROFILE_MAX 256 #endif @@ -25,7 +29,6 @@ struct tmgr_port { char name[NAME_SIZE]; struct rte_sched_port *s; uint32_t n_subports_per_port; - uint32_t n_pipes_per_subport; }; TAILQ_HEAD(tmgr_port_list, tmgr_port); @@ -42,8 +45,6 @@ struct tmgr_port_params { uint32_t frame_overhead; uint32_t mtu; uint32_t cpu_id; - uint32_t n_pipes_per_subport; - uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; }; int -- 2.21.0
Modify qos sample app to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- examples/qos_sched/app_thread.c | 20 ++- examples/qos_sched/cfg_file.c | 229 ++++++++++++++++-------------- examples/qos_sched/init.c | 54 +++---- examples/qos_sched/main.h | 1 + examples/qos_sched/profile.cfg | 5 +- examples/qos_sched/profile_ov.cfg | 5 +- examples/qos_sched/stats.c | 44 +++--- 7 files changed, 203 insertions(+), 155 deletions(-) diff --git a/examples/qos_sched/app_thread.c b/examples/qos_sched/app_thread.c index 18b734a14..dbc878b55 100644 --- a/examples/qos_sched/app_thread.c +++ b/examples/qos_sched/app_thread.c @@ -35,15 +35,25 @@ get_pkt_sched(struct rte_mbuf *m, uint32_t *subport, uint32_t *pipe, uint16_t *pdata = rte_pktmbuf_mtod(m, uint16_t *); uint16_t pipe_queue; + /* Outer VLAN ID*/ *subport = (rte_be_to_cpu_16(pdata[SUBPORT_OFFSET]) & 0x0FFF) & - (port_params.n_subports_per_port - 1); /* Outer VLAN ID*/ + (port_params.n_subports_per_port - 1); + + /* Inner VLAN ID */ *pipe = (rte_be_to_cpu_16(pdata[PIPE_OFFSET]) & 0x0FFF) & - (port_params.n_pipes_per_subport - 1); /* Inner VLAN ID */ + (subport_params[*subport].n_pipes_per_subport_enabled - 1); + pipe_queue = active_queues[(pdata[QUEUE_OFFSET] >> 8) % n_active_queues]; + + /* Traffic class (Destination IP) */ *traffic_class = pipe_queue > RTE_SCHED_TRAFFIC_CLASS_BE ? - RTE_SCHED_TRAFFIC_CLASS_BE : pipe_queue; /* Destination IP */ - *queue = pipe_queue - *traffic_class; /* Destination IP */ - *color = pdata[COLOR_OFFSET] & 0x03; /* Destination IP */ + RTE_SCHED_TRAFFIC_CLASS_BE : pipe_queue; + + /* Traffic class queue (Destination IP) */ + *queue = pipe_queue - *traffic_class; + + /* Color (Destination IP) */ + *color = pdata[COLOR_OFFSET] & 0x03; return 0; } diff --git a/examples/qos_sched/cfg_file.c b/examples/qos_sched/cfg_file.c index 45bf599e4..c6d3f5ab6 100644 --- a/examples/qos_sched/cfg_file.c +++ b/examples/qos_sched/cfg_file.c @@ -24,14 +24,10 @@ int cfg_load_port(struct rte_cfgfile *cfg, struct rte_sched_port_params *port_params) { const char *entry; - int j; if (!cfg || !port_params) return -1; - memset(active_queues, 0, sizeof(active_queues)); - n_active_queues = 0; - entry = rte_cfgfile_get_entry(cfg, "port", "frame overhead"); if (entry) port_params->frame_overhead = (uint32_t)atoi(entry); @@ -40,106 +36,6 @@ cfg_load_port(struct rte_cfgfile *cfg, struct rte_sched_port_params *port_params if (entry) port_params->n_subports_per_port = (uint32_t)atoi(entry); - entry = rte_cfgfile_get_entry(cfg, "port", "number of pipes per subport"); - if (entry) - port_params->n_pipes_per_subport = (uint32_t)atoi(entry); - - entry = rte_cfgfile_get_entry(cfg, "port", "queue sizes"); - if (entry) { - char *next; - - for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { - port_params->qsize[j] = (uint16_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - - for (j = 0; j < RTE_SCHED_TRAFFIC_CLASS_BE; j++) - if (port_params->qsize[j]) { - active_queues[n_active_queues] = j; - n_active_queues++; - } - - if (port_params->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]) - for (j = 0; j < RTE_SCHED_BE_QUEUES_PER_PIPE; j++) { - active_queues[n_active_queues] = - RTE_SCHED_TRAFFIC_CLASS_BE + j; - n_active_queues++; - } - } - -#ifdef RTE_SCHED_RED - for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { - char str[32]; - - /* Parse WRED min thresholds */ - snprintf(str, sizeof(str), "tc %d wred min", j); - entry = rte_cfgfile_get_entry(cfg, "red", str); - if (entry) { - char *next; - int k; - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < RTE_COLORS; k++) { - port_params->red_params[j][k].min_th - = (uint16_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - } - - /* Parse WRED max thresholds */ - snprintf(str, sizeof(str), "tc %d wred max", j); - entry = rte_cfgfile_get_entry(cfg, "red", str); - if (entry) { - char *next; - int k; - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < RTE_COLORS; k++) { - port_params->red_params[j][k].max_th - = (uint16_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - } - - /* Parse WRED inverse mark probabilities */ - snprintf(str, sizeof(str), "tc %d wred inv prob", j); - entry = rte_cfgfile_get_entry(cfg, "red", str); - if (entry) { - char *next; - int k; - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < RTE_COLORS; k++) { - port_params->red_params[j][k].maxp_inv - = (uint8_t)strtol(entry, &next, 10); - - if (next == NULL) - break; - entry = next; - } - } - - /* Parse WRED EWMA filter weights */ - snprintf(str, sizeof(str), "tc %d wred weight", j); - entry = rte_cfgfile_get_entry(cfg, "red", str); - if (entry) { - char *next; - int k; - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < RTE_COLORS; k++) { - port_params->red_params[j][k].wq_log2 - = (uint8_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - } - } -#endif /* RTE_SCHED_RED */ - return 0; } @@ -155,7 +51,7 @@ cfg_load_pipe(struct rte_cfgfile *cfg, struct rte_sched_pipe_params *pipe_params return -1; profiles = rte_cfgfile_num_sections(cfg, "pipe profile", sizeof("pipe profile") - 1); - port_params.n_pipe_profiles = profiles; + subport_params[0].n_pipe_profiles = profiles; for (j = 0; j < profiles; j++) { char pipe_name[32]; @@ -253,12 +149,121 @@ cfg_load_subport(struct rte_cfgfile *cfg, struct rte_sched_subport_params *subpo return -1; memset(app_pipe_to_profile, -1, sizeof(app_pipe_to_profile)); + memset(active_queues, 0, sizeof(active_queues)); + n_active_queues = 0; + +#ifdef RTE_SCHED_RED + char sec_name[CFG_NAME_LEN]; + struct rte_red_params red_params[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; + + snprintf(sec_name, sizeof(sec_name), "red"); + + if (rte_cfgfile_has_section(cfg, sec_name)) { + + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + char str[32]; + + /* Parse WRED min thresholds */ + snprintf(str, sizeof(str), "tc %d wred min", i); + entry = rte_cfgfile_get_entry(cfg, sec_name, str); + if (entry) { + char *next; + /* for each packet colour (green, yellow, red) */ + for (j = 0; j < RTE_COLORS; j++) { + red_params[i][j].min_th + = (uint16_t)strtol(entry, &next, 10); + if (next == NULL) + break; + entry = next; + } + } + + /* Parse WRED max thresholds */ + snprintf(str, sizeof(str), "tc %d wred max", i); + entry = rte_cfgfile_get_entry(cfg, "red", str); + if (entry) { + char *next; + /* for each packet colour (green, yellow, red) */ + for (j = 0; j < RTE_COLORS; j++) { + red_params[i][j].max_th + = (uint16_t)strtol(entry, &next, 10); + if (next == NULL) + break; + entry = next; + } + } + + /* Parse WRED inverse mark probabilities */ + snprintf(str, sizeof(str), "tc %d wred inv prob", i); + entry = rte_cfgfile_get_entry(cfg, "red", str); + if (entry) { + char *next; + /* for each packet colour (green, yellow, red) */ + for (j = 0; j < RTE_COLORS; j++) { + red_params[i][j].maxp_inv + = (uint8_t)strtol(entry, &next, 10); + + if (next == NULL) + break; + entry = next; + } + } + + /* Parse WRED EWMA filter weights */ + snprintf(str, sizeof(str), "tc %d wred weight", i); + entry = rte_cfgfile_get_entry(cfg, "red", str); + if (entry) { + char *next; + /* for each packet colour (green, yellow, red) */ + for (j = 0; j < RTE_COLORS; j++) { + red_params[i][j].wq_log2 + = (uint8_t)strtol(entry, &next, 10); + if (next == NULL) + break; + entry = next; + } + } + } + } +#endif /* RTE_SCHED_RED */ for (i = 0; i < MAX_SCHED_SUBPORTS; i++) { char sec_name[CFG_NAME_LEN]; snprintf(sec_name, sizeof(sec_name), "subport %d", i); if (rte_cfgfile_has_section(cfg, sec_name)) { + entry = rte_cfgfile_get_entry(cfg, sec_name, + "number of pipes per subport"); + if (entry) + subport_params[i].n_pipes_per_subport_enabled = + (uint32_t)atoi(entry); + + entry = rte_cfgfile_get_entry(cfg, sec_name, "queue sizes"); + if (entry) { + char *next; + + for (j = 0; j < RTE_SCHED_TRAFFIC_CLASS_BE; j++) { + subport_params[i].qsize[j] = + (uint16_t)strtol(entry, &next, 10); + if (subport_params[i].qsize[j] != 0) { + active_queues[n_active_queues] = j; + n_active_queues++; + } + if (next == NULL) + break; + entry = next; + } + + subport_params[i].qsize[RTE_SCHED_TRAFFIC_CLASS_BE] = + (uint16_t)strtol(entry, &next, 10); + + for (j = 0; j < RTE_SCHED_BE_QUEUES_PER_PIPE; j++) { + active_queues[n_active_queues] = + RTE_SCHED_TRAFFIC_CLASS_BE + j; + n_active_queues++; + } + } + entry = rte_cfgfile_get_entry(cfg, sec_name, "tb rate"); if (entry) subport_params[i].tb_rate = (uint32_t)atoi(entry); @@ -362,6 +367,20 @@ cfg_load_subport(struct rte_cfgfile *cfg, struct rte_sched_subport_params *subpo } } } +#ifdef RTE_SCHED_RED + for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { + for (k = 0; k < RTE_COLORS; k++) { + subport_params[i].red_params[j][k].min_th = + red_params[j][k].min_th; + subport_params[i].red_params[j][k].max_th = + red_params[j][k].max_th; + subport_params[i].red_params[j][k].maxp_inv = + red_params[j][k].maxp_inv; + subport_params[i].red_params[j][k].wq_log2 = + red_params[j][k].wq_log2; + } + } +#endif } } diff --git a/examples/qos_sched/init.c b/examples/qos_sched/init.c index 32e6e1ba2..0a17e0d4d 100644 --- a/examples/qos_sched/init.c +++ b/examples/qos_sched/init.c @@ -180,18 +180,6 @@ app_init_port(uint16_t portid, struct rte_mempool *mp) return 0; } -static struct rte_sched_subport_params subport_params[MAX_SCHED_SUBPORTS] = { - { - .tb_rate = 1250000000, - .tb_size = 1000000, - - .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000, - 1250000000, 1250000000, 1250000000, 1250000000, 1250000000, - 1250000000, 1250000000, 1250000000, 1250000000}, - .tc_period = 10, - }, -}; - static struct rte_sched_pipe_params pipe_profiles[MAX_SCHED_PIPE_PROFILES] = { { /* Profile #0 */ .tb_rate = 305175, @@ -208,19 +196,21 @@ static struct rte_sched_pipe_params pipe_profiles[MAX_SCHED_PIPE_PROFILES] = { }, }; -struct rte_sched_port_params port_params = { - .name = "port_scheduler_0", - .socket = 0, /* computed */ - .rate = 0, /* computed */ - .mtu = 6 + 6 + 4 + 4 + 2 + 1500, - .frame_overhead = RTE_SCHED_FRAME_OVERHEAD_DEFAULT, - .n_subports_per_port = 1, - .n_pipes_per_subport = 4096, - .qsize = {64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}, - .pipe_profiles = pipe_profiles, - .n_pipe_profiles = sizeof(pipe_profiles) / sizeof(struct rte_sched_pipe_params), - .n_max_pipe_profiles = MAX_SCHED_PIPE_PROFILES, +struct rte_sched_subport_params subport_params[MAX_SCHED_SUBPORTS] = { + { + .tb_rate = 1250000000, + .tb_size = 1000000, + .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000, + 1250000000, 1250000000, 1250000000, 1250000000, 1250000000, + 1250000000, 1250000000, 1250000000, 1250000000}, + .tc_period = 10, + .n_pipes_per_subport_enabled = 4096, + .qsize = {64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}, + .pipe_profiles = pipe_profiles, + .n_pipe_profiles = sizeof(pipe_profiles) / + sizeof(struct rte_sched_pipe_params), + .n_max_pipe_profiles = MAX_SCHED_PIPE_PROFILES, #ifdef RTE_SCHED_RED .red_params = { /* Traffic Class 0 Colors Green / Yellow / Red */ @@ -289,6 +279,17 @@ struct rte_sched_port_params port_params = { [12][2] = {.min_th = 32, .max_th = 64, .maxp_inv = 10, .wq_log2 = 9}, }, #endif /* RTE_SCHED_RED */ + }, +}; + +struct rte_sched_port_params port_params = { + .name = "port_scheduler_0", + .socket = 0, /* computed */ + .rate = 0, /* computed */ + .mtu = 6 + 6 + 4 + 4 + 2 + 1500, + .frame_overhead = RTE_SCHED_FRAME_OVERHEAD_DEFAULT, + .n_subports_per_port = 1, + .n_pipes_per_subport = MAX_SCHED_PIPES, }; static struct rte_sched_port * @@ -323,7 +324,10 @@ app_init_sched_port(uint32_t portid, uint32_t socketid) subport, err); } - for (pipe = 0; pipe < port_params.n_pipes_per_subport; pipe++) { + uint32_t n_pipes_per_subport = + subport_params[subport].n_pipes_per_subport_enabled; + + for (pipe = 0; pipe < n_pipes_per_subport; pipe++) { if (app_pipe_to_profile[subport][pipe] != -1) { err = rte_sched_pipe_config(port, subport, pipe, app_pipe_to_profile[subport][pipe]); diff --git a/examples/qos_sched/main.h b/examples/qos_sched/main.h index d8f890b64..baa2b3ead 100644 --- a/examples/qos_sched/main.h +++ b/examples/qos_sched/main.h @@ -152,6 +152,7 @@ uint32_t active_queues[RTE_SCHED_QUEUES_PER_PIPE]; uint32_t n_active_queues; extern struct rte_sched_port_params port_params; +extern struct rte_sched_subport_params subport_params[MAX_SCHED_SUBPORTS]; int app_parse_args(int argc, char **argv); int app_init(void); diff --git a/examples/qos_sched/profile.cfg b/examples/qos_sched/profile.cfg index 335561370..61b8b7071 100644 --- a/examples/qos_sched/profile.cfg +++ b/examples/qos_sched/profile.cfg @@ -20,11 +20,12 @@ [port] frame overhead = 24 number of subports per port = 1 -number of pipes per subport = 4096 -queue sizes = 64 64 64 64 64 64 64 64 64 64 64 64 64 ; Subport configuration [subport 0] +number of pipes per subport = 4096 +queue sizes = 64 64 64 64 64 64 64 64 64 64 64 64 64 + tb rate = 1250000000 ; Bytes per second tb size = 1000000 ; Bytes diff --git a/examples/qos_sched/profile_ov.cfg b/examples/qos_sched/profile_ov.cfg index 394987399..ab509d28d 100644 --- a/examples/qos_sched/profile_ov.cfg +++ b/examples/qos_sched/profile_ov.cfg @@ -5,11 +5,12 @@ [port] frame overhead = 24 number of subports per port = 1 -number of pipes per subport = 32 -queue sizes = 64 64 64 64 64 64 64 64 64 64 64 64 64 ; Subport configuration [subport 0] +number of pipes per subport = 32 +queue sizes = 64 64 64 64 64 64 64 64 64 64 64 64 64 + tb rate = 8400000 ; Bytes per second tb size = 100000 ; Bytes diff --git a/examples/qos_sched/stats.c b/examples/qos_sched/stats.c index e62e4a2f6..ce34b6c7c 100644 --- a/examples/qos_sched/stats.c +++ b/examples/qos_sched/stats.c @@ -24,7 +24,7 @@ qavg_q(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id, uint8_t tc, if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || - pipe_id >= port_params.n_pipes_per_subport || + pipe_id >= subport_params[subport_id].n_pipes_per_subport_enabled || tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE || q >= RTE_SCHED_BE_QUEUES_PER_PIPE || (tc < RTE_SCHED_TRAFFIC_CLASS_BE && q > 0)) @@ -32,7 +32,7 @@ qavg_q(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id, uint8_t tc, port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - queue_id += port_params.n_pipes_per_subport * + queue_id += subport_params[i].n_pipes_per_subport_enabled * RTE_SCHED_QUEUES_PER_PIPE; if (tc < RTE_SCHED_TRAFFIC_CLASS_BE) queue_id += pipe_id * RTE_SCHED_QUEUES_PER_PIPE + tc; @@ -69,14 +69,16 @@ qavg_tcpipe(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id, } if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || - pipe_id >= port_params.n_pipes_per_subport || + pipe_id >= subport_params[subport_id].n_pipes_per_subport_enabled || tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE) return -1; port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - queue_id += port_params.n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; + queue_id += + subport_params[i].n_pipes_per_subport_enabled * + RTE_SCHED_QUEUES_PER_PIPE; queue_id += pipe_id * RTE_SCHED_QUEUES_PER_PIPE + tc; @@ -123,13 +125,13 @@ qavg_pipe(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id) if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || - pipe_id >= port_params.n_pipes_per_subport) + pipe_id >= subport_params[subport_id].n_pipes_per_subport_enabled) return -1; port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - queue_id += port_params.n_pipes_per_subport * + queue_id += subport_params[i].n_pipes_per_subport_enabled * RTE_SCHED_QUEUES_PER_PIPE; queue_id += pipe_id * RTE_SCHED_QUEUES_PER_PIPE; @@ -177,13 +179,17 @@ qavg_tcsubport(uint16_t port_id, uint32_t subport_id, uint8_t tc) for (i = 0; i < subport_id; i++) subport_queue_id += - port_params.n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; + subport_params[i].n_pipes_per_subport_enabled * + RTE_SCHED_QUEUES_PER_PIPE; average = 0; for (count = 0; count < qavg_ntimes; count++) { + uint32_t n_pipes_per_subport = + subport_params[subport_id].n_pipes_per_subport_enabled; + part_average = 0; - for (i = 0; i < port_params.n_pipes_per_subport; i++) { + for (i = 0; i < n_pipes_per_subport; i++) { if (tc < RTE_SCHED_TRAFFIC_CLASS_BE) { queue_id = subport_queue_id + i * RTE_SCHED_QUEUES_PER_PIPE + tc; @@ -203,10 +209,11 @@ qavg_tcsubport(uint16_t port_id, uint32_t subport_id, uint8_t tc) } if (tc < RTE_SCHED_TRAFFIC_CLASS_BE) - average += part_average / (port_params.n_pipes_per_subport); + average += part_average / + (subport_params[subport_id].n_pipes_per_subport_enabled); else - average += - part_average / (port_params.n_pipes_per_subport) * + average += part_average / + (subport_params[subport_id].n_pipes_per_subport_enabled) * RTE_SCHED_BE_QUEUES_PER_PIPE; usleep(qavg_period); @@ -240,14 +247,17 @@ qavg_subport(uint16_t port_id, uint32_t subport_id) port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - subport_queue_id += port_params.n_pipes_per_subport * + subport_queue_id += subport_params[i].n_pipes_per_subport_enabled * RTE_SCHED_QUEUES_PER_PIPE; average = 0; for (count = 0; count < qavg_ntimes; count++) { + uint32_t n_pipes_per_subport = + subport_params[subport_id].n_pipes_per_subport_enabled; + part_average = 0; - for (i = 0; i < port_params.n_pipes_per_subport; i++) { + for (i = 0; i < n_pipes_per_subport; i++) { queue_id = subport_queue_id + i * RTE_SCHED_QUEUES_PER_PIPE; for (j = 0; j < RTE_SCHED_QUEUES_PER_PIPE; j++) { @@ -258,7 +268,8 @@ qavg_subport(uint16_t port_id, uint32_t subport_id) } average += part_average / - (port_params.n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE); + (subport_params[subport_id].n_pipes_per_subport_enabled * + RTE_SCHED_QUEUES_PER_PIPE); usleep(qavg_period); } @@ -322,12 +333,13 @@ pipe_stat(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id) if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || - pipe_id >= port_params.n_pipes_per_subport) + pipe_id >= subport_params[subport_id].n_pipes_per_subport_enabled) return -1; port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - queue_id += port_params.n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; + queue_id += subport_params[i].n_pipes_per_subport_enabled * + RTE_SCHED_QUEUES_PER_PIPE; queue_id += pipe_id * RTE_SCHED_QUEUES_PER_PIPE; -- 2.21.0
Remove redundant data structure fields from port level data structures. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 42 +----------------------------------- lib/librte_sched/rte_sched.h | 22 ------------------- 2 files changed, 1 insertion(+), 63 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 1faa580d0..710ecf65a 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -216,13 +216,6 @@ struct rte_sched_port { uint32_t mtu; uint32_t frame_overhead; int socket; - uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - uint32_t n_pipe_profiles; - uint32_t n_max_pipe_profiles; - uint32_t pipe_tc_be_rate_max; -#ifdef RTE_SCHED_RED - struct rte_red_config red_config[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; -#endif /* Timing */ uint64_t time_cpu_cycles; /* Current CPU time measured in CPU cyles */ @@ -230,48 +223,15 @@ struct rte_sched_port { uint64_t time; /* Current NIC TX time measured in bytes */ struct rte_reciprocal inv_cycles_per_byte; /* CPU cycles per byte */ - /* Scheduling loop detection */ - uint32_t pipe_loop; - uint32_t pipe_exhaustion; - - /* Bitmap */ - struct rte_bitmap *bmp; - uint32_t grinder_base_bmp_pos[RTE_SCHED_PORT_N_GRINDERS] __rte_aligned_16; - /* Grinders */ - struct rte_sched_grinder grinder[RTE_SCHED_PORT_N_GRINDERS]; - uint32_t busy_grinders; struct rte_mbuf **pkts_out; uint32_t n_pkts_out; uint32_t subport_id; - /* Queue base calculation */ - uint32_t qsize_add[RTE_SCHED_QUEUES_PER_PIPE]; - uint32_t qsize_sum; - /* Large data structures */ - struct rte_sched_subport *subports[0]; - struct rte_sched_subport *subport; - struct rte_sched_pipe *pipe; - struct rte_sched_queue *queue; - struct rte_sched_queue_extra *queue_extra; - struct rte_sched_pipe_profile *pipe_profiles; - uint8_t *bmp_array; - struct rte_mbuf **queue_array; - uint8_t memory[0] __rte_cache_aligned; + struct rte_sched_subport *subports[0] __rte_cache_aligned; } __rte_cache_aligned; -enum rte_sched_port_array { - e_RTE_SCHED_PORT_ARRAY_SUBPORT = 0, - e_RTE_SCHED_PORT_ARRAY_PIPE, - e_RTE_SCHED_PORT_ARRAY_QUEUE, - e_RTE_SCHED_PORT_ARRAY_QUEUE_EXTRA, - e_RTE_SCHED_PORT_ARRAY_PIPE_PROFILES, - e_RTE_SCHED_PORT_ARRAY_BMP_ARRAY, - e_RTE_SCHED_PORT_ARRAY_QUEUE_ARRAY, - e_RTE_SCHED_PORT_ARRAY_TOTAL, -}; - enum rte_sched_subport_array { e_RTE_SCHED_SUBPORT_ARRAY_PIPE = 0, e_RTE_SCHED_SUBPORT_ARRAY_QUEUE, diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index 40f02f124..c82c23c14 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -260,28 +260,6 @@ struct rte_sched_port_params { * the subports of the same port. */ uint32_t n_pipes_per_subport; - - /** Packet queue size for each traffic class. - * All the pipes within the same subport share the similar - * configuration for the queues. - */ - uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - - /** Pipe profile table. - * Every pipe is configured using one of the profiles from this table. - */ - struct rte_sched_pipe_params *pipe_profiles; - - /** Profiles in the pipe profile table */ - uint32_t n_pipe_profiles; - - /** Max profiles allowed in the pipe profile table */ - uint32_t n_max_pipe_profiles; - -#ifdef RTE_SCHED_RED - /** RED parameters */ - struct rte_red_params red_params[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; -#endif }; /* -- 2.21.0
To support high bandwidth NICs, all rates (port, subport level token bucket and traffic class rates, pipe level token bucket and traffic class rates) and stats counters defined in public data structures (rte_sched.h) are modified to support 64-bit values. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- examples/ip_pipeline/cli.c | 18 +++++----- examples/ip_pipeline/tmgr.h | 2 +- examples/qos_sched/cfg_file.c | 64 +++++++++++++++++------------------ examples/qos_sched/stats.c | 6 ++-- lib/librte_sched/rte_sched.h | 38 ++++++++++----------- 5 files changed, 64 insertions(+), 64 deletions(-) diff --git a/examples/ip_pipeline/cli.c b/examples/ip_pipeline/cli.c index c72030682..3e23f4e7b 100644 --- a/examples/ip_pipeline/cli.c +++ b/examples/ip_pipeline/cli.c @@ -414,23 +414,23 @@ cmd_tmgr_subport_profile(char **tokens, return; } - if (parser_read_uint32(&p.tb_rate, tokens[3]) != 0) { + if (parser_read_uint64(&p.tb_rate, tokens[3]) != 0) { snprintf(out, out_size, MSG_ARG_INVALID, "tb_rate"); return; } - if (parser_read_uint32(&p.tb_size, tokens[4]) != 0) { + if (parser_read_uint64(&p.tb_size, tokens[4]) != 0) { snprintf(out, out_size, MSG_ARG_INVALID, "tb_size"); return; } for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - if (parser_read_uint32(&p.tc_rate[i], tokens[5 + i]) != 0) { + if (parser_read_uint64(&p.tc_rate[i], tokens[5 + i]) != 0) { snprintf(out, out_size, MSG_ARG_INVALID, "tc_rate"); return; } - if (parser_read_uint32(&p.tc_period, tokens[18]) != 0) { + if (parser_read_uint64(&p.tc_period, tokens[18]) != 0) { snprintf(out, out_size, MSG_ARG_INVALID, "tc_period"); return; } @@ -487,23 +487,23 @@ cmd_tmgr_pipe_profile(char **tokens, return; } - if (parser_read_uint32(&p.tb_rate, tokens[3]) != 0) { + if (parser_read_uint64(&p.tb_rate, tokens[3]) != 0) { snprintf(out, out_size, MSG_ARG_INVALID, "tb_rate"); return; } - if (parser_read_uint32(&p.tb_size, tokens[4]) != 0) { + if (parser_read_uint64(&p.tb_size, tokens[4]) != 0) { snprintf(out, out_size, MSG_ARG_INVALID, "tb_size"); return; } for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - if (parser_read_uint32(&p.tc_rate[i], tokens[5 + i]) != 0) { + if (parser_read_uint64(&p.tc_rate[i], tokens[5 + i]) != 0) { snprintf(out, out_size, MSG_ARG_INVALID, "tc_rate"); return; } - if (parser_read_uint32(&p.tc_period, tokens[18]) != 0) { + if (parser_read_uint64(&p.tc_period, tokens[18]) != 0) { snprintf(out, out_size, MSG_ARG_INVALID, "tc_period"); return; } @@ -556,7 +556,7 @@ cmd_tmgr(char **tokens, return; } - if (parser_read_uint32(&p.rate, tokens[3]) != 0) { + if (parser_read_uint64(&p.rate, tokens[3]) != 0) { snprintf(out, out_size, MSG_ARG_INVALID, "rate"); return; } diff --git a/examples/ip_pipeline/tmgr.h b/examples/ip_pipeline/tmgr.h index 1fcf66ee1..ee50cf7cc 100644 --- a/examples/ip_pipeline/tmgr.h +++ b/examples/ip_pipeline/tmgr.h @@ -40,7 +40,7 @@ struct tmgr_port * tmgr_port_find(const char *name); struct tmgr_port_params { - uint32_t rate; + uint64_t rate; uint32_t n_subports_per_port; uint32_t frame_overhead; uint32_t mtu; diff --git a/examples/qos_sched/cfg_file.c b/examples/qos_sched/cfg_file.c index c6d3f5ab6..5714c3f36 100644 --- a/examples/qos_sched/cfg_file.c +++ b/examples/qos_sched/cfg_file.c @@ -59,67 +59,67 @@ cfg_load_pipe(struct rte_cfgfile *cfg, struct rte_sched_pipe_params *pipe_params entry = rte_cfgfile_get_entry(cfg, pipe_name, "tb rate"); if (entry) - pipe_params[j].tb_rate = (uint32_t)atoi(entry); + pipe_params[j].tb_rate = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, pipe_name, "tb size"); if (entry) - pipe_params[j].tb_size = (uint32_t)atoi(entry); + pipe_params[j].tb_size = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc period"); if (entry) - pipe_params[j].tc_period = (uint32_t)atoi(entry); + pipe_params[j].tc_period = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 0 rate"); if (entry) - pipe_params[j].tc_rate[0] = (uint32_t)atoi(entry); + pipe_params[j].tc_rate[0] = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 1 rate"); if (entry) - pipe_params[j].tc_rate[1] = (uint32_t)atoi(entry); + pipe_params[j].tc_rate[1] = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 2 rate"); if (entry) - pipe_params[j].tc_rate[2] = (uint32_t)atoi(entry); + pipe_params[j].tc_rate[2] = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 3 rate"); if (entry) - pipe_params[j].tc_rate[3] = (uint32_t)atoi(entry); + pipe_params[j].tc_rate[3] = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 4 rate"); if (entry) - pipe_params[j].tc_rate[4] = (uint32_t)atoi(entry); + pipe_params[j].tc_rate[4] = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 5 rate"); if (entry) - pipe_params[j].tc_rate[5] = (uint32_t)atoi(entry); + pipe_params[j].tc_rate[5] = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 6 rate"); if (entry) - pipe_params[j].tc_rate[6] = (uint32_t)atoi(entry); + pipe_params[j].tc_rate[6] = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 7 rate"); if (entry) - pipe_params[j].tc_rate[7] = (uint32_t)atoi(entry); + pipe_params[j].tc_rate[7] = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 8 rate"); if (entry) - pipe_params[j].tc_rate[8] = (uint32_t)atoi(entry); + pipe_params[j].tc_rate[8] = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 9 rate"); if (entry) - pipe_params[j].tc_rate[9] = (uint32_t)atoi(entry); + pipe_params[j].tc_rate[9] = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 10 rate"); if (entry) - pipe_params[j].tc_rate[10] = (uint32_t)atoi(entry); + pipe_params[j].tc_rate[10] = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 11 rate"); if (entry) - pipe_params[j].tc_rate[11] = (uint32_t)atoi(entry); + pipe_params[j].tc_rate[11] = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 12 rate"); if (entry) - pipe_params[j].tc_rate[12] = (uint32_t)atoi(entry); + pipe_params[j].tc_rate[12] = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, pipe_name, "tc 12 oversubscription weight"); if (entry) @@ -266,67 +266,67 @@ cfg_load_subport(struct rte_cfgfile *cfg, struct rte_sched_subport_params *subpo entry = rte_cfgfile_get_entry(cfg, sec_name, "tb rate"); if (entry) - subport_params[i].tb_rate = (uint32_t)atoi(entry); + subport_params[i].tb_rate = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, sec_name, "tb size"); if (entry) - subport_params[i].tb_size = (uint32_t)atoi(entry); + subport_params[i].tb_size = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, sec_name, "tc period"); if (entry) - subport_params[i].tc_period = (uint32_t)atoi(entry); + subport_params[i].tc_period = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 0 rate"); if (entry) - subport_params[i].tc_rate[0] = (uint32_t)atoi(entry); + subport_params[i].tc_rate[0] = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 1 rate"); if (entry) - subport_params[i].tc_rate[1] = (uint32_t)atoi(entry); + subport_params[i].tc_rate[1] = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 2 rate"); if (entry) - subport_params[i].tc_rate[2] = (uint32_t)atoi(entry); + subport_params[i].tc_rate[2] = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 3 rate"); if (entry) - subport_params[i].tc_rate[3] = (uint32_t)atoi(entry); + subport_params[i].tc_rate[3] = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 4 rate"); if (entry) - subport_params[i].tc_rate[4] = (uint32_t)atoi(entry); + subport_params[i].tc_rate[4] = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 5 rate"); if (entry) - subport_params[i].tc_rate[5] = (uint32_t)atoi(entry); + subport_params[i].tc_rate[5] = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 6 rate"); if (entry) - subport_params[i].tc_rate[6] = (uint32_t)atoi(entry); + subport_params[i].tc_rate[6] = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 7 rate"); if (entry) - subport_params[i].tc_rate[7] = (uint32_t)atoi(entry); + subport_params[i].tc_rate[7] = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 8 rate"); if (entry) - subport_params[i].tc_rate[8] = (uint32_t)atoi(entry); + subport_params[i].tc_rate[8] = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 9 rate"); if (entry) - subport_params[i].tc_rate[9] = (uint32_t)atoi(entry); + subport_params[i].tc_rate[9] = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 10 rate"); if (entry) - subport_params[i].tc_rate[10] = (uint32_t)atoi(entry); + subport_params[i].tc_rate[10] = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 11 rate"); if (entry) - subport_params[i].tc_rate[11] = (uint32_t)atoi(entry); + subport_params[i].tc_rate[11] = (uint64_t)atoi(entry); entry = rte_cfgfile_get_entry(cfg, sec_name, "tc 12 rate"); if (entry) - subport_params[i].tc_rate[12] = (uint32_t)atoi(entry); + subport_params[i].tc_rate[12] = (uint64_t)atoi(entry); int n_entries = rte_cfgfile_section_num_entries(cfg, sec_name); struct rte_cfgfile_entry entries[n_entries]; diff --git a/examples/qos_sched/stats.c b/examples/qos_sched/stats.c index ce34b6c7c..161f086f1 100644 --- a/examples/qos_sched/stats.c +++ b/examples/qos_sched/stats.c @@ -307,7 +307,7 @@ subport_stat(uint16_t port_id, uint32_t subport_id) printf("+----+-------------+-------------+-------------+-------------+-------------+\n"); for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - printf("| %d | %11" PRIu32 " | %11" PRIu32 " | %11" PRIu32 " | %11" PRIu32 " | %11" PRIu32 " |\n", + printf("| %d | %11" PRIu64 " | %11" PRIu64 " | %11" PRIu64 " | %11" PRIu64 " | %11" PRIu32 " |\n", i, stats.n_pkts_tc[i], stats.n_pkts_tc_dropped[i], stats.n_bytes_tc[i], stats.n_bytes_tc_dropped[i], tc_ov[i]); printf("+----+-------------+-------------+-------------+-------------+-------------+\n"); @@ -351,7 +351,7 @@ pipe_stat(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id) for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { if (i < RTE_SCHED_TRAFFIC_CLASS_BE) { rte_sched_queue_read_stats(port, queue_id + i, &stats, &qlen); - printf("| %d | %d | %11" PRIu32 " | %11" PRIu32 " | %11" PRIu32 " | %11" PRIu32 " | %11i |\n", + printf("| %d | %d | %11" PRIu64 " | %11" PRIu64 " | %11" PRIu64 " | %11" PRIu64 " | %11i |\n", i, 0, stats.n_pkts, stats.n_pkts_dropped, stats.n_bytes, stats.n_bytes_dropped, qlen); printf("+----+-------+-------------+-------------+-------------+-------------+-------------+\n"); @@ -359,7 +359,7 @@ pipe_stat(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id) for (j = 0; j < RTE_SCHED_BE_QUEUES_PER_PIPE; j++) { rte_sched_queue_read_stats(port, queue_id + i + j, &stats, &qlen); - printf("| %d | %d | %11" PRIu32 " | %11" PRIu32 " | %11" PRIu32 " | %11" PRIu32 " | %11i |\n", + printf("| %d | %d | %11" PRIu64 " | %11" PRIu64 " | %11" PRIu64 " | %11" PRIu64 " | %11i |\n", i, j, stats.n_pkts, stats.n_pkts_dropped, stats.n_bytes, stats.n_bytes_dropped, qlen); printf("+----+-------+-------------+-------------+-------------+-------------+-------------+\n"); diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index c82c23c14..8a5a93c98 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -121,16 +121,16 @@ extern "C" { */ struct rte_sched_pipe_params { /** Token bucket rate (measured in bytes per second) */ - uint32_t tb_rate; + uint64_t tb_rate; /** Token bucket size (measured in credits) */ - uint32_t tb_size; + uint64_t tb_size; /** Traffic class rates (measured in bytes per second) */ - uint32_t tc_rate[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + uint64_t tc_rate[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; /** Enforcement period (measured in milliseconds) */ - uint32_t tc_period; + uint64_t tc_period; /** Best-effort traffic class oversubscription weight */ uint8_t tc_ov_weight; @@ -150,16 +150,16 @@ struct rte_sched_pipe_params { */ struct rte_sched_subport_params { /** Token bucket rate (measured in bytes per second) */ - uint32_t tb_rate; + uint64_t tb_rate; /** Token bucket size (measured in credits) */ - uint32_t tb_size; + uint64_t tb_size; /** Traffic class rates (measured in bytes per second) */ - uint32_t tc_rate[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + uint64_t tc_rate[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; /** Enforcement period for rates (measured in milliseconds) */ - uint32_t tc_period; + uint64_t tc_period; /** Number of subport pipes. * The subport can enable/allocate fewer pipes than the maximum @@ -195,41 +195,41 @@ struct rte_sched_subport_params { /** Subport statistics */ struct rte_sched_subport_stats { /** Number of packets successfully written */ - uint32_t n_pkts_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + uint64_t n_pkts_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; /** Number of packets dropped */ - uint32_t n_pkts_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + uint64_t n_pkts_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; /** Number of bytes successfully written for each traffic class */ - uint32_t n_bytes_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + uint64_t n_bytes_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; /** Number of bytes dropped for each traffic class */ - uint32_t n_bytes_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + uint64_t n_bytes_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; #ifdef RTE_SCHED_RED /** Number of packets dropped by red */ - uint32_t n_pkts_red_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + uint64_t n_pkts_red_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; #endif }; /** Queue statistics */ struct rte_sched_queue_stats { /** Packets successfully written */ - uint32_t n_pkts; + uint64_t n_pkts; /** Packets dropped */ - uint32_t n_pkts_dropped; + uint64_t n_pkts_dropped; #ifdef RTE_SCHED_RED /** Packets dropped by RED */ - uint32_t n_pkts_red_dropped; + uint64_t n_pkts_red_dropped; #endif /** Bytes successfully written */ - uint32_t n_bytes; + uint64_t n_bytes; /** Bytes dropped */ - uint32_t n_bytes_dropped; + uint64_t n_bytes_dropped; }; /** Port configuration parameters. */ @@ -241,7 +241,7 @@ struct rte_sched_port_params { int socket; /** Output port rate (measured in bytes per second) */ - uint32_t rate; + uint64_t rate; /** Maximum Ethernet frame size (measured in bytes). * Should not include the framing overhead. -- 2.21.0
Modify internal structure and functions to support 64-bit values for rates and stats parameters. Release note is updated and deprecation notice is removed. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- doc/guides/rel_notes/deprecation.rst | 6 - doc/guides/rel_notes/release_19_11.rst | 7 +- lib/librte_sched/rte_approx.c | 57 ++++--- lib/librte_sched/rte_approx.h | 3 +- lib/librte_sched/rte_sched.c | 211 +++++++++++++------------ lib/librte_sched/rte_sched_common.h | 12 +- 6 files changed, 162 insertions(+), 134 deletions(-) diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst index 237813b64..91916d4ac 100644 --- a/doc/guides/rel_notes/deprecation.rst +++ b/doc/guides/rel_notes/deprecation.rst @@ -125,12 +125,6 @@ Deprecation Notices to one it means it represents IV, when is set to zero it means J0 is used directly, in this case 16 bytes of J0 need to be passed. -* sched: To allow more traffic classes, flexible mapping of pipe queues to - traffic classes, and subport level configuration of pipes and queues - changes will be made to macros, data structures and API functions defined - in "rte_sched.h". These changes are aligned to improvements suggested in the - RFC https://mails.dpdk.org/archives/dev/2018-November/120035.html. - * metrics: The function ``rte_metrics_init`` will have a non-void return in order to notify errors instead of calling ``rte_exit``. diff --git a/doc/guides/rel_notes/release_19_11.rst b/doc/guides/rel_notes/release_19_11.rst index 23ceb8f67..87812b32c 100644 --- a/doc/guides/rel_notes/release_19_11.rst +++ b/doc/guides/rel_notes/release_19_11.rst @@ -172,6 +172,11 @@ API Changes * ethdev: changed ``rte_eth_dev_owner_delete`` return value from ``void`` to ``int`` to provide a way to report various error conditions. +* sched: The pipe nodes configuration parameters such as number of pipes, + pipe queue sizes, pipe profiles, etc., are moved from port level structure + to subport level. This allows different subports of the same port to + have different configuration for the pipe nodes. + ABI Changes ----------- @@ -259,7 +264,7 @@ The libraries prepended with a plus sign were incremented in this version. librte_rcu.so.1 librte_reorder.so.1 librte_ring.so.2 - librte_sched.so.3 + + librte_sched.so.4 librte_security.so.2 librte_stack.so.1 librte_table.so.3 diff --git a/lib/librte_sched/rte_approx.c b/lib/librte_sched/rte_approx.c index 30620b83d..4883d3969 100644 --- a/lib/librte_sched/rte_approx.c +++ b/lib/librte_sched/rte_approx.c @@ -18,22 +18,23 @@ */ /* fraction comparison: compare (a/b) and (c/d) */ -static inline uint32_t -less(uint32_t a, uint32_t b, uint32_t c, uint32_t d) +static inline sched_counter_t +less(sched_counter_t a, sched_counter_t b, sched_counter_t c, sched_counter_t d) { return a*d < b*c; } -static inline uint32_t -less_or_equal(uint32_t a, uint32_t b, uint32_t c, uint32_t d) +static inline sched_counter_t +less_or_equal(sched_counter_t a, sched_counter_t b, sched_counter_t c, + sched_counter_t d) { return a*d <= b*c; } /* check whether a/b is a valid approximation */ -static inline uint32_t -matches(uint32_t a, uint32_t b, - uint32_t alpha_num, uint32_t d_num, uint32_t denum) +static inline sched_counter_t +matches(sched_counter_t a, sched_counter_t b, + sched_counter_t alpha_num, sched_counter_t d_num, sched_counter_t denum) { if (less_or_equal(a, b, alpha_num - d_num, denum)) return 0; @@ -45,33 +46,39 @@ matches(uint32_t a, uint32_t b, } static inline void -find_exact_solution_left(uint32_t p_a, uint32_t q_a, uint32_t p_b, uint32_t q_b, - uint32_t alpha_num, uint32_t d_num, uint32_t denum, uint32_t *p, uint32_t *q) +find_exact_solution_left(sched_counter_t p_a, sched_counter_t q_a, + sched_counter_t p_b, sched_counter_t q_b, sched_counter_t alpha_num, + sched_counter_t d_num, sched_counter_t denum, sched_counter_t *p, + sched_counter_t *q) { - uint32_t k_num = denum * p_b - (alpha_num + d_num) * q_b; - uint32_t k_denum = (alpha_num + d_num) * q_a - denum * p_a; - uint32_t k = (k_num / k_denum) + 1; + sched_counter_t k_num = denum * p_b - (alpha_num + d_num) * q_b; + sched_counter_t k_denum = (alpha_num + d_num) * q_a - denum * p_a; + sched_counter_t k = (k_num / k_denum) + 1; *p = p_b + k * p_a; *q = q_b + k * q_a; } static inline void -find_exact_solution_right(uint32_t p_a, uint32_t q_a, uint32_t p_b, uint32_t q_b, - uint32_t alpha_num, uint32_t d_num, uint32_t denum, uint32_t *p, uint32_t *q) +find_exact_solution_right(sched_counter_t p_a, sched_counter_t q_a, + sched_counter_t p_b, sched_counter_t q_b, sched_counter_t alpha_num, + sched_counter_t d_num, sched_counter_t denum, sched_counter_t *p, + sched_counter_t *q) { - uint32_t k_num = - denum * p_b + (alpha_num - d_num) * q_b; - uint32_t k_denum = - (alpha_num - d_num) * q_a + denum * p_a; - uint32_t k = (k_num / k_denum) + 1; + sched_counter_t k_num = -denum * p_b + (alpha_num - d_num) * q_b; + sched_counter_t k_denum = -(alpha_num - d_num) * q_a + denum * p_a; + sched_counter_t k = (k_num / k_denum) + 1; *p = p_b + k * p_a; *q = q_b + k * q_a; } static int -find_best_rational_approximation(uint32_t alpha_num, uint32_t d_num, uint32_t denum, uint32_t *p, uint32_t *q) +find_best_rational_approximation(sched_counter_t alpha_num, + sched_counter_t d_num, sched_counter_t denum, sched_counter_t *p, + sched_counter_t *q) { - uint32_t p_a, q_a, p_b, q_b; + sched_counter_t p_a, q_a, p_b, q_b; /* check assumptions on the inputs */ if (!((0 < d_num) && (d_num < alpha_num) && (alpha_num < denum) && (d_num + alpha_num < denum))) { @@ -85,8 +92,8 @@ find_best_rational_approximation(uint32_t alpha_num, uint32_t d_num, uint32_t de q_b = 1; while (1) { - uint32_t new_p_a, new_q_a, new_p_b, new_q_b; - uint32_t x_num, x_denum, x; + sched_counter_t new_p_a, new_q_a, new_p_b, new_q_b; + sched_counter_t x_num, x_denum, x; int aa, bb; /* compute the number of steps to the left */ @@ -139,9 +146,9 @@ find_best_rational_approximation(uint32_t alpha_num, uint32_t d_num, uint32_t de } } -int rte_approx(double alpha, double d, uint32_t *p, uint32_t *q) +int rte_approx(double alpha, double d, sched_counter_t *p, sched_counter_t *q) { - uint32_t alpha_num, d_num, denum; + sched_counter_t alpha_num, d_num, denum; /* Check input arguments */ if (!((0.0 < d) && (d < alpha) && (alpha < 1.0))) { @@ -159,8 +166,8 @@ int rte_approx(double alpha, double d, uint32_t *p, uint32_t *q) d *= 10; denum *= 10; } - alpha_num = (uint32_t) alpha; - d_num = (uint32_t) d; + alpha_num = (sched_counter_t) alpha; + d_num = (sched_counter_t) d; /* Perform approximation */ return find_best_rational_approximation(alpha_num, d_num, denum, p, q); diff --git a/lib/librte_sched/rte_approx.h b/lib/librte_sched/rte_approx.h index 0244d98f1..e591e122d 100644 --- a/lib/librte_sched/rte_approx.h +++ b/lib/librte_sched/rte_approx.h @@ -20,6 +20,7 @@ extern "C" { ***/ #include <stdint.h> +#include "rte_sched_common.h" /** * Find best rational approximation @@ -37,7 +38,7 @@ extern "C" { * @return * 0 upon success, error code otherwise */ -int rte_approx(double alpha, double d, uint32_t *p, uint32_t *q); +int rte_approx(double alpha, double d, sched_counter_t *p, sched_counter_t *q); #ifdef __cplusplus } diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 710ecf65a..11d1febe2 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -49,13 +49,13 @@ struct rte_sched_pipe_profile { /* Token bucket (TB) */ - uint32_t tb_period; - uint32_t tb_credits_per_period; - uint32_t tb_size; + sched_counter_t tb_period; + sched_counter_t tb_credits_per_period; + sched_counter_t tb_size; /* Pipe traffic classes */ - uint32_t tc_period; - uint32_t tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + sched_counter_t tc_period; + sched_counter_t tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; uint8_t tc_ov_weight; /* Pipe best-effort traffic class queues */ @@ -65,20 +65,20 @@ struct rte_sched_pipe_profile { struct rte_sched_pipe { /* Token bucket (TB) */ uint64_t tb_time; /* time of last update */ - uint32_t tb_credits; + sched_counter_t tb_credits; /* Pipe profile and flags */ uint32_t profile; /* Traffic classes (TCs) */ uint64_t tc_time; /* time of next update */ - uint32_t tc_credits[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + sched_counter_t tc_credits[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; /* Weighted Round Robin (WRR) */ uint8_t wrr_tokens[RTE_SCHED_BE_QUEUES_PER_PIPE]; /* TC oversubscription */ - uint32_t tc_ov_credits; + sched_counter_t tc_ov_credits; uint8_t tc_ov_period_id; } __rte_cache_aligned; @@ -141,28 +141,28 @@ struct rte_sched_grinder { struct rte_sched_subport { /* Token bucket (TB) */ uint64_t tb_time; /* time of last update */ - uint32_t tb_period; - uint32_t tb_credits_per_period; - uint32_t tb_size; - uint32_t tb_credits; + sched_counter_t tb_period; + sched_counter_t tb_credits_per_period; + sched_counter_t tb_size; + sched_counter_t tb_credits; /* Traffic classes (TCs) */ uint64_t tc_time; /* time of next update */ - uint32_t tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - uint32_t tc_credits[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - uint32_t tc_period; + sched_counter_t tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + sched_counter_t tc_credits[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + sched_counter_t tc_period; /* TC oversubscription */ - uint32_t tc_ov_wm; - uint32_t tc_ov_wm_min; - uint32_t tc_ov_wm_max; + sched_counter_t tc_ov_wm; + sched_counter_t tc_ov_wm_min; + sched_counter_t tc_ov_wm_max; uint8_t tc_ov_period_id; uint8_t tc_ov; uint32_t tc_ov_n; double tc_ov_rate; /* Statistics */ - struct rte_sched_subport_stats stats; + struct rte_sched_subport_stats stats __rte_cache_aligned; /* Subport pipes */ uint32_t n_pipes_per_subport_enabled; @@ -170,7 +170,7 @@ struct rte_sched_subport { uint32_t n_max_pipe_profiles; /* Pipe best-effort TC rate */ - uint32_t pipe_tc_be_rate_max; + sched_counter_t pipe_tc_be_rate_max; /* Pipe queues size */ uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; @@ -212,7 +212,7 @@ 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 rate; + sched_counter_t rate; uint32_t mtu; uint32_t frame_overhead; int socket; @@ -517,33 +517,35 @@ rte_sched_port_log_pipe_profile(struct rte_sched_subport *subport, uint32_t i) struct rte_sched_pipe_profile *p = subport->pipe_profiles + i; RTE_LOG(DEBUG, SCHED, "Low level config for pipe profile %u:\n" - " Token bucket: period = %u, credits per period = %u, size = %u\n" - " Traffic classes: period = %u,\n" - " credits per period = [%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %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" " Best-effort traffic class oversubscription: weight = %hhu\n" " WRR cost: [%hhu, %hhu, %hhu, %hhu]\n", i, /* Token bucket */ - p->tb_period, - p->tb_credits_per_period, - p->tb_size, + (uint64_t)p->tb_period, + (uint64_t)p->tb_credits_per_period, + (uint64_t)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], + (uint64_t)p->tc_period, + (uint64_t)p->tc_credits_per_period[0], + (uint64_t)p->tc_credits_per_period[1], + (uint64_t)p->tc_credits_per_period[2], + (uint64_t)p->tc_credits_per_period[3], + (uint64_t)p->tc_credits_per_period[4], + (uint64_t)p->tc_credits_per_period[5], + (uint64_t)p->tc_credits_per_period[6], + (uint64_t)p->tc_credits_per_period[7], + (uint64_t)p->tc_credits_per_period[8], + (uint64_t)p->tc_credits_per_period[9], + (uint64_t)p->tc_credits_per_period[10], + (uint64_t)p->tc_credits_per_period[11], + (uint64_t)p->tc_credits_per_period[12], /* Best-effort traffic class oversubscription */ p->tc_ov_weight, @@ -553,7 +555,7 @@ rte_sched_port_log_pipe_profile(struct rte_sched_subport *subport, uint32_t i) } static inline uint64_t -rte_sched_time_ms_to_bytes(uint32_t time_ms, uint32_t rate) +rte_sched_time_ms_to_bytes(sched_counter_t time_ms, sched_counter_t rate) { uint64_t time = time_ms; @@ -566,7 +568,7 @@ static void rte_sched_pipe_profile_convert(struct rte_sched_subport *subport, struct rte_sched_pipe_params *src, struct rte_sched_pipe_profile *dst, - uint32_t rate) + sched_counter_t rate) { uint32_t wrr_cost[RTE_SCHED_BE_QUEUES_PER_PIPE]; uint32_t lcd1, lcd2, lcd; @@ -581,8 +583,8 @@ rte_sched_pipe_profile_convert(struct rte_sched_subport *subport, / (double) rate; double d = RTE_SCHED_TB_RATE_CONFIG_ERR; - rte_approx(tb_rate, d, - &dst->tb_credits_per_period, &dst->tb_period); + rte_approx(tb_rate, d, &dst->tb_credits_per_period, + &dst->tb_period); } dst->tb_size = src->tb_size; @@ -594,8 +596,8 @@ rte_sched_pipe_profile_convert(struct rte_sched_subport *subport, for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) if (subport->qsize[i]) dst->tc_credits_per_period[i] - = rte_sched_time_ms_to_bytes(src->tc_period, - src->tc_rate[i]); + = (sched_counter_t) rte_sched_time_ms_to_bytes( + src->tc_period, src->tc_rate[i]); dst->tc_ov_weight = src->tc_ov_weight; @@ -637,7 +639,8 @@ rte_sched_subport_config_pipe_profile_table(struct rte_sched_subport *subport, subport->pipe_tc_be_rate_max = 0; for (i = 0; i < subport->n_pipe_profiles; i++) { struct rte_sched_pipe_params *src = params->pipe_profiles + i; - uint32_t pipe_tc_be_rate = src->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; + sched_counter_t pipe_tc_be_rate = + src->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; if (subport->pipe_tc_be_rate_max < pipe_tc_be_rate) subport->pipe_tc_be_rate_max = pipe_tc_be_rate; @@ -647,7 +650,7 @@ rte_sched_subport_config_pipe_profile_table(struct rte_sched_subport *subport, static int rte_sched_subport_check_params(struct rte_sched_subport_params *params, uint32_t n_max_pipes_per_subport, - uint32_t rate) + sched_counter_t rate) { uint32_t i; @@ -684,7 +687,7 @@ rte_sched_subport_check_params(struct rte_sched_subport_params *params, } for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - uint32_t tc_rate = params->tc_rate[i]; + sched_counter_t tc_rate = params->tc_rate[i]; uint16_t qsize = params->qsize[i]; if ((qsize == 0 && tc_rate != 0) || @@ -910,36 +913,40 @@ rte_sched_port_log_subport_config(struct rte_sched_port *port, uint32_t i) struct rte_sched_subport *s = port->subports[i]; RTE_LOG(DEBUG, SCHED, "Low level config for subport %u:\n" - " Token bucket: period = %u, credits per period = %u, size = %u\n" - " Traffic classes: period = %u\n" - " credits per period = [%u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u]\n" - " Best effort traffic class oversubscription: wm min = %u, wm max = %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" + " Best effort traffic class oversubscription: wm min = %"PRIu64 + ", wm max = %"PRIu64"\n", i, /* Token bucket */ - s->tb_period, - s->tb_credits_per_period, - s->tb_size, + (uint64_t)s->tb_period, + (uint64_t)s->tb_credits_per_period, + (uint64_t)s->tb_size, /* Traffic classes */ - s->tc_period, - s->tc_credits_per_period[0], - s->tc_credits_per_period[1], - s->tc_credits_per_period[2], - s->tc_credits_per_period[3], - 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], + (uint64_t)s->tc_period, + (uint64_t)s->tc_credits_per_period[0], + (uint64_t)s->tc_credits_per_period[1], + (uint64_t)s->tc_credits_per_period[2], + (uint64_t)s->tc_credits_per_period[3], + (uint64_t)s->tc_credits_per_period[4], + (uint64_t)s->tc_credits_per_period[5], + (uint64_t)s->tc_credits_per_period[6], + (uint64_t)s->tc_credits_per_period[7], + (uint64_t)s->tc_credits_per_period[8], + (uint64_t)s->tc_credits_per_period[9], + (uint64_t)s->tc_credits_per_period[10], + (uint64_t)s->tc_credits_per_period[11], + (uint64_t)s->tc_credits_per_period[12], /* Best effort traffic class oversubscription */ - s->tc_ov_wm_min, - s->tc_ov_wm_max); + (uint64_t)s->tc_ov_wm_min, + (uint64_t)s->tc_ov_wm_max); } static void @@ -1023,7 +1030,8 @@ rte_sched_subport_config(struct rte_sched_port *port, double tb_rate = ((double) params->tb_rate) / ((double) port->rate); double d = RTE_SCHED_TB_RATE_CONFIG_ERR; - rte_approx(tb_rate, d, &s->tb_credits_per_period, &s->tb_period); + rte_approx(tb_rate, d, &s->tb_credits_per_period, + &s->tb_period); } s->tb_size = params->tb_size; @@ -1035,8 +1043,8 @@ rte_sched_subport_config(struct rte_sched_port *port, for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { if (params->qsize[i]) s->tc_credits_per_period[i] - = rte_sched_time_ms_to_bytes(params->tc_period, - params->tc_rate[i]); + = (sched_counter_t) rte_sched_time_ms_to_bytes( + params->tc_period, params->tc_rate[i]); } s->tc_time = port->time + s->tc_period; for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) @@ -1970,13 +1978,15 @@ grinder_credits_update(struct rte_sched_port *port, /* Subport TB */ n_periods = (port->time - subport->tb_time) / subport->tb_period; subport->tb_credits += n_periods * subport->tb_credits_per_period; - subport->tb_credits = rte_sched_min_val_2_u32(subport->tb_credits, subport->tb_size); + subport->tb_credits = rte_sched_min_val_2(subport->tb_credits, + subport->tb_size); subport->tb_time += n_periods * subport->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_sched_min_val_2_u32(pipe->tb_credits, params->tb_size); + pipe->tb_credits = rte_sched_min_val_2(pipe->tb_credits, + params->tb_size); pipe->tb_time += n_periods * params->tb_period; /* Subport TCs */ @@ -1998,13 +2008,13 @@ grinder_credits_update(struct rte_sched_port *port, #else -static inline uint32_t +static inline sched_counter_t grinder_tc_ov_credits_update(struct rte_sched_port *port, struct rte_sched_subport *subport) { - uint32_t tc_ov_consumption[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - uint32_t tc_consumption = 0, tc_ov_consumption_max; - uint32_t tc_ov_wm = subport->tc_ov_wm; + sched_counter_t tc_ov_consumption[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + sched_counter_t tc_consumption = 0, tc_ov_consumption_max; + sched_counter_t tc_ov_wm = subport->tc_ov_wm; uint32_t i; if (subport->tc_ov == 0) @@ -2053,13 +2063,15 @@ grinder_credits_update(struct rte_sched_port *port, /* Subport TB */ n_periods = (port->time - subport->tb_time) / subport->tb_period; subport->tb_credits += n_periods * subport->tb_credits_per_period; - subport->tb_credits = rte_sched_min_val_2_u32(subport->tb_credits, subport->tb_size); + subport->tb_credits = rte_sched_min_val_2(subport->tb_credits, + subport->tb_size); subport->tb_time += n_periods * subport->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_sched_min_val_2_u32(pipe->tb_credits, params->tb_size); + pipe->tb_credits = rte_sched_min_val_2(pipe->tb_credits, + params->tb_size); pipe->tb_time += n_periods * params->tb_period; /* Subport TCs */ @@ -2101,11 +2113,11 @@ grinder_credits_check(struct rte_sched_port *port, struct rte_sched_pipe *pipe = grinder->pipe; struct rte_mbuf *pkt = grinder->pkt; uint32_t tc_index = grinder->tc_index; - uint32_t pkt_len = pkt->pkt_len + port->frame_overhead; - uint32_t subport_tb_credits = subport->tb_credits; - uint32_t subport_tc_credits = subport->tc_credits[tc_index]; - uint32_t pipe_tb_credits = pipe->tb_credits; - uint32_t pipe_tc_credits = pipe->tc_credits[tc_index]; + sched_counter_t pkt_len = pkt->pkt_len + port->frame_overhead; + sched_counter_t subport_tb_credits = subport->tb_credits; + sched_counter_t subport_tc_credits = subport->tc_credits[tc_index]; + sched_counter_t pipe_tb_credits = pipe->tb_credits; + sched_counter_t pipe_tc_credits = pipe->tc_credits[tc_index]; int enough_credits; /* Check queue credits */ @@ -2136,21 +2148,22 @@ grinder_credits_check(struct rte_sched_port *port, struct rte_sched_pipe *pipe = grinder->pipe; struct rte_mbuf *pkt = grinder->pkt; uint32_t tc_index = grinder->tc_index; - uint32_t pkt_len = pkt->pkt_len + port->frame_overhead; - uint32_t subport_tb_credits = subport->tb_credits; - uint32_t subport_tc_credits = subport->tc_credits[tc_index]; - uint32_t pipe_tb_credits = pipe->tb_credits; - uint32_t pipe_tc_credits = pipe->tc_credits[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] = {0}; - uint32_t pipe_tc_ov_credits, i; + sched_counter_t pkt_len = pkt->pkt_len + port->frame_overhead; + sched_counter_t subport_tb_credits = subport->tb_credits; + sched_counter_t subport_tc_credits = subport->tc_credits[tc_index]; + sched_counter_t pipe_tb_credits = pipe->tb_credits; + sched_counter_t pipe_tc_credits = pipe->tc_credits[tc_index]; + sched_counter_t pipe_tc_ov_mask1[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + sched_counter_t pipe_tc_ov_mask2[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE] = {0}; + sched_counter_t pipe_tc_ov_credits; + uint32_t i; int enough_credits; for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - pipe_tc_ov_mask1[i] = UINT32_MAX; + pipe_tc_ov_mask1[i] = ~0; pipe_tc_ov_mask1[RTE_SCHED_TRAFFIC_CLASS_BE] = pipe->tc_ov_credits; - pipe_tc_ov_mask2[RTE_SCHED_TRAFFIC_CLASS_BE] = UINT32_MAX; + pipe_tc_ov_mask2[RTE_SCHED_TRAFFIC_CLASS_BE] = ~0; pipe_tc_ov_credits = pipe_tc_ov_mask1[tc_index]; /* Check pipe and subport credits */ diff --git a/lib/librte_sched/rte_sched_common.h b/lib/librte_sched/rte_sched_common.h index 8c191a9b8..06520a686 100644 --- a/lib/librte_sched/rte_sched_common.h +++ b/lib/librte_sched/rte_sched_common.h @@ -14,8 +14,16 @@ extern "C" { #define __rte_aligned_16 __attribute__((__aligned__(16))) -static inline uint32_t -rte_sched_min_val_2_u32(uint32_t x, uint32_t y) +//#define COUNTER_SIZE_64 + +#ifdef COUNTER_SIZE_64 +typedef uint64_t sched_counter_t; +#else +typedef uint32_t sched_counter_t; +#endif + +static inline sched_counter_t +rte_sched_min_val_2(sched_counter_t x, sched_counter_t y) { return (x < y)? x : y; } -- 2.21.0
> -----Original Message-----
> From: Singh, Jasvinder
> Sent: Monday, October 14, 2019 1:10 PM
> To: dev@dpdk.org
> Cc: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>
> Subject: [PATCH v4 00/17] sched: subport level configuration of pipe nodes
>
> This patchset refactors the dpdk qos sched library to allow subport
> level configuration flexibility of the pipe nodes.
>
> Currently, all parameters for the pipe nodes (subscribers)
> configuration are part of the port level structure which forces
> all groups of subscribers (pipes) in different subports to
> have similar configurations in terms of their number, queue sizes,
> traffic-classes, etc.
>
> The new implementation moves pipe nodes configuration parameters
> from port level to subport level structure. This allows different
> subports of the same port to have different configuration for the
> pipe nodes, for examples- number of pipes, queue sizes, pipe
> profiles, etc.
>
> In order to keep the implementation complexity under control, all
> pipes within the same subport share the same configuration for queue
> sizes.
>
> v4:
> - remove deprecation note
> - rebase on current dpdk head
> - add 64-bit values support
>
Hi Jasvinder,
I think the 64-bit counter support is a distinct unrelated feature, and I suggest we send a separate patchset for it. It also saves us re-reviewing the large patchset that was already reviewed?
Regards,
Cristian
> -----Original Message-----
> From: Dumitrescu, Cristian
> Sent: Monday, October 14, 2019 3:24 PM
> To: Singh, Jasvinder <jasvinder.singh@intel.com>; dev@dpdk.org
> Subject: RE: [PATCH v4 00/17] sched: subport level configuration of pipe nodes
>
>
>
> > -----Original Message-----
> > From: Singh, Jasvinder
> > Sent: Monday, October 14, 2019 1:10 PM
> > To: dev@dpdk.org
> > Cc: Dumitrescu, Cristian <cristian.dumitrescu@intel.com>
> > Subject: [PATCH v4 00/17] sched: subport level configuration of pipe
> > nodes
> >
> > This patchset refactors the dpdk qos sched library to allow subport
> > level configuration flexibility of the pipe nodes.
> >
> > Currently, all parameters for the pipe nodes (subscribers)
> > configuration are part of the port level structure which forces all
> > groups of subscribers (pipes) in different subports to have similar
> > configurations in terms of their number, queue sizes, traffic-classes,
> > etc.
> >
> > The new implementation moves pipe nodes configuration parameters from
> > port level to subport level structure. This allows different subports
> > of the same port to have different configuration for the pipe nodes,
> > for examples- number of pipes, queue sizes, pipe profiles, etc.
> >
> > In order to keep the implementation complexity under control, all
> > pipes within the same subport share the same configuration for queue
> > sizes.
> >
> > v4:
> > - remove deprecation note
> > - rebase on current dpdk head
> > - add 64-bit values support
> >
>
> Hi Jasvinder,
>
> I think the 64-bit counter support is a distinct unrelated feature, and I suggest
> we send a separate patchset for it. It also saves us re-reviewing the large
> patchset that was already reviewed?
>
I sent separate patches on 64-but counter support. Thanks.
This patchset refactors the dpdk qos sched library to allow subport level configuration flexibility of the pipe nodes. Currently, all parameters for the pipe nodes (subscribers) configuration are part of the port level structure which forces all groups of subscribers (pipes) in different subports to have similar configurations in terms of their number, queue sizes, traffic-classes, etc. The new implementation moves pipe nodes configuration parameters from port level to subport level structure. This allows different subports of the same port to have different configuration for the pipe nodes, for examples- number of pipes, queue sizes, pipe profiles, etc. In order to keep the implementation complexity under control, all pipes within the same subport share the same configuration for queue sizes. v5: - remove patches on 64-bit values support, sent separately v4: - remove deprecation note - rebase on current dpdk head - add 64-bit values support v3: - improve doxygen comments v2: - fix qsize parsing in sample application - fix checkpatch warnings Jasvinder Singh (15): sched: add pipe config params to subport struct sched: modify internal structs for config flexibility sched: remove pipe params config from port level sched: add pipe config to subport level sched: modify pipe functions for config flexibility sched: modify pkt enqueue for config flexibility sched: update memory compute to support flexiblity sched: update grinder functions for config flexibility sched: update pkt dequeue for flexible config sched: update queue stats read for config flexibility test/sched: modify tests for subport config flexibility net/softnic: add subport config flexibility to TM ip_pipeline: add subport config flexibility to TM examples/qos_sched: add subport configuration flexibility sched: remove redundant code app/test/test_sched.c | 35 +- doc/guides/rel_notes/release_19_11.rst | 7 +- drivers/net/softnic/rte_eth_softnic_tm.c | 54 +- examples/ip_pipeline/cli.c | 71 +- examples/ip_pipeline/tmgr.c | 25 +- examples/ip_pipeline/tmgr.h | 7 +- examples/qos_sched/app_thread.c | 20 +- examples/qos_sched/cfg_file.c | 229 ++-- examples/qos_sched/init.c | 54 +- examples/qos_sched/main.h | 1 + examples/qos_sched/profile.cfg | 5 +- examples/qos_sched/profile_ov.cfg | 5 +- examples/qos_sched/stats.c | 44 +- lib/librte_sched/Makefile | 2 +- lib/librte_sched/meson.build | 2 +- lib/librte_sched/rte_sched.c | 1394 +++++++++++++--------- lib/librte_sched/rte_sched.h | 129 +- lib/librte_sched/rte_sched_version.map | 2 +- 18 files changed, 1213 insertions(+), 873 deletions(-) -- 2.21.0
Add pipe configuration parameters to subport level structure to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/Makefile | 2 +- lib/librte_sched/meson.build | 2 +- lib/librte_sched/rte_sched.h | 92 ++++++++++++++++++++++++------------ 3 files changed, 65 insertions(+), 31 deletions(-) diff --git a/lib/librte_sched/Makefile b/lib/librte_sched/Makefile index 3d7f410e1..6e4a72d89 100644 --- a/lib/librte_sched/Makefile +++ b/lib/librte_sched/Makefile @@ -18,7 +18,7 @@ LDLIBS += -lrte_timer EXPORT_MAP := rte_sched_version.map -LIBABIVER := 3 +LIBABIVER := 4 # # all source are stored in SRCS-y diff --git a/lib/librte_sched/meson.build b/lib/librte_sched/meson.build index 59d43c6d8..9f40a2368 100644 --- a/lib/librte_sched/meson.build +++ b/lib/librte_sched/meson.build @@ -1,7 +1,7 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2017 Intel Corporation -version = 3 +version = 4 sources = files('rte_sched.c', 'rte_red.c', 'rte_approx.c') headers = files('rte_sched.h', 'rte_sched_common.h', 'rte_red.h', 'rte_approx.h') diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index eac6db274..fbb0e23fa 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -111,7 +111,7 @@ extern "C" { #endif /* - * Subport configuration parameters. The period and credits_per_period + * Pipe configuration parameters. The period and credits_per_period * parameters are measured in bytes, with one byte meaning the time * duration associated with the transmission of one byte on the * physical medium of the output port, with pipe or pipe traffic class @@ -119,7 +119,7 @@ extern "C" { * credits_per_period divided by period. One credit represents one * byte. */ -struct rte_sched_subport_params { +struct rte_sched_pipe_params { /** Token bucket rate (measured in bytes per second) */ uint32_t tb_rate; @@ -129,32 +129,18 @@ struct rte_sched_subport_params { /** Traffic class rates (measured in bytes per second) */ uint32_t tc_rate[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - /** Enforcement period for rates (measured in milliseconds) */ + /** Enforcement period (measured in milliseconds) */ uint32_t tc_period; -}; - -/** Subport statistics */ -struct rte_sched_subport_stats { - /** Number of packets successfully written */ - uint32_t n_pkts_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - - /** Number of packets dropped */ - uint32_t n_pkts_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - /** Number of bytes successfully written for each traffic class */ - uint32_t n_bytes_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - - /** Number of bytes dropped for each traffic class */ - uint32_t n_bytes_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + /** Best-effort traffic class oversubscription weight */ + uint8_t tc_ov_weight; -#ifdef RTE_SCHED_RED - /** Number of packets dropped by red */ - uint32_t n_pkts_red_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; -#endif + /** WRR weights of best-effort traffic class queues */ + uint8_t wrr_weights[RTE_SCHED_BE_QUEUES_PER_PIPE]; }; /* - * Pipe configuration parameters. The period and credits_per_period + * Subport configuration parameters. The period and credits_per_period * parameters are measured in bytes, with one byte meaning the time * duration associated with the transmission of one byte on the * physical medium of the output port, with pipe or pipe traffic class @@ -162,7 +148,7 @@ struct rte_sched_subport_stats { * credits_per_period divided by period. One credit represents one * byte. */ -struct rte_sched_pipe_params { +struct rte_sched_subport_params { /** Token bucket rate (measured in bytes per second) */ uint32_t tb_rate; @@ -172,14 +158,58 @@ struct rte_sched_pipe_params { /** Traffic class rates (measured in bytes per second) */ uint32_t tc_rate[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - /** Enforcement period (measured in milliseconds) */ + /** Enforcement period for rates (measured in milliseconds) */ uint32_t tc_period; - /** Best-effort traffic class oversubscription weight */ - uint8_t tc_ov_weight; + /** Number of subport pipes. + * The subport can enable/allocate fewer pipes than the maximum + * number set through struct port_params::n_max_pipes_per_subport, + * as needed, to avoid memory allocation for the queues of the + * pipes that are not really needed. + */ + uint32_t n_pipes_per_subport_enabled; - /** WRR weights of best-effort traffic class queues */ - uint8_t wrr_weights[RTE_SCHED_BE_QUEUES_PER_PIPE]; + /** Packet queue size for each traffic class. + * All the pipes within the same subport share the similar + * configuration for the queues. + */ + uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + + /** Pipe profile table. + * Every pipe is configured using one of the profiles from this table. + */ + struct rte_sched_pipe_params *pipe_profiles; + + /** Profiles in the pipe profile table */ + uint32_t n_pipe_profiles; + + /** Max allowed profiles in the pipe profile table */ + uint32_t n_max_pipe_profiles; + +#ifdef RTE_SCHED_RED + /** RED parameters */ + struct rte_red_params red_params[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; +#endif +}; + +/** Subport statistics */ +struct rte_sched_subport_stats { + /** Number of packets successfully written */ + uint32_t n_pkts_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + + /** Number of packets dropped */ + uint32_t n_pkts_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + + /** Number of bytes successfully written for each traffic class */ + uint32_t n_bytes_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + + /** Number of bytes dropped for each traffic class */ + uint32_t n_bytes_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + +#ifdef RTE_SCHED_RED + /** Number of packets dropped by red */ + uint32_t n_pkts_red_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; +#endif }; /** Queue statistics */ @@ -224,7 +254,11 @@ struct rte_sched_port_params { /** Number of subports */ uint32_t n_subports_per_port; - /** Number of subport_pipes */ + /** 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 + * the subports of the same port. + */ uint32_t n_pipes_per_subport; /** Packet queue size for each traffic class. -- 2.21.0
Update internal structures related to port and subport to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 106 ++++++++++++++++++++++++++--------- 1 file changed, 78 insertions(+), 28 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index d8ab21d64..672412b77 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -47,33 +47,6 @@ */ #define RTE_SCHED_TIME_SHIFT 8 -struct rte_sched_subport { - /* Token bucket (TB) */ - uint64_t tb_time; /* time of last update */ - uint32_t tb_period; - uint32_t tb_credits_per_period; - uint32_t tb_size; - uint32_t tb_credits; - - /* Traffic classes (TCs) */ - uint64_t tc_time; /* time of next update */ - uint32_t tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - uint32_t tc_credits[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - uint32_t tc_period; - - /* TC oversubscription */ - uint32_t tc_ov_wm; - uint32_t tc_ov_wm_min; - uint32_t tc_ov_wm_max; - uint8_t tc_ov_period_id; - uint8_t tc_ov; - uint32_t tc_ov_n; - double tc_ov_rate; - - /* Statistics */ - struct rte_sched_subport_stats stats; -}; - struct rte_sched_pipe_profile { /* Token bucket (TB) */ uint32_t tb_period; @@ -107,7 +80,6 @@ struct rte_sched_pipe { /* TC oversubscription */ uint32_t tc_ov_credits; uint8_t tc_ov_period_id; - uint8_t reserved[3]; } __rte_cache_aligned; struct rte_sched_queue { @@ -166,6 +138,72 @@ struct rte_sched_grinder { uint8_t wrr_cost[RTE_SCHED_BE_QUEUES_PER_PIPE]; }; +struct rte_sched_subport { + /* Token bucket (TB) */ + uint64_t tb_time; /* time of last update */ + uint32_t tb_period; + uint32_t tb_credits_per_period; + uint32_t tb_size; + uint32_t tb_credits; + + /* Traffic classes (TCs) */ + uint64_t tc_time; /* time of next update */ + uint32_t tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + uint32_t tc_credits[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + uint32_t tc_period; + + /* TC oversubscription */ + uint32_t tc_ov_wm; + uint32_t tc_ov_wm_min; + uint32_t tc_ov_wm_max; + uint8_t tc_ov_period_id; + uint8_t tc_ov; + uint32_t tc_ov_n; + double tc_ov_rate; + + /* Statistics */ + struct rte_sched_subport_stats stats; + + /* Subport pipes */ + uint32_t n_pipes_per_subport_enabled; + uint32_t n_pipe_profiles; + uint32_t n_max_pipe_profiles; + + /* Pipe best-effort TC rate */ + uint32_t pipe_tc_be_rate_max; + + /* Pipe queues size */ + uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + +#ifdef RTE_SCHED_RED + struct rte_red_config red_config[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; +#endif + + /* Scheduling loop detection */ + uint32_t pipe_loop; + uint32_t pipe_exhaustion; + + /* Bitmap */ + struct rte_bitmap *bmp; + uint32_t grinder_base_bmp_pos[RTE_SCHED_PORT_N_GRINDERS] __rte_aligned_16; + + /* Grinders */ + struct rte_sched_grinder grinder[RTE_SCHED_PORT_N_GRINDERS]; + uint32_t busy_grinders; + + /* Queue base calculation */ + uint32_t qsize_add[RTE_SCHED_QUEUES_PER_PIPE]; + uint32_t qsize_sum; + + struct rte_sched_pipe *pipe; + struct rte_sched_queue *queue; + struct rte_sched_queue_extra *queue_extra; + struct rte_sched_pipe_profile *pipe_profiles; + uint8_t *bmp_array; + struct rte_mbuf **queue_array; + uint8_t memory[0] __rte_cache_aligned; +} __rte_cache_aligned; + struct rte_sched_port { /* User parameters */ uint32_t n_subports_per_port; @@ -177,6 +215,7 @@ struct rte_sched_port { uint32_t rate; uint32_t mtu; uint32_t frame_overhead; + int socket; uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; uint32_t n_pipe_profiles; uint32_t n_max_pipe_profiles; @@ -210,6 +249,7 @@ struct rte_sched_port { uint32_t qsize_sum; /* Large data structures */ + struct rte_sched_subport *subports[0]; struct rte_sched_subport *subport; struct rte_sched_pipe *pipe; struct rte_sched_queue *queue; @@ -231,6 +271,16 @@ enum rte_sched_port_array { e_RTE_SCHED_PORT_ARRAY_TOTAL, }; +enum rte_sched_subport_array { + e_RTE_SCHED_SUBPORT_ARRAY_PIPE = 0, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_EXTRA, + e_RTE_SCHED_SUBPORT_ARRAY_PIPE_PROFILES, + e_RTE_SCHED_SUBPORT_ARRAY_BMP_ARRAY, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_ARRAY, + e_RTE_SCHED_SUBPORT_ARRAY_TOTAL, +}; + #ifdef RTE_SCHED_COLLECT_STATS static inline uint32_t -- 2.21.0
Remove pipes configuration from the port level to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 254 ++++++++++------------------------- 1 file changed, 71 insertions(+), 183 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 672412b77..952e449f7 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -291,6 +291,31 @@ rte_sched_port_queues_per_subport(struct rte_sched_port *port) #endif +static inline uint32_t +rte_sched_subport_pipe_queues(struct rte_sched_subport *subport) +{ + return RTE_SCHED_QUEUES_PER_PIPE * subport->n_pipes_per_subport_enabled; +} + +static inline struct rte_mbuf ** +rte_sched_subport_pipe_qbase(struct rte_sched_subport *subport, uint32_t qindex) +{ + uint32_t pindex = qindex >> 4; + uint32_t qpos = qindex & (RTE_SCHED_QUEUES_PER_PIPE - 1); + + return (subport->queue_array + pindex * + subport->qsize_sum + subport->qsize_add[qpos]); +} + +static inline uint16_t +rte_sched_subport_pipe_qsize(struct rte_sched_port *port, +struct rte_sched_subport *subport, uint32_t qindex) +{ + uint32_t tc = port->pipe_tc[qindex & (RTE_SCHED_QUEUES_PER_PIPE - 1)]; + + return subport->qsize[tc]; +} + static inline uint32_t rte_sched_port_queues_per_port(struct rte_sched_port *port) { @@ -414,8 +439,6 @@ pipe_profile_check(struct rte_sched_pipe_params *params, 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__); @@ -456,45 +479,10 @@ rte_sched_port_check_params(struct rte_sched_port_params *params) if (params->n_pipes_per_subport == 0 || !rte_is_power_of_2(params->n_pipes_per_subport)) { RTE_LOG(ERR, SCHED, - "%s: Incorrect value for pipes number\n", __func__); - return -EINVAL; - } - - /* qsize: if non-zero, power of 2, - * no bigger than 32K (due to 16-bit read/write pointers) - */ - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - uint16_t qsize = params->qsize[i]; - - if ((qsize != 0 && !rte_is_power_of_2(qsize)) || - ((i == RTE_SCHED_TRAFFIC_CLASS_BE) && (qsize == 0))) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tc rate\n", __func__); - return -EINVAL; - } - } - - /* pipe_profiles and n_pipe_profiles */ - if (params->pipe_profiles == NULL || - params->n_pipe_profiles == 0 || - params->n_pipe_profiles > params->n_max_pipe_profiles) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for number of pipe profiles\n", __func__); + "%s: Incorrect value for maximum pipes number\n", __func__); return -EINVAL; } - for (i = 0; i < params->n_pipe_profiles; i++) { - struct rte_sched_pipe_params *p = params->pipe_profiles + i; - int status; - - status = pipe_profile_check(p, params->rate, ¶ms->qsize[0]); - if (status != 0) { - RTE_LOG(ERR, SCHED, - "%s: Pipe profile check failed(%d)\n", __func__, status); - return -EINVAL; - } - } - return 0; } @@ -582,32 +570,6 @@ rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params) return size0 + size1; } -static void -rte_sched_port_config_qsize(struct rte_sched_port *port) -{ - uint32_t i; - - port->qsize_add[0] = 0; - - /* Strict prority traffic class */ - for (i = 1; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - port->qsize_add[i] = port->qsize_add[i-1] + port->qsize[i-1]; - - /* Best-effort traffic class */ - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 1] = - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE] + - port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 2] = - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 1] + - port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 3] = - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 2] + - port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; - - port->qsize_sum = port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 3] + - port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; -} - static void rte_sched_port_log_pipe_profile(struct rte_sched_port *port, uint32_t i) { @@ -717,56 +679,41 @@ rte_sched_pipe_profile_convert(struct rte_sched_port *port, dst->wrr_cost[3] = (uint8_t) wrr_cost[3]; } -static void -rte_sched_port_config_pipe_profile_table(struct rte_sched_port *port, - struct rte_sched_port_params *params) -{ - uint32_t i; - - for (i = 0; i < port->n_pipe_profiles; i++) { - struct rte_sched_pipe_params *src = params->pipe_profiles + i; - struct rte_sched_pipe_profile *dst = port->pipe_profiles + i; - - rte_sched_pipe_profile_convert(port, src, dst, params->rate); - rte_sched_port_log_pipe_profile(port, i); - } - - port->pipe_tc_be_rate_max = 0; - for (i = 0; i < port->n_pipe_profiles; i++) { - struct rte_sched_pipe_params *src = params->pipe_profiles + i; - uint32_t pipe_tc_be_rate = src->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; - - if (port->pipe_tc_be_rate_max < pipe_tc_be_rate) - port->pipe_tc_be_rate_max = pipe_tc_be_rate; - } -} - struct rte_sched_port * rte_sched_port_config(struct rte_sched_port_params *params) { struct rte_sched_port *port = NULL; - uint32_t mem_size, bmp_mem_size, n_queues_per_port, i, j, cycles_per_byte; + uint32_t size0, size1; + uint32_t cycles_per_byte; + uint32_t i, j; + int status; - /* Check user parameters. Determine the amount of memory to allocate */ - mem_size = rte_sched_port_get_memory_footprint(params); - if (mem_size == 0) + status = rte_sched_port_check_params(params); + if (status != 0) { + RTE_LOG(ERR, SCHED, + "%s: Port scheduler params check failed (%d)\n", + __func__, status); return NULL; + } + + size0 = sizeof(struct rte_sched_port); + size1 = params->n_subports_per_port * sizeof(struct rte_sched_subport *); /* Allocate memory to store the data structures */ - port = rte_zmalloc_socket("qos_params", mem_size, RTE_CACHE_LINE_SIZE, + port = rte_zmalloc_socket("qos_params", size0 + size1, RTE_CACHE_LINE_SIZE, params->socket); - if (port == NULL) - return NULL; + if (port == NULL) { + RTE_LOG(ERR, SCHED, "%s: Memory allocation fails\n", __func__); - /* compile time checks */ - RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS == 0); - RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS & (RTE_SCHED_PORT_N_GRINDERS - 1)); + return NULL; + } /* User parameters */ port->n_subports_per_port = params->n_subports_per_port; port->n_pipes_per_subport = params->n_pipes_per_subport; port->n_pipes_per_subport_log2 = __builtin_ctz(params->n_pipes_per_subport); + port->socket = params->socket; for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) port->pipe_queue[i] = i; @@ -787,32 +734,6 @@ rte_sched_port_config(struct rte_sched_port_params *params) port->rate = params->rate; port->mtu = params->mtu + params->frame_overhead; port->frame_overhead = params->frame_overhead; - memcpy(port->qsize, params->qsize, sizeof(params->qsize)); - port->n_pipe_profiles = params->n_pipe_profiles; - port->n_max_pipe_profiles = params->n_max_pipe_profiles; - -#ifdef RTE_SCHED_RED - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - uint32_t j; - - for (j = 0; j < RTE_COLORS; j++) { - /* if min/max are both zero, then RED is disabled */ - if ((params->red_params[i][j].min_th | - params->red_params[i][j].max_th) == 0) { - continue; - } - - if (rte_red_config_init(&port->red_config[i][j], - params->red_params[i][j].wq_log2, - params->red_params[i][j].min_th, - params->red_params[i][j].max_th, - params->red_params[i][j].maxp_inv) != 0) { - rte_free(port); - return NULL; - } - } - } -#endif /* Timing */ port->time_cpu_cycles = rte_get_tsc_cycles(); @@ -823,79 +744,32 @@ rte_sched_port_config(struct rte_sched_port_params *params) / params->rate; port->inv_cycles_per_byte = rte_reciprocal_value(cycles_per_byte); - /* Scheduling loop detection */ - port->pipe_loop = RTE_SCHED_PIPE_INVALID; - port->pipe_exhaustion = 0; - /* Grinders */ - port->busy_grinders = 0; port->pkts_out = NULL; port->n_pkts_out = 0; - /* Queue base calculation */ - rte_sched_port_config_qsize(port); - - /* Large data structures */ - port->subport = (struct rte_sched_subport *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_SUBPORT)); - port->pipe = (struct rte_sched_pipe *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_PIPE)); - port->queue = (struct rte_sched_queue *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_QUEUE)); - port->queue_extra = (struct rte_sched_queue_extra *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_QUEUE_EXTRA)); - port->pipe_profiles = (struct rte_sched_pipe_profile *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_PIPE_PROFILES)); - port->bmp_array = port->memory - + rte_sched_port_get_array_base(params, e_RTE_SCHED_PORT_ARRAY_BMP_ARRAY); - port->queue_array = (struct rte_mbuf **) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_QUEUE_ARRAY)); - - /* Pipe profile table */ - rte_sched_port_config_pipe_profile_table(port, params); - - /* Bitmap */ - n_queues_per_port = rte_sched_port_queues_per_port(port); - bmp_mem_size = rte_bitmap_get_memory_footprint(n_queues_per_port); - port->bmp = rte_bitmap_init(n_queues_per_port, port->bmp_array, - bmp_mem_size); - if (port->bmp == NULL) { - RTE_LOG(ERR, SCHED, "Bitmap init error\n"); - rte_free(port); - return NULL; - } - - for (i = 0; i < RTE_SCHED_PORT_N_GRINDERS; i++) - port->grinder_base_bmp_pos[i] = RTE_SCHED_PIPE_INVALID; - - return port; } -void -rte_sched_port_free(struct rte_sched_port *port) +static inline void +rte_sched_subport_free(struct rte_sched_port *port, + struct rte_sched_subport *subport) { + uint32_t n_subport_pipe_queues; uint32_t qindex; - uint32_t n_queues_per_port; - /* Check user parameters */ - if (port == NULL) + if (subport == NULL) return; - n_queues_per_port = rte_sched_port_queues_per_port(port); + n_subport_pipe_queues = rte_sched_subport_pipe_queues(subport); /* Free enqueued mbufs */ - for (qindex = 0; qindex < n_queues_per_port; qindex++) { - struct rte_mbuf **mbufs = rte_sched_port_qbase(port, qindex); - uint16_t qsize = rte_sched_port_qsize(port, qindex); + for (qindex = 0; qindex < n_subport_pipe_queues; qindex++) { + struct rte_mbuf **mbufs = + rte_sched_subport_pipe_qbase(subport, qindex); + uint16_t qsize = rte_sched_subport_pipe_qsize(port, subport, qindex); if (qsize != 0) { - struct rte_sched_queue *queue = port->queue + qindex; + struct rte_sched_queue *queue = subport->queue + qindex; uint16_t qr = queue->qr & (qsize - 1); uint16_t qw = queue->qw & (qsize - 1); @@ -904,7 +778,21 @@ rte_sched_port_free(struct rte_sched_port *port) } } - rte_bitmap_free(port->bmp); + rte_bitmap_free(subport->bmp); +} + +void +rte_sched_port_free(struct rte_sched_port *port) +{ + uint32_t i; + + /* Check user parameters */ + if (port == NULL) + return; + + for (i = 0; i < port->n_subports_per_port; i++) + rte_sched_subport_free(port, port->subports[i]); + rte_free(port); } -- 2.21.0
Add pipes configuration from the port level to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 388 ++++++++++++++++++++++++++++++----- 1 file changed, 332 insertions(+), 56 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 952e449f7..60dfc6232 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -550,24 +550,91 @@ rte_sched_port_get_array_base(struct rte_sched_port_params *params, enum rte_sch return base; } -uint32_t -rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params) +static uint32_t +rte_sched_subport_get_array_base(struct rte_sched_subport_params *params, + enum rte_sched_subport_array array) { - uint32_t size0, size1; - int status; + uint32_t n_pipes_per_subport = params->n_pipes_per_subport_enabled; + uint32_t n_subport_pipe_queues = + RTE_SCHED_QUEUES_PER_PIPE * n_pipes_per_subport; - status = rte_sched_port_check_params(params); - if (status != 0) { - RTE_LOG(NOTICE, SCHED, - "Port scheduler params check failed (%d)\n", status); + uint32_t size_pipe = n_pipes_per_subport * sizeof(struct rte_sched_pipe); + uint32_t size_queue = + n_subport_pipe_queues * sizeof(struct rte_sched_queue); + uint32_t size_queue_extra + = n_subport_pipe_queues * sizeof(struct rte_sched_queue_extra); + uint32_t size_pipe_profiles = params->n_max_pipe_profiles * + sizeof(struct rte_sched_pipe_profile); + uint32_t size_bmp_array = + rte_bitmap_get_memory_footprint(n_subport_pipe_queues); + uint32_t size_per_pipe_queue_array, size_queue_array; - return 0; + uint32_t base, i; + + size_per_pipe_queue_array = 0; + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + if (i < RTE_SCHED_TRAFFIC_CLASS_BE) + size_per_pipe_queue_array += + params->qsize[i] * sizeof(struct rte_mbuf *); + else + size_per_pipe_queue_array += RTE_SCHED_MAX_QUEUES_PER_TC * + params->qsize[i] * sizeof(struct rte_mbuf *); } + size_queue_array = n_pipes_per_subport * size_per_pipe_queue_array; - size0 = sizeof(struct rte_sched_port); - size1 = rte_sched_port_get_array_base(params, e_RTE_SCHED_PORT_ARRAY_TOTAL); + base = 0; - return size0 + size1; + if (array == e_RTE_SCHED_SUBPORT_ARRAY_PIPE) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_pipe); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_QUEUE) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_queue); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_EXTRA) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_queue_extra); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_PIPE_PROFILES) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_pipe_profiles); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_BMP_ARRAY) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_bmp_array); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_ARRAY) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_queue_array); + + return base; +} + +static void +rte_sched_subport_config_qsize(struct rte_sched_subport *subport) +{ + uint32_t i; + + subport->qsize_add[0] = 0; + + /* Strict prority traffic class */ + for (i = 1; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) + subport->qsize_add[i] = subport->qsize_add[i-1] + subport->qsize[i-1]; + + /* Best-effort traffic class */ + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 1] = + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE] + + subport->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 2] = + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 1] + + subport->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 3] = + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 2] + + subport->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; + + subport->qsize_sum = subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 3] + + subport->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; } static void @@ -679,6 +746,126 @@ rte_sched_pipe_profile_convert(struct rte_sched_port *port, dst->wrr_cost[3] = (uint8_t) wrr_cost[3]; } +static int +rte_sched_subport_check_params(struct rte_sched_subport_params *params, + uint32_t n_max_pipes_per_subport, + uint32_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; + } + + /* qsize: if non-zero, power of 2, + * no bigger than 32K (due to 16-bit read/write pointers) + */ + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + uint16_t qsize = params->qsize[i]; + + if (qsize != 0 && !rte_is_power_of_2(qsize)) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for qsize\n", __func__); + return -EINVAL; + } + } + + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + uint32_t tc_rate = params->tc_rate[i]; + uint16_t qsize = params->qsize[i]; + + if ((qsize == 0 && tc_rate != 0) || + (qsize != 0 && tc_rate == 0) || + (tc_rate > params->tb_rate)) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for tc rate\n", __func__); + return -EINVAL; + } + } + + if (params->qsize[RTE_SCHED_TRAFFIC_CLASS_BE] == 0 || + params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE] == 0) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect qsize or 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; + } + + /* n_pipes_per_subport: non-zero, power of 2 */ + if (params->n_pipes_per_subport_enabled == 0 || + params->n_pipes_per_subport_enabled > n_max_pipes_per_subport || + !rte_is_power_of_2(params->n_pipes_per_subport_enabled)) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for pipes number\n", __func__); + return -EINVAL; + } + + /* pipe_profiles and n_pipe_profiles */ + if (params->pipe_profiles == NULL || + params->n_pipe_profiles == 0 || + params->n_max_pipe_profiles == 0 || + params->n_pipe_profiles > params->n_max_pipe_profiles) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for pipe profiles\n", __func__); + return -EINVAL; + } + + for (i = 0; i < params->n_pipe_profiles; i++) { + struct rte_sched_pipe_params *p = params->pipe_profiles + i; + int status; + + status = pipe_profile_check(p, rate, ¶ms->qsize[0]); + if (status != 0) { + RTE_LOG(ERR, SCHED, + "%s: Pipe profile check failed(%d)\n", __func__, status); + return -EINVAL; + } + } + + return 0; +} + +uint32_t +rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params) +{ + uint32_t size0, size1; + int status; + + status = rte_sched_port_check_params(params); + if (status != 0) { + RTE_LOG(NOTICE, SCHED, + "Port scheduler params check failed (%d)\n", status); + + return 0; + } + + size0 = sizeof(struct rte_sched_port); + size1 = rte_sched_port_get_array_base(params, + e_RTE_SCHED_PORT_ARRAY_TOTAL); + + return size0 + size1; +} + struct rte_sched_port * rte_sched_port_config(struct rte_sched_port_params *params) { @@ -799,7 +986,7 @@ rte_sched_port_free(struct rte_sched_port *port) static void rte_sched_port_log_subport_config(struct rte_sched_port *port, uint32_t i) { - struct rte_sched_subport *s = port->subport + i; + struct rte_sched_subport *s = port->subports[i]; RTE_LOG(DEBUG, SCHED, "Low level config for subport %u:\n" " Token bucket: period = %u, credits per period = %u, size = %u\n" @@ -834,72 +1021,78 @@ rte_sched_port_log_subport_config(struct rte_sched_port *port, uint32_t i) s->tc_ov_wm_max); } +static void +rte_sched_free_memory(struct rte_sched_port *port, uint32_t n_subports) +{ + uint32_t i; + + for (i = 0; i < n_subports; i++) { + struct rte_sched_subport *subport = port->subports[i]; + + rte_sched_subport_free(port, subport); + } + + rte_free(port); +} + int rte_sched_subport_config(struct rte_sched_port *port, uint32_t subport_id, struct rte_sched_subport_params *params) { - struct rte_sched_subport *s; - uint32_t i; + struct rte_sched_subport *s = NULL; + uint32_t n_subports = subport_id; + uint32_t n_subport_pipe_queues, i; + uint32_t size0, size1, bmp_mem_size; + int status; /* Check user parameters */ if (port == NULL) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for parameter port\n", __func__); - return -EINVAL; + return 0; } if (subport_id >= port->n_subports_per_port) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for subport id\n", __func__); - return -EINVAL; - } - if (params == NULL) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for parameter params\n", __func__); + rte_sched_free_memory(port, n_subports); return -EINVAL; } - if (params->tb_rate == 0 || params->tb_rate > port->rate) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tb rate\n", __func__); - return -EINVAL; - } + status = rte_sched_subport_check_params(params, + port->n_pipes_per_subport, + port->rate); + if (status != 0) { + RTE_LOG(NOTICE, SCHED, + "%s: Port scheduler params check failed (%d)\n", + __func__, status); - if (params->tb_size == 0) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tb size\n", __func__); + rte_sched_free_memory(port, n_subports); return -EINVAL; } - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - uint32_t tc_rate = params->tc_rate[i]; - uint16_t qsize = port->qsize[i]; + /* Determine the amount of memory to allocate */ + size0 = sizeof(struct rte_sched_subport); + size1 = rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_TOTAL); - if ((qsize == 0 && tc_rate != 0) || - (qsize != 0 && tc_rate == 0) || - (tc_rate > params->tb_rate)) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tc rate\n", __func__); - return -EINVAL; - } - } - - if (port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE] == 0 || - params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE] == 0) { + /* Allocate memory to store the data structures */ + s = rte_zmalloc_socket("subport_params", size0 + size1, + RTE_CACHE_LINE_SIZE, port->socket); + if (s == NULL) { RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tc rate(best effort)\n", __func__); - return -EINVAL; - } + "%s: Memory allocation fails\n", __func__); - if (params->tc_period == 0) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tc period\n", __func__); - return -EINVAL; + rte_sched_free_memory(port, n_subports); + return -ENOMEM; } - s = port->subport + subport_id; + n_subports++; + + /* Port */ + port->subports[subport_id] = s; /* Token Bucket (TB) */ if (params->tb_rate == port->rate) { @@ -919,26 +1112,109 @@ rte_sched_subport_config(struct rte_sched_port *port, /* Traffic Classes (TCs) */ s->tc_period = rte_sched_time_ms_to_bytes(params->tc_period, port->rate); for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - if (port->qsize[i]) + if (params->qsize[i]) s->tc_credits_per_period[i] = rte_sched_time_ms_to_bytes(params->tc_period, - params->tc_rate[i]); - + params->tc_rate[i]); } s->tc_time = port->time + s->tc_period; for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - if (port->qsize[i]) + if (params->qsize[i]) s->tc_credits[i] = s->tc_credits_per_period[i]; + /* compile time checks */ + RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS == 0); + RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS & + (RTE_SCHED_PORT_N_GRINDERS - 1)); + + /* User parameters */ + s->n_pipes_per_subport_enabled = params->n_pipes_per_subport_enabled; + memcpy(s->qsize, params->qsize, sizeof(params->qsize)); + s->n_pipe_profiles = params->n_pipe_profiles; + s->n_max_pipe_profiles = params->n_max_pipe_profiles; + +#ifdef RTE_SCHED_RED + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + uint32_t j; + + for (j = 0; j < RTE_COLORS; j++) { + /* if min/max are both zero, then RED is disabled */ + if ((params->red_params[i][j].min_th | + params->red_params[i][j].max_th) == 0) { + continue; + } + + if (rte_red_config_init(&s->red_config[i][j], + params->red_params[i][j].wq_log2, + params->red_params[i][j].min_th, + params->red_params[i][j].max_th, + params->red_params[i][j].maxp_inv) != 0) { + rte_sched_free_memory(port, n_subports); + + RTE_LOG(NOTICE, SCHED, + "%s: RED configuration init fails\n", __func__); + return -EINVAL; + } + } + } +#endif + + /* Scheduling loop detection */ + s->pipe_loop = RTE_SCHED_PIPE_INVALID; + s->pipe_exhaustion = 0; + + /* Grinders */ + s->busy_grinders = 0; + + /* Queue base calculation */ + rte_sched_subport_config_qsize(s); + + /* Large data structures */ + s->pipe = (struct rte_sched_pipe *) + (s->memory + rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_PIPE)); + s->queue = (struct rte_sched_queue *) + (s->memory + rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE)); + s->queue_extra = (struct rte_sched_queue_extra *) + (s->memory + rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_EXTRA)); + s->pipe_profiles = (struct rte_sched_pipe_profile *) + (s->memory + rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_PIPE_PROFILES)); + s->bmp_array = s->memory + rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_BMP_ARRAY); + s->queue_array = (struct rte_mbuf **) + (s->memory + rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_ARRAY)); + + /* Bitmap */ + n_subport_pipe_queues = rte_sched_subport_pipe_queues(s); + bmp_mem_size = rte_bitmap_get_memory_footprint(n_subport_pipe_queues); + s->bmp = rte_bitmap_init(n_subport_pipe_queues, s->bmp_array, + bmp_mem_size); + if (s->bmp == NULL) { + RTE_LOG(ERR, SCHED, + "%s: Subport bitmap init error\n", __func__); + + rte_sched_free_memory(port, n_subports); + return -EINVAL; + } + + for (i = 0; i < RTE_SCHED_PORT_N_GRINDERS; i++) + s->grinder_base_bmp_pos[i] = RTE_SCHED_PIPE_INVALID; + +#ifdef RTE_SCHED_SUBPORT_TC_OV /* TC oversubscription */ s->tc_ov_wm_min = port->mtu; s->tc_ov_wm_max = rte_sched_time_ms_to_bytes(params->tc_period, - port->pipe_tc_be_rate_max); + s->pipe_tc_be_rate_max); s->tc_ov_wm = s->tc_ov_wm_max; s->tc_ov_period_id = 0; s->tc_ov = 0; s->tc_ov_n = 0; s->tc_ov_rate = 0; +#endif rte_sched_port_log_subport_config(port, subport_id); -- 2.21.0
Modify pipe level functions to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 103 +++++++++++++++++-------- lib/librte_sched/rte_sched.h | 7 +- lib/librte_sched/rte_sched_version.map | 2 +- 3 files changed, 76 insertions(+), 36 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 60dfc6232..6b6219e45 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -638,9 +638,9 @@ rte_sched_subport_config_qsize(struct rte_sched_subport *subport) } static void -rte_sched_port_log_pipe_profile(struct rte_sched_port *port, uint32_t i) +rte_sched_port_log_pipe_profile(struct rte_sched_subport *subport, uint32_t i) { - struct rte_sched_pipe_profile *p = port->pipe_profiles + i; + struct rte_sched_pipe_profile *p = subport->pipe_profiles + i; RTE_LOG(DEBUG, SCHED, "Low level config for pipe profile %u:\n" " Token bucket: period = %u, credits per period = %u, size = %u\n" @@ -689,7 +689,7 @@ rte_sched_time_ms_to_bytes(uint32_t time_ms, uint32_t rate) } static void -rte_sched_pipe_profile_convert(struct rte_sched_port *port, +rte_sched_pipe_profile_convert(struct rte_sched_subport *subport, struct rte_sched_pipe_params *src, struct rte_sched_pipe_profile *dst, uint32_t rate) @@ -718,7 +718,7 @@ rte_sched_pipe_profile_convert(struct rte_sched_port *port, rate); for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - if (port->qsize[i]) + if (subport->qsize[i]) dst->tc_credits_per_period[i] = rte_sched_time_ms_to_bytes(src->tc_period, src->tc_rate[i]); @@ -746,6 +746,30 @@ rte_sched_pipe_profile_convert(struct rte_sched_port *port, dst->wrr_cost[3] = (uint8_t) wrr_cost[3]; } +static void +rte_sched_subport_config_pipe_profile_table(struct rte_sched_subport *subport, + struct rte_sched_subport_params *params, uint32_t rate) +{ + uint32_t i; + + for (i = 0; i < subport->n_pipe_profiles; i++) { + struct rte_sched_pipe_params *src = params->pipe_profiles + i; + struct rte_sched_pipe_profile *dst = subport->pipe_profiles + i; + + rte_sched_pipe_profile_convert(subport, src, dst, rate); + rte_sched_port_log_pipe_profile(subport, i); + } + + subport->pipe_tc_be_rate_max = 0; + for (i = 0; i < subport->n_pipe_profiles; i++) { + struct rte_sched_pipe_params *src = params->pipe_profiles + i; + uint32_t pipe_tc_be_rate = src->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; + + if (subport->pipe_tc_be_rate_max < pipe_tc_be_rate) + subport->pipe_tc_be_rate_max = pipe_tc_be_rate; + } +} + static int rte_sched_subport_check_params(struct rte_sched_subport_params *params, uint32_t n_max_pipes_per_subport, @@ -1188,6 +1212,9 @@ rte_sched_subport_config(struct rte_sched_port *port, (s->memory + rte_sched_subport_get_array_base(params, e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_ARRAY)); + /* Pipe profile table */ + rte_sched_subport_config_pipe_profile_table(s, params, port->rate); + /* Bitmap */ n_subport_pipe_queues = rte_sched_subport_pipe_queues(s); bmp_mem_size = rte_bitmap_get_memory_footprint(n_subport_pipe_queues); @@ -1230,6 +1257,7 @@ rte_sched_pipe_config(struct rte_sched_port *port, struct rte_sched_subport *s; struct rte_sched_pipe *p; struct rte_sched_pipe_profile *params; + uint32_t n_subports = subport_id + 1; uint32_t deactivate, profile, i; /* Check user parameters */ @@ -1245,34 +1273,32 @@ rte_sched_pipe_config(struct rte_sched_port *port, if (subport_id >= port->n_subports_per_port) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for parameter subport id\n", __func__); + + rte_sched_free_memory(port, n_subports); return -EINVAL; } - if (pipe_id >= port->n_pipes_per_subport) { + s = port->subports[subport_id]; + if (pipe_id >= s->n_pipes_per_subport_enabled) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for parameter pipe id\n", __func__); + + rte_sched_free_memory(port, n_subports); return -EINVAL; } - if (!deactivate && profile >= port->n_pipe_profiles) { + if (!deactivate && profile >= s->n_pipe_profiles) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for parameter pipe profile\n", __func__); - return -EINVAL; - } - /* Check that subport configuration is valid */ - s = port->subport + subport_id; - if (s->tb_period == 0) { - RTE_LOG(ERR, SCHED, - "%s: Subport configuration invalid\n", __func__); + rte_sched_free_memory(port, n_subports); return -EINVAL; } - p = port->pipe + (subport_id * port->n_pipes_per_subport + pipe_id); - /* Handle the case when pipe already has a valid configuration */ + p = s->pipe + pipe_id; if (p->tb_time) { - params = port->pipe_profiles + p->profile; + params = s->pipe_profiles + p->profile; double subport_tc_be_rate = (double) s->tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASS_BE] @@ -1302,7 +1328,7 @@ rte_sched_pipe_config(struct rte_sched_port *port, /* Apply the new pipe configuration */ p->profile = profile; - params = port->pipe_profiles + p->profile; + params = s->pipe_profiles + p->profile; /* Token Bucket (TB) */ p->tb_time = port->time; @@ -1312,7 +1338,7 @@ rte_sched_pipe_config(struct rte_sched_port *port, p->tc_time = port->time + params->tc_period; for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - if (port->qsize[i]) + if (s->qsize[i]) p->tc_credits[i] = params->tc_credits_per_period[i]; { @@ -1342,10 +1368,12 @@ rte_sched_pipe_config(struct rte_sched_port *port, } int -rte_sched_port_pipe_profile_add(struct rte_sched_port *port, +rte_sched_subport_pipe_profile_add(struct rte_sched_port *port, + uint32_t subport_id, struct rte_sched_pipe_params *params, uint32_t *pipe_profile_id) { + struct rte_sched_subport *s; struct rte_sched_pipe_profile *pp; uint32_t i; int status; @@ -1357,40 +1385,49 @@ rte_sched_port_pipe_profile_add(struct rte_sched_port *port, return -EINVAL; } - /* Pipe profiles not exceeds the max limit */ - if (port->n_pipe_profiles >= port->n_max_pipe_profiles) { + /* Subport id not exceeds the max limit */ + if (subport_id > port->n_subports_per_port) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for subport id\n", __func__); + return -EINVAL; + } + + s = port->subports[subport_id]; + + /* Pipe profiles exceeds the max limit */ + if (s->n_pipe_profiles >= s->n_max_pipe_profiles) { RTE_LOG(ERR, SCHED, "%s: Number of pipe profiles exceeds the max limit\n", __func__); return -EINVAL; } /* Pipe params */ - status = pipe_profile_check(params, port->rate, &port->qsize[0]); + status = pipe_profile_check(params, port->rate, &s->qsize[0]); if (status != 0) { RTE_LOG(ERR, SCHED, "%s: Pipe profile check failed(%d)\n", __func__, status); return -EINVAL; } - pp = &port->pipe_profiles[port->n_pipe_profiles]; - rte_sched_pipe_profile_convert(port, params, pp, port->rate); + pp = &s->pipe_profiles[s->n_pipe_profiles]; + rte_sched_pipe_profile_convert(s, params, pp, port->rate); - /* Pipe profile not exists */ - for (i = 0; i < port->n_pipe_profiles; i++) - if (memcmp(port->pipe_profiles + i, pp, sizeof(*pp)) == 0) { + /* Pipe profile should not exists */ + for (i = 0; i < s->n_pipe_profiles; i++) + if (memcmp(s->pipe_profiles + i, pp, sizeof(*pp)) == 0) { RTE_LOG(ERR, SCHED, - "%s: Pipe profile doesn't exist\n", __func__); + "%s: Pipe profile exists\n", __func__); return -EINVAL; } /* Pipe profile commit */ - *pipe_profile_id = port->n_pipe_profiles; - port->n_pipe_profiles++; + *pipe_profile_id = s->n_pipe_profiles; + s->n_pipe_profiles++; - if (port->pipe_tc_be_rate_max < params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]) - port->pipe_tc_be_rate_max = params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; + if (s->pipe_tc_be_rate_max < params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]) + s->pipe_tc_be_rate_max = params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; - rte_sched_port_log_pipe_profile(port, *pipe_profile_id); + rte_sched_port_log_pipe_profile(s, *pipe_profile_id); return 0; } diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index fbb0e23fa..5001f09ed 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -317,6 +317,8 @@ rte_sched_port_free(struct rte_sched_port *port); * * @param port * Handle to port scheduler instance + * @param subport_id + * Subport ID * @param params * Pipe profile parameters * @param pipe_profile_id @@ -326,7 +328,8 @@ rte_sched_port_free(struct rte_sched_port *port); */ __rte_experimental int -rte_sched_port_pipe_profile_add(struct rte_sched_port *port, +rte_sched_subport_pipe_profile_add(struct rte_sched_port *port, + uint32_t subport_id, struct rte_sched_pipe_params *params, uint32_t *pipe_profile_id); @@ -357,7 +360,7 @@ rte_sched_subport_config(struct rte_sched_port *port, * @param pipe_id * Pipe ID within subport * @param pipe_profile - * ID of port-level pre-configured pipe profile + * ID of subport-level pre-configured pipe profile * @return * 0 upon success, error code otherwise */ diff --git a/lib/librte_sched/rte_sched_version.map b/lib/librte_sched/rte_sched_version.map index 729588794..f33761e63 100644 --- a/lib/librte_sched/rte_sched_version.map +++ b/lib/librte_sched/rte_sched_version.map @@ -33,5 +33,5 @@ DPDK_2.1 { EXPERIMENTAL { global: - rte_sched_port_pipe_profile_add; + rte_sched_subport_pipe_profile_add; }; -- 2.21.0
Modify scheduler packet enqueue operation of the scheduler to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 277 ++++++++++++++++++++++------------- 1 file changed, 178 insertions(+), 99 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 6b6219e45..a8174afad 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -1440,10 +1440,11 @@ rte_sched_port_qindex(struct rte_sched_port *port, 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) | - ((rte_sched_port_pipe_queue(port, traffic_class) + queue) & - (RTE_SCHED_QUEUES_PER_PIPE - 1)); + (port->n_pipes_per_subport_log2 + 4)) | + ((pipe & + (port->subports[subport]->n_pipes_per_subport_enabled - 1)) << 4) | + ((rte_sched_port_pipe_queue(port, traffic_class) + queue) & + (RTE_SCHED_QUEUES_PER_PIPE - 1)); } void @@ -1468,7 +1469,8 @@ rte_sched_port_pkt_read_tree_path(struct rte_sched_port *port, uint32_t queue_id = rte_mbuf_sched_queue_get(pkt); *subport = queue_id >> (port->n_pipes_per_subport_log2 + 4); - *pipe = (queue_id >> 4) & (port->n_pipes_per_subport - 1); + *pipe = (queue_id >> 4) & + (port->subports[*subport]->n_pipes_per_subport_enabled - 1); *traffic_class = rte_sched_port_pipe_tc(port, queue_id); *queue = rte_sched_port_tc_queue(port, queue_id); } @@ -1512,7 +1514,7 @@ rte_sched_subport_read_stats(struct rte_sched_port *port, return -EINVAL; } - s = port->subport + subport_id; + s = port->subports[subport_id]; /* Copy subport stats and clear */ memcpy(stats, &s->stats, sizeof(struct rte_sched_subport_stats)); @@ -1585,43 +1587,50 @@ rte_sched_port_queue_is_empty(struct rte_sched_port *port, uint32_t qindex) #ifdef RTE_SCHED_COLLECT_STATS static inline void -rte_sched_port_update_subport_stats(struct rte_sched_port *port, uint32_t qindex, struct rte_mbuf *pkt) +rte_sched_port_update_subport_stats(struct rte_sched_port *port, + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt) { - struct rte_sched_subport *s = port->subport + (qindex / rte_sched_port_queues_per_subport(port)); uint32_t tc_index = rte_sched_port_pipe_tc(port, qindex); uint32_t pkt_len = pkt->pkt_len; - s->stats.n_pkts_tc[tc_index] += 1; - s->stats.n_bytes_tc[tc_index] += pkt_len; + subport->stats.n_pkts_tc[tc_index] += 1; + subport->stats.n_bytes_tc[tc_index] += pkt_len; } #ifdef RTE_SCHED_RED static inline void rte_sched_port_update_subport_stats_on_drop(struct rte_sched_port *port, - uint32_t qindex, - struct rte_mbuf *pkt, uint32_t red) + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt, + uint32_t red) #else static inline void rte_sched_port_update_subport_stats_on_drop(struct rte_sched_port *port, - uint32_t qindex, - struct rte_mbuf *pkt, __rte_unused uint32_t red) + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt, + __rte_unused uint32_t red) #endif { - struct rte_sched_subport *s = port->subport + (qindex / rte_sched_port_queues_per_subport(port)); uint32_t tc_index = rte_sched_port_pipe_tc(port, qindex); uint32_t pkt_len = pkt->pkt_len; - s->stats.n_pkts_tc_dropped[tc_index] += 1; - s->stats.n_bytes_tc_dropped[tc_index] += pkt_len; + subport->stats.n_pkts_tc_dropped[tc_index] += 1; + subport->stats.n_bytes_tc_dropped[tc_index] += pkt_len; #ifdef RTE_SCHED_RED - s->stats.n_pkts_red_dropped[tc_index] += red; + subport->stats.n_pkts_red_dropped[tc_index] += red; #endif } static inline void -rte_sched_port_update_queue_stats(struct rte_sched_port *port, uint32_t qindex, struct rte_mbuf *pkt) +rte_sched_port_update_queue_stats(struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt) { - struct rte_sched_queue_extra *qe = port->queue_extra + qindex; + struct rte_sched_queue_extra *qe = subport->queue_extra + qindex; uint32_t pkt_len = pkt->pkt_len; qe->stats.n_pkts += 1; @@ -1630,17 +1639,19 @@ rte_sched_port_update_queue_stats(struct rte_sched_port *port, uint32_t qindex, #ifdef RTE_SCHED_RED static inline void -rte_sched_port_update_queue_stats_on_drop(struct rte_sched_port *port, - uint32_t qindex, - struct rte_mbuf *pkt, uint32_t red) +rte_sched_port_update_queue_stats_on_drop(struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt, + uint32_t red) #else static inline void -rte_sched_port_update_queue_stats_on_drop(struct rte_sched_port *port, - uint32_t qindex, - struct rte_mbuf *pkt, __rte_unused uint32_t red) +rte_sched_port_update_queue_stats_on_drop(struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt, + __rte_unused uint32_t red) #endif { - struct rte_sched_queue_extra *qe = port->queue_extra + qindex; + struct rte_sched_queue_extra *qe = subport->queue_extra + qindex; uint32_t pkt_len = pkt->pkt_len; qe->stats.n_pkts_dropped += 1; @@ -1655,7 +1666,11 @@ rte_sched_port_update_queue_stats_on_drop(struct rte_sched_port *port, #ifdef RTE_SCHED_RED static inline int -rte_sched_port_red_drop(struct rte_sched_port *port, struct rte_mbuf *pkt, uint32_t qindex, uint16_t qlen) +rte_sched_port_red_drop(struct rte_sched_port *port, + struct rte_sched_subport *subport, + struct rte_mbuf *pkt, + uint32_t qindex, + uint16_t qlen) { struct rte_sched_queue_extra *qe; struct rte_red_config *red_cfg; @@ -1665,12 +1680,12 @@ rte_sched_port_red_drop(struct rte_sched_port *port, struct rte_mbuf *pkt, uint3 tc_index = rte_sched_port_pipe_tc(port, qindex); color = rte_sched_port_pkt_read_color(pkt); - red_cfg = &port->red_config[tc_index][color]; + red_cfg = &subport->red_config[tc_index][color]; if ((red_cfg->min_th | red_cfg->max_th) == 0) return 0; - qe = port->queue_extra + qindex; + qe = subport->queue_extra + qindex; red = &qe->red; return rte_red_enqueue(red_cfg, red, qlen, port->time); @@ -1687,7 +1702,14 @@ rte_sched_port_set_queue_empty_timestamp(struct rte_sched_port *port, uint32_t q #else -#define rte_sched_port_red_drop(port, pkt, qindex, qlen) 0 +static inline int rte_sched_port_red_drop(struct rte_sched_port *port __rte_unused, + struct rte_sched_subport *subport __rte_unused, + struct rte_mbuf *pkt __rte_unused, + uint32_t qindex __rte_unused, + uint16_t qlen __rte_unused) +{ + return 0; +} #define rte_sched_port_set_queue_empty_timestamp(port, qindex) @@ -1722,63 +1744,79 @@ debug_check_queue_slab(struct rte_sched_port *port, uint32_t bmp_pos, #endif /* RTE_SCHED_DEBUG */ +static inline struct rte_sched_subport * +rte_sched_port_subport(struct rte_sched_port *port, + struct rte_mbuf *pkt) +{ + uint32_t queue_id = rte_mbuf_sched_queue_get(pkt); + uint32_t subport_id = queue_id >> (port->n_pipes_per_subport_log2 + 4); + + return port->subports[subport_id]; +} + static inline uint32_t -rte_sched_port_enqueue_qptrs_prefetch0(struct rte_sched_port *port, - struct rte_mbuf *pkt) +rte_sched_port_enqueue_qptrs_prefetch0(struct rte_sched_subport *subport, + struct rte_mbuf *pkt, uint32_t subport_qmask) { struct rte_sched_queue *q; #ifdef RTE_SCHED_COLLECT_STATS struct rte_sched_queue_extra *qe; #endif uint32_t qindex = rte_mbuf_sched_queue_get(pkt); + uint32_t subport_queue_id = subport_qmask & qindex; - q = port->queue + qindex; + q = subport->queue + subport_queue_id; rte_prefetch0(q); #ifdef RTE_SCHED_COLLECT_STATS - qe = port->queue_extra + qindex; + qe = subport->queue_extra + subport_queue_id; rte_prefetch0(qe); #endif - return qindex; + return subport_queue_id; } static inline void rte_sched_port_enqueue_qwa_prefetch0(struct rte_sched_port *port, - uint32_t qindex, struct rte_mbuf **qbase) + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf **qbase) { struct rte_sched_queue *q; struct rte_mbuf **q_qw; uint16_t qsize; - q = port->queue + qindex; - qsize = rte_sched_port_qsize(port, qindex); + q = subport->queue + qindex; + qsize = rte_sched_subport_pipe_qsize(port, subport, qindex); q_qw = qbase + (q->qw & (qsize - 1)); rte_prefetch0(q_qw); - rte_bitmap_prefetch0(port->bmp, qindex); + rte_bitmap_prefetch0(subport->bmp, qindex); } static inline int -rte_sched_port_enqueue_qwa(struct rte_sched_port *port, uint32_t qindex, - struct rte_mbuf **qbase, struct rte_mbuf *pkt) +rte_sched_port_enqueue_qwa(struct rte_sched_port *port, + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf **qbase, + struct rte_mbuf *pkt) { struct rte_sched_queue *q; uint16_t qsize; uint16_t qlen; - q = port->queue + qindex; - qsize = rte_sched_port_qsize(port, qindex); + q = subport->queue + qindex; + qsize = rte_sched_subport_pipe_qsize(port, subport, qindex); qlen = q->qw - q->qr; /* Drop the packet (and update drop stats) when queue is full */ - if (unlikely(rte_sched_port_red_drop(port, pkt, qindex, qlen) || + if (unlikely(rte_sched_port_red_drop(port, subport, pkt, qindex, qlen) || (qlen >= qsize))) { rte_pktmbuf_free(pkt); #ifdef RTE_SCHED_COLLECT_STATS - rte_sched_port_update_subport_stats_on_drop(port, qindex, pkt, - qlen < qsize); - rte_sched_port_update_queue_stats_on_drop(port, qindex, pkt, - qlen < qsize); + rte_sched_port_update_subport_stats_on_drop(port, subport, + qindex, pkt, qlen < qsize); + rte_sched_port_update_queue_stats_on_drop(subport, qindex, pkt, + qlen < qsize); #endif return 0; } @@ -1787,13 +1825,13 @@ rte_sched_port_enqueue_qwa(struct rte_sched_port *port, uint32_t qindex, qbase[q->qw & (qsize - 1)] = pkt; q->qw++; - /* Activate queue in the port bitmap */ - rte_bitmap_set(port->bmp, qindex); + /* Activate queue in the subport bitmap */ + rte_bitmap_set(subport->bmp, qindex); /* Statistics */ #ifdef RTE_SCHED_COLLECT_STATS - rte_sched_port_update_subport_stats(port, qindex, pkt); - rte_sched_port_update_queue_stats(port, qindex, pkt); + rte_sched_port_update_subport_stats(port, subport, qindex, pkt); + rte_sched_port_update_queue_stats(subport, qindex, pkt); #endif return 1; @@ -1821,17 +1859,22 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, *pkt30, *pkt31, *pkt_last; struct rte_mbuf **q00_base, **q01_base, **q10_base, **q11_base, **q20_base, **q21_base, **q30_base, **q31_base, **q_last_base; + struct rte_sched_subport *subport00, *subport01, *subport10, *subport11, + *subport20, *subport21, *subport30, *subport31, *subport_last; uint32_t q00, q01, q10, q11, q20, q21, q30, q31, q_last; uint32_t r00, r01, r10, r11, r20, r21, r30, r31, r_last; + uint32_t subport_qmask; uint32_t result, i; result = 0; + subport_qmask = (1 << (port->n_pipes_per_subport_log2 + 4)) - 1; /* * Less then 6 input packets available, which is not enough to * feed the pipeline */ if (unlikely(n_pkts < 6)) { + struct rte_sched_subport *subports[5]; struct rte_mbuf **q_base[5]; uint32_t q[5]; @@ -1839,22 +1882,26 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, for (i = 0; i < n_pkts; i++) rte_prefetch0(pkts[i]); + /* Prefetch the subport structure for each packet */ + for (i = 0; i < n_pkts; i++) + subports[i] = rte_sched_port_subport(port, pkts[i]); + /* Prefetch the queue structure for each queue */ for (i = 0; i < n_pkts; i++) - q[i] = rte_sched_port_enqueue_qptrs_prefetch0(port, - pkts[i]); + q[i] = rte_sched_port_enqueue_qptrs_prefetch0(subports[i], + pkts[i], subport_qmask); /* Prefetch the write pointer location of each queue */ for (i = 0; i < n_pkts; i++) { - q_base[i] = rte_sched_port_qbase(port, q[i]); - rte_sched_port_enqueue_qwa_prefetch0(port, q[i], - q_base[i]); + q_base[i] = rte_sched_subport_pipe_qbase(subports[i], q[i]); + rte_sched_port_enqueue_qwa_prefetch0(port, subports[i], + q[i], q_base[i]); } /* Write each packet to its queue */ for (i = 0; i < n_pkts; i++) - result += rte_sched_port_enqueue_qwa(port, q[i], - q_base[i], pkts[i]); + result += rte_sched_port_enqueue_qwa(port, subports[i], + q[i], q_base[i], pkts[i]); return result; } @@ -1870,21 +1917,29 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, rte_prefetch0(pkt10); rte_prefetch0(pkt11); - q20 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt20); - q21 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt21); + subport20 = rte_sched_port_subport(port, pkt20); + subport21 = rte_sched_port_subport(port, pkt21); + q20 = rte_sched_port_enqueue_qptrs_prefetch0(subport20, + pkt20, subport_qmask); + q21 = rte_sched_port_enqueue_qptrs_prefetch0(subport21, + pkt21, subport_qmask); pkt00 = pkts[4]; pkt01 = pkts[5]; rte_prefetch0(pkt00); rte_prefetch0(pkt01); - q10 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt10); - q11 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt11); + subport10 = rte_sched_port_subport(port, pkt10); + subport11 = rte_sched_port_subport(port, pkt11); + q10 = rte_sched_port_enqueue_qptrs_prefetch0(subport10, + pkt10, subport_qmask); + q11 = rte_sched_port_enqueue_qptrs_prefetch0(subport11, + pkt11, subport_qmask); - q20_base = rte_sched_port_qbase(port, q20); - q21_base = rte_sched_port_qbase(port, q21); - rte_sched_port_enqueue_qwa_prefetch0(port, q20, q20_base); - rte_sched_port_enqueue_qwa_prefetch0(port, q21, q21_base); + q20_base = rte_sched_subport_pipe_qbase(subport20, q20); + q21_base = rte_sched_subport_pipe_qbase(subport21, q21); + rte_sched_port_enqueue_qwa_prefetch0(port, subport20, q20, q20_base); + rte_sched_port_enqueue_qwa_prefetch0(port, subport21, q21, q21_base); /* Run the pipeline */ for (i = 6; i < (n_pkts & (~1)); i += 2) { @@ -1899,6 +1954,10 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, q31 = q21; q20 = q10; q21 = q11; + subport30 = subport20; + subport31 = subport21; + subport20 = subport10; + subport21 = subport11; q30_base = q20_base; q31_base = q21_base; @@ -1908,19 +1967,25 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, rte_prefetch0(pkt00); rte_prefetch0(pkt01); - /* Stage 1: Prefetch queue structure storing queue pointers */ - q10 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt10); - q11 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt11); + /* Stage 1: Prefetch subport and queue structure storing queue pointers */ + subport10 = rte_sched_port_subport(port, pkt10); + subport11 = rte_sched_port_subport(port, pkt11); + q10 = rte_sched_port_enqueue_qptrs_prefetch0(subport10, + pkt10, subport_qmask); + q11 = rte_sched_port_enqueue_qptrs_prefetch0(subport11, + pkt11, subport_qmask); /* Stage 2: Prefetch queue write location */ - q20_base = rte_sched_port_qbase(port, q20); - q21_base = rte_sched_port_qbase(port, q21); - rte_sched_port_enqueue_qwa_prefetch0(port, q20, q20_base); - rte_sched_port_enqueue_qwa_prefetch0(port, q21, q21_base); + q20_base = rte_sched_subport_pipe_qbase(subport20, q20); + q21_base = rte_sched_subport_pipe_qbase(subport21, q21); + rte_sched_port_enqueue_qwa_prefetch0(port, subport20, q20, q20_base); + rte_sched_port_enqueue_qwa_prefetch0(port, subport21, q21, q21_base); /* Stage 3: Write packet to queue and activate queue */ - r30 = rte_sched_port_enqueue_qwa(port, q30, q30_base, pkt30); - r31 = rte_sched_port_enqueue_qwa(port, q31, q31_base, pkt31); + r30 = rte_sched_port_enqueue_qwa(port, subport30, + q30, q30_base, pkt30); + r31 = rte_sched_port_enqueue_qwa(port, subport31, + q31, q31_base, pkt31); result += r30 + r31; } @@ -1932,38 +1997,52 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, pkt_last = pkts[n_pkts - 1]; rte_prefetch0(pkt_last); - q00 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt00); - q01 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt01); - - q10_base = rte_sched_port_qbase(port, q10); - q11_base = rte_sched_port_qbase(port, q11); - rte_sched_port_enqueue_qwa_prefetch0(port, q10, q10_base); - rte_sched_port_enqueue_qwa_prefetch0(port, q11, q11_base); - - r20 = rte_sched_port_enqueue_qwa(port, q20, q20_base, pkt20); - r21 = rte_sched_port_enqueue_qwa(port, q21, q21_base, pkt21); + subport00 = rte_sched_port_subport(port, pkt00); + subport01 = rte_sched_port_subport(port, pkt01); + q00 = rte_sched_port_enqueue_qptrs_prefetch0(subport00, + pkt00, subport_qmask); + q01 = rte_sched_port_enqueue_qptrs_prefetch0(subport01, + pkt01, subport_qmask); + + q10_base = rte_sched_subport_pipe_qbase(subport10, q10); + q11_base = rte_sched_subport_pipe_qbase(subport11, q11); + rte_sched_port_enqueue_qwa_prefetch0(port, subport10, q10, q10_base); + rte_sched_port_enqueue_qwa_prefetch0(port, subport11, q11, q11_base); + + r20 = rte_sched_port_enqueue_qwa(port, subport20, + q20, q20_base, pkt20); + r21 = rte_sched_port_enqueue_qwa(port, subport21, + q21, q21_base, pkt21); result += r20 + r21; - q_last = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt_last); + subport_last = rte_sched_port_subport(port, pkt_last); + q_last = rte_sched_port_enqueue_qptrs_prefetch0(subport_last, + pkt_last, subport_qmask); - q00_base = rte_sched_port_qbase(port, q00); - q01_base = rte_sched_port_qbase(port, q01); - rte_sched_port_enqueue_qwa_prefetch0(port, q00, q00_base); - rte_sched_port_enqueue_qwa_prefetch0(port, q01, q01_base); + q00_base = rte_sched_subport_pipe_qbase(subport00, q00); + q01_base = rte_sched_subport_pipe_qbase(subport01, q01); + rte_sched_port_enqueue_qwa_prefetch0(port, subport00, q00, q00_base); + rte_sched_port_enqueue_qwa_prefetch0(port, subport01, q01, q01_base); - r10 = rte_sched_port_enqueue_qwa(port, q10, q10_base, pkt10); - r11 = rte_sched_port_enqueue_qwa(port, q11, q11_base, pkt11); + r10 = rte_sched_port_enqueue_qwa(port, subport10, q10, + q10_base, pkt10); + r11 = rte_sched_port_enqueue_qwa(port, subport11, q11, + q11_base, pkt11); result += r10 + r11; - q_last_base = rte_sched_port_qbase(port, q_last); - rte_sched_port_enqueue_qwa_prefetch0(port, q_last, q_last_base); + q_last_base = rte_sched_subport_pipe_qbase(subport_last, q_last); + rte_sched_port_enqueue_qwa_prefetch0(port, subport_last, + q_last, q_last_base); - r00 = rte_sched_port_enqueue_qwa(port, q00, q00_base, pkt00); - r01 = rte_sched_port_enqueue_qwa(port, q01, q01_base, pkt01); + r00 = rte_sched_port_enqueue_qwa(port, subport00, q00, + q00_base, pkt00); + r01 = rte_sched_port_enqueue_qwa(port, subport01, q01, + q01_base, pkt01); result += r00 + r01; if (n_pkts & 1) { - r_last = rte_sched_port_enqueue_qwa(port, q_last, q_last_base, pkt_last); + r_last = rte_sched_port_enqueue_qwa(port, subport_last, + q_last, q_last_base, pkt_last); result += r_last; } -- 2.21.0
Update memory footprint compute function for allowing subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 100 ++++++++++------------------------- lib/librte_sched/rte_sched.h | 8 +-- 2 files changed, 34 insertions(+), 74 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index a8174afad..58f34359c 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -486,70 +486,6 @@ rte_sched_port_check_params(struct rte_sched_port_params *params) return 0; } -static uint32_t -rte_sched_port_get_array_base(struct rte_sched_port_params *params, enum rte_sched_port_array array) -{ - uint32_t n_subports_per_port = params->n_subports_per_port; - uint32_t n_pipes_per_subport = params->n_pipes_per_subport; - uint32_t n_pipes_per_port = n_pipes_per_subport * n_subports_per_port; - uint32_t n_queues_per_port = RTE_SCHED_QUEUES_PER_PIPE * n_pipes_per_subport * n_subports_per_port; - - uint32_t size_subport = n_subports_per_port * sizeof(struct rte_sched_subport); - uint32_t size_pipe = n_pipes_per_port * sizeof(struct rte_sched_pipe); - uint32_t size_queue = n_queues_per_port * sizeof(struct rte_sched_queue); - uint32_t size_queue_extra - = n_queues_per_port * sizeof(struct rte_sched_queue_extra); - uint32_t size_pipe_profiles - = params->n_max_pipe_profiles * sizeof(struct rte_sched_pipe_profile); - uint32_t size_bmp_array = rte_bitmap_get_memory_footprint(n_queues_per_port); - uint32_t size_per_pipe_queue_array, size_queue_array; - - uint32_t base, i; - - size_per_pipe_queue_array = 0; - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - if (i < RTE_SCHED_TRAFFIC_CLASS_BE) - size_per_pipe_queue_array += - params->qsize[i] * sizeof(struct rte_mbuf *); - else - size_per_pipe_queue_array += RTE_SCHED_MAX_QUEUES_PER_TC * - params->qsize[i] * sizeof(struct rte_mbuf *); - } - size_queue_array = n_pipes_per_port * size_per_pipe_queue_array; - - base = 0; - - if (array == e_RTE_SCHED_PORT_ARRAY_SUBPORT) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_subport); - - if (array == e_RTE_SCHED_PORT_ARRAY_PIPE) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_pipe); - - if (array == e_RTE_SCHED_PORT_ARRAY_QUEUE) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_queue); - - if (array == e_RTE_SCHED_PORT_ARRAY_QUEUE_EXTRA) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_queue_extra); - - if (array == e_RTE_SCHED_PORT_ARRAY_PIPE_PROFILES) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_pipe_profiles); - - if (array == e_RTE_SCHED_PORT_ARRAY_BMP_ARRAY) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_bmp_array); - - if (array == e_RTE_SCHED_PORT_ARRAY_QUEUE_ARRAY) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_queue_array); - - return base; -} - static uint32_t rte_sched_subport_get_array_base(struct rte_sched_subport_params *params, enum rte_sched_subport_array array) @@ -870,22 +806,44 @@ rte_sched_subport_check_params(struct rte_sched_subport_params *params, } uint32_t -rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params) +rte_sched_port_get_memory_footprint(struct rte_sched_port_params *port_params, + struct rte_sched_subport_params **subport_params) { - uint32_t size0, size1; + uint32_t size0 = 0, size1 = 0, i; int status; - status = rte_sched_port_check_params(params); + status = rte_sched_port_check_params(port_params); if (status != 0) { - RTE_LOG(NOTICE, SCHED, - "Port scheduler params check failed (%d)\n", status); + RTE_LOG(ERR, SCHED, + "%s: Port scheduler port params check failed (%d)\n", + __func__, status); return 0; } + for (i = 0; i < port_params->n_subports_per_port; i++) { + struct rte_sched_subport_params *sp = subport_params[i]; + + status = rte_sched_subport_check_params(sp, + port_params->n_pipes_per_subport, + port_params->rate); + if (status != 0) { + RTE_LOG(ERR, SCHED, + "%s: Port scheduler subport params check failed (%d)\n", + __func__, status); + + return 0; + } + } + size0 = sizeof(struct rte_sched_port); - size1 = rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_TOTAL); + + for (i = 0; i < port_params->n_subports_per_port; i++) { + struct rte_sched_subport_params *sp = subport_params[i]; + + size1 += rte_sched_subport_get_array_base(sp, + e_RTE_SCHED_SUBPORT_ARRAY_TOTAL); + } return size0 + size1; } diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index 5001f09ed..40f02f124 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -373,14 +373,16 @@ rte_sched_pipe_config(struct rte_sched_port *port, /** * Hierarchical scheduler memory footprint size per port * - * @param params + * @param port_params * Port scheduler configuration parameter structure + * @param subport_params + * Array of subport parameter structures * @return * Memory footprint size in bytes upon success, 0 otherwise */ uint32_t -rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params); - +rte_sched_port_get_memory_footprint(struct rte_sched_port_params *port_params, + struct rte_sched_subport_params **subport_params); /* * Statistics * -- 2.21.0
Modify packet grinder functions of the schedule to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 223 +++++++++++++++++------------------ 1 file changed, 106 insertions(+), 117 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 58f34359c..d7abe9661 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -322,24 +322,6 @@ rte_sched_port_queues_per_port(struct rte_sched_port *port) return RTE_SCHED_QUEUES_PER_PIPE * port->n_pipes_per_subport * port->n_subports_per_port; } -static inline struct rte_mbuf ** -rte_sched_port_qbase(struct rte_sched_port *port, uint32_t qindex) -{ - uint32_t pindex = qindex >> 4; - uint32_t qpos = qindex & 0xF; - - return (port->queue_array + pindex * - port->qsize_sum + port->qsize_add[qpos]); -} - -static inline uint16_t -rte_sched_port_qsize(struct rte_sched_port *port, uint32_t qindex) -{ - uint32_t tc = port->pipe_tc[qindex & (RTE_SCHED_QUEUES_PER_PIPE - 1)]; - - return port->qsize[tc]; -} - static inline uint16_t rte_sched_port_pipe_queue(struct rte_sched_port *port, uint32_t traffic_class) { @@ -1533,9 +1515,10 @@ rte_sched_queue_read_stats(struct rte_sched_port *port, #ifdef RTE_SCHED_DEBUG static inline int -rte_sched_port_queue_is_empty(struct rte_sched_port *port, uint32_t qindex) +rte_sched_port_queue_is_empty(struct rte_sched_subport *subport, + uint32_t qindex) { - struct rte_sched_queue *queue = port->queue + qindex; + struct rte_sched_queue *queue = subport->queue + qindex; return queue->qr == queue->qw; } @@ -1650,9 +1633,10 @@ rte_sched_port_red_drop(struct rte_sched_port *port, } static inline void -rte_sched_port_set_queue_empty_timestamp(struct rte_sched_port *port, uint32_t qindex) +rte_sched_port_set_queue_empty_timestamp(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t qindex) { - struct rte_sched_queue_extra *qe = port->queue_extra + qindex; + struct rte_sched_queue_extra *qe = subport->queue_extra + qindex; struct rte_red *red = &qe->red; rte_red_mark_queue_empty(red, port->time); @@ -1669,14 +1653,14 @@ static inline int rte_sched_port_red_drop(struct rte_sched_port *port __rte_unus return 0; } -#define rte_sched_port_set_queue_empty_timestamp(port, qindex) +#define rte_sched_port_set_queue_empty_timestamp(port, subport, qindex) #endif /* RTE_SCHED_RED */ #ifdef RTE_SCHED_DEBUG static inline void -debug_check_queue_slab(struct rte_sched_port *port, uint32_t bmp_pos, +debug_check_queue_slab(struct rte_sched_subport *subport, uint32_t bmp_pos, uint64_t bmp_slab) { uint64_t mask; @@ -1688,7 +1672,7 @@ debug_check_queue_slab(struct rte_sched_port *port, uint32_t bmp_pos, panic = 0; for (i = 0, mask = 1; i < 64; i++, mask <<= 1) { if (mask & bmp_slab) { - if (rte_sched_port_queue_is_empty(port, bmp_pos + i)) { + if (rte_sched_port_queue_is_empty(subport, bmp_pos + i)) { printf("Queue %u (slab offset %u) is empty\n", bmp_pos + i, i); panic = 1; } @@ -2010,10 +1994,10 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, #ifndef RTE_SCHED_SUBPORT_TC_OV static inline void -grinder_credits_update(struct rte_sched_port *port, uint32_t pos) +grinder_credits_update(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; struct rte_sched_pipe_profile *params = grinder->pipe_params; uint64_t n_periods; @@ -2051,10 +2035,9 @@ grinder_credits_update(struct rte_sched_port *port, uint32_t pos) #else static inline uint32_t -grinder_tc_ov_credits_update(struct rte_sched_port *port, uint32_t pos) +grinder_tc_ov_credits_update(struct rte_sched_port *port, + struct rte_sched_subport *subport) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; uint32_t tc_ov_consumption[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; uint32_t tc_consumption = 0, tc_ov_consumption_max; uint32_t tc_ov_wm = subport->tc_ov_wm; @@ -2094,10 +2077,10 @@ grinder_tc_ov_credits_update(struct rte_sched_port *port, uint32_t pos) } static inline void -grinder_credits_update(struct rte_sched_port *port, uint32_t pos) +grinder_credits_update(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; struct rte_sched_pipe_profile *params = grinder->pipe_params; uint64_t n_periods; @@ -2117,7 +2100,7 @@ grinder_credits_update(struct rte_sched_port *port, uint32_t pos) /* Subport TCs */ if (unlikely(port->time >= subport->tc_time)) { - subport->tc_ov_wm = grinder_tc_ov_credits_update(port, pos); + subport->tc_ov_wm = grinder_tc_ov_credits_update(port, subport); for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) subport->tc_credits[i] = subport->tc_credits_per_period[i]; @@ -2147,10 +2130,10 @@ grinder_credits_update(struct rte_sched_port *port, uint32_t pos) #ifndef RTE_SCHED_SUBPORT_TC_OV static inline int -grinder_credits_check(struct rte_sched_port *port, uint32_t pos) +grinder_credits_check(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; + 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; @@ -2182,10 +2165,10 @@ grinder_credits_check(struct rte_sched_port *port, uint32_t pos) #else static inline int -grinder_credits_check(struct rte_sched_port *port, uint32_t pos) +grinder_credits_check(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; + 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; @@ -2230,15 +2213,16 @@ grinder_credits_check(struct rte_sched_port *port, uint32_t pos) static inline int -grinder_schedule(struct rte_sched_port *port, uint32_t pos) +grinder_schedule(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_queue *queue = grinder->queue[grinder->qpos]; struct rte_mbuf *pkt = grinder->pkt; uint32_t pkt_len = pkt->pkt_len + port->frame_overhead; uint32_t be_tc_active; - if (!grinder_credits_check(port, pos)) + if (!grinder_credits_check(port, subport, pos)) return 0; /* Advance port time */ @@ -2255,15 +2239,15 @@ grinder_schedule(struct rte_sched_port *port, uint32_t pos) if (queue->qr == queue->qw) { uint32_t qindex = grinder->qindex[grinder->qpos]; - rte_bitmap_clear(port->bmp, qindex); + rte_bitmap_clear(subport->bmp, qindex); grinder->qmask &= ~(1 << grinder->qpos); if (be_tc_active) grinder->wrr_mask[grinder->qpos] = 0; - rte_sched_port_set_queue_empty_timestamp(port, qindex); + rte_sched_port_set_queue_empty_timestamp(port, subport, qindex); } /* Reset pipe loop detection */ - port->pipe_loop = RTE_SCHED_PIPE_INVALID; + subport->pipe_loop = RTE_SCHED_PIPE_INVALID; grinder->productive = 1; return 1; @@ -2272,13 +2256,13 @@ grinder_schedule(struct rte_sched_port *port, uint32_t pos) #ifdef SCHED_VECTOR_SSE4 static inline int -grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) +grinder_pipe_exists(struct rte_sched_subport *subport, uint32_t base_pipe) { __m128i index = _mm_set1_epi32(base_pipe); - __m128i pipes = _mm_load_si128((__m128i *)port->grinder_base_bmp_pos); + __m128i pipes = _mm_load_si128((__m128i *)subport->grinder_base_bmp_pos); __m128i res = _mm_cmpeq_epi32(pipes, index); - pipes = _mm_load_si128((__m128i *)(port->grinder_base_bmp_pos + 4)); + pipes = _mm_load_si128((__m128i *)(subport->grinder_base_bmp_pos + 4)); pipes = _mm_cmpeq_epi32(pipes, index); res = _mm_or_si128(res, pipes); @@ -2291,10 +2275,10 @@ grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) #elif defined(SCHED_VECTOR_NEON) static inline int -grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) +grinder_pipe_exists(struct rte_sched_subport *subport, uint32_t base_pipe) { uint32x4_t index, pipes; - uint32_t *pos = (uint32_t *)port->grinder_base_bmp_pos; + uint32_t *pos = (uint32_t *)subport->grinder_base_bmp_pos; index = vmovq_n_u32(base_pipe); pipes = vld1q_u32(pos); @@ -2311,12 +2295,12 @@ grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) #else static inline int -grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) +grinder_pipe_exists(struct rte_sched_subport *subport, uint32_t base_pipe) { uint32_t i; for (i = 0; i < RTE_SCHED_PORT_N_GRINDERS; i++) { - if (port->grinder_base_bmp_pos[i] == base_pipe) + if (subport->grinder_base_bmp_pos[i] == base_pipe) return 1; } @@ -2326,9 +2310,10 @@ grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) #endif /* RTE_SCHED_OPTIMIZATIONS */ static inline void -grinder_pcache_populate(struct rte_sched_port *port, uint32_t pos, uint32_t bmp_pos, uint64_t bmp_slab) +grinder_pcache_populate(struct rte_sched_subport *subport, + uint32_t pos, uint32_t bmp_pos, uint64_t bmp_slab) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint16_t w[4]; grinder->pcache_w = 0; @@ -2357,9 +2342,10 @@ grinder_pcache_populate(struct rte_sched_port *port, uint32_t pos, uint32_t bmp_ } static inline void -grinder_tccache_populate(struct rte_sched_port *port, uint32_t pos, uint32_t qindex, uint16_t qmask) +grinder_tccache_populate(struct rte_sched_subport *subport, + uint32_t pos, uint32_t qindex, uint16_t qmask) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint8_t b, i; grinder->tccache_w = 0; @@ -2380,9 +2366,10 @@ grinder_tccache_populate(struct rte_sched_port *port, uint32_t pos, uint32_t qin } static inline int -grinder_next_tc(struct rte_sched_port *port, uint32_t pos) +grinder_next_tc(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_mbuf **qbase; uint32_t qindex; uint16_t qsize; @@ -2391,15 +2378,15 @@ grinder_next_tc(struct rte_sched_port *port, uint32_t pos) return 0; qindex = grinder->tccache_qindex[grinder->tccache_r]; - qbase = rte_sched_port_qbase(port, qindex); - qsize = rte_sched_port_qsize(port, qindex); + qbase = rte_sched_subport_pipe_qbase(subport, qindex); + qsize = rte_sched_subport_pipe_qsize(port, subport, qindex); grinder->tc_index = rte_sched_port_pipe_tc(port, qindex); grinder->qmask = grinder->tccache_qmask[grinder->tccache_r]; grinder->qsize = qsize; if (grinder->tc_index < RTE_SCHED_TRAFFIC_CLASS_BE) { - grinder->queue[0] = port->queue + qindex; + grinder->queue[0] = subport->queue + qindex; grinder->qbase[0] = qbase; grinder->qindex[0] = qindex; grinder->tccache_r++; @@ -2407,10 +2394,10 @@ grinder_next_tc(struct rte_sched_port *port, uint32_t pos) return 1; } - grinder->queue[0] = port->queue + qindex; - grinder->queue[1] = port->queue + qindex + 1; - grinder->queue[2] = port->queue + qindex + 2; - grinder->queue[3] = port->queue + qindex + 3; + grinder->queue[0] = subport->queue + qindex; + grinder->queue[1] = subport->queue + qindex + 1; + grinder->queue[2] = subport->queue + qindex + 2; + grinder->queue[3] = subport->queue + qindex + 3; grinder->qbase[0] = qbase; grinder->qbase[1] = qbase + qsize; @@ -2427,9 +2414,10 @@ grinder_next_tc(struct rte_sched_port *port, uint32_t pos) } static inline int -grinder_next_pipe(struct rte_sched_port *port, uint32_t pos) +grinder_next_pipe(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint32_t pipe_qindex; uint16_t pipe_qmask; @@ -2442,22 +2430,22 @@ grinder_next_pipe(struct rte_sched_port *port, uint32_t pos) uint32_t bmp_pos = 0; /* Get another non-empty pipe group */ - if (unlikely(rte_bitmap_scan(port->bmp, &bmp_pos, &bmp_slab) <= 0)) + if (unlikely(rte_bitmap_scan(subport->bmp, &bmp_pos, &bmp_slab) <= 0)) return 0; #ifdef RTE_SCHED_DEBUG - debug_check_queue_slab(port, bmp_pos, bmp_slab); + debug_check_queue_slab(subport, bmp_pos, bmp_slab); #endif /* Return if pipe group already in one of the other grinders */ - port->grinder_base_bmp_pos[pos] = RTE_SCHED_BMP_POS_INVALID; - if (unlikely(grinder_pipe_exists(port, bmp_pos))) + subport->grinder_base_bmp_pos[pos] = RTE_SCHED_BMP_POS_INVALID; + if (unlikely(grinder_pipe_exists(subport, bmp_pos))) return 0; - port->grinder_base_bmp_pos[pos] = bmp_pos; + subport->grinder_base_bmp_pos[pos] = bmp_pos; /* Install new pipe group into grinder's pipe cache */ - grinder_pcache_populate(port, pos, bmp_pos, bmp_slab); + grinder_pcache_populate(subport, pos, bmp_pos, bmp_slab); pipe_qmask = grinder->pcache_qmask[0]; pipe_qindex = grinder->pcache_qindex[0]; @@ -2466,18 +2454,18 @@ grinder_next_pipe(struct rte_sched_port *port, uint32_t pos) /* Install new pipe in the grinder */ grinder->pindex = pipe_qindex >> 4; - grinder->subport = port->subport + (grinder->pindex / port->n_pipes_per_subport); - grinder->pipe = port->pipe + grinder->pindex; + grinder->subport = subport; + grinder->pipe = subport->pipe + grinder->pindex; grinder->pipe_params = NULL; /* to be set after the pipe structure is prefetched */ grinder->productive = 0; - grinder_tccache_populate(port, pos, pipe_qindex, pipe_qmask); - grinder_next_tc(port, pos); + grinder_tccache_populate(subport, pos, pipe_qindex, pipe_qmask); + grinder_next_tc(port, subport, pos); /* Check for pipe exhaustion */ - if (grinder->pindex == port->pipe_loop) { - port->pipe_exhaustion = 1; - port->pipe_loop = RTE_SCHED_PIPE_INVALID; + if (grinder->pindex == subport->pipe_loop) { + subport->pipe_exhaustion = 1; + subport->pipe_loop = RTE_SCHED_PIPE_INVALID; } return 1; @@ -2485,9 +2473,9 @@ grinder_next_pipe(struct rte_sched_port *port, uint32_t pos) static inline void -grinder_wrr_load(struct rte_sched_port *port, uint32_t pos) +grinder_wrr_load(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; struct rte_sched_pipe_profile *pipe_params = grinder->pipe_params; uint32_t qmask = grinder->qmask; @@ -2513,9 +2501,9 @@ grinder_wrr_load(struct rte_sched_port *port, uint32_t pos) } static inline void -grinder_wrr_store(struct rte_sched_port *port, uint32_t pos) +grinder_wrr_store(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; pipe->wrr_tokens[0] = @@ -2533,9 +2521,9 @@ grinder_wrr_store(struct rte_sched_port *port, uint32_t pos) } static inline void -grinder_wrr(struct rte_sched_port *port, uint32_t pos) +grinder_wrr(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint16_t wrr_tokens_min; grinder->wrr_tokens[0] |= ~grinder->wrr_mask[0]; @@ -2553,21 +2541,21 @@ grinder_wrr(struct rte_sched_port *port, uint32_t pos) } -#define grinder_evict(port, pos) +#define grinder_evict(subport, pos) static inline void -grinder_prefetch_pipe(struct rte_sched_port *port, uint32_t pos) +grinder_prefetch_pipe(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; rte_prefetch0(grinder->pipe); rte_prefetch0(grinder->queue[0]); } static inline void -grinder_prefetch_tc_queue_arrays(struct rte_sched_port *port, uint32_t pos) +grinder_prefetch_tc_queue_arrays(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint16_t qsize, qr[RTE_SCHED_MAX_QUEUES_PER_TC]; qsize = grinder->qsize; @@ -2588,17 +2576,17 @@ grinder_prefetch_tc_queue_arrays(struct rte_sched_port *port, uint32_t pos) rte_prefetch0(grinder->qbase[0] + qr[0]); rte_prefetch0(grinder->qbase[1] + qr[1]); - grinder_wrr_load(port, pos); - grinder_wrr(port, pos); + grinder_wrr_load(subport, pos); + grinder_wrr(subport, pos); rte_prefetch0(grinder->qbase[2] + qr[2]); rte_prefetch0(grinder->qbase[3] + qr[3]); } static inline void -grinder_prefetch_mbuf(struct rte_sched_port *port, uint32_t pos) +grinder_prefetch_mbuf(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint32_t qpos = grinder->qpos; struct rte_mbuf **qbase = grinder->qbase[qpos]; uint16_t qsize = grinder->qsize; @@ -2617,14 +2605,15 @@ grinder_prefetch_mbuf(struct rte_sched_port *port, uint32_t pos) static inline uint32_t grinder_handle(struct rte_sched_port *port, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_subport *subport = port->subport; + struct rte_sched_grinder *grinder = subport->grinder + pos; switch (grinder->state) { case e_GRINDER_PREFETCH_PIPE: { - if (grinder_next_pipe(port, pos)) { - grinder_prefetch_pipe(port, pos); - port->busy_grinders++; + if (grinder_next_pipe(port, subport, pos)) { + grinder_prefetch_pipe(subport, pos); + subport->busy_grinders++; grinder->state = e_GRINDER_PREFETCH_TC_QUEUE_ARRAYS; return 0; @@ -2637,9 +2626,9 @@ grinder_handle(struct rte_sched_port *port, uint32_t pos) { struct rte_sched_pipe *pipe = grinder->pipe; - grinder->pipe_params = port->pipe_profiles + pipe->profile; - grinder_prefetch_tc_queue_arrays(port, pos); - grinder_credits_update(port, pos); + grinder->pipe_params = subport->pipe_profiles + pipe->profile; + grinder_prefetch_tc_queue_arrays(subport, pos); + grinder_credits_update(port, subport, pos); grinder->state = e_GRINDER_PREFETCH_MBUF; return 0; @@ -2647,7 +2636,7 @@ grinder_handle(struct rte_sched_port *port, uint32_t pos) case e_GRINDER_PREFETCH_MBUF: { - grinder_prefetch_mbuf(port, pos); + grinder_prefetch_mbuf(subport, pos); grinder->state = e_GRINDER_READ_MBUF; return 0; @@ -2657,47 +2646,47 @@ grinder_handle(struct rte_sched_port *port, uint32_t pos) { uint32_t wrr_active, result = 0; - result = grinder_schedule(port, pos); + result = grinder_schedule(port, subport, pos); wrr_active = (grinder->tc_index == RTE_SCHED_TRAFFIC_CLASS_BE); /* Look for next packet within the same TC */ if (result && grinder->qmask) { if (wrr_active) - grinder_wrr(port, pos); + grinder_wrr(subport, pos); - grinder_prefetch_mbuf(port, pos); + grinder_prefetch_mbuf(subport, pos); return 1; } if (wrr_active) - grinder_wrr_store(port, pos); + grinder_wrr_store(subport, pos); /* Look for another active TC within same pipe */ - if (grinder_next_tc(port, pos)) { - grinder_prefetch_tc_queue_arrays(port, pos); + if (grinder_next_tc(port, subport, pos)) { + grinder_prefetch_tc_queue_arrays(subport, pos); grinder->state = e_GRINDER_PREFETCH_MBUF; return result; } if (grinder->productive == 0 && - port->pipe_loop == RTE_SCHED_PIPE_INVALID) - port->pipe_loop = grinder->pindex; + subport->pipe_loop == RTE_SCHED_PIPE_INVALID) + subport->pipe_loop = grinder->pindex; - grinder_evict(port, pos); + grinder_evict(subport, pos); /* Look for another active pipe */ - if (grinder_next_pipe(port, pos)) { - grinder_prefetch_pipe(port, pos); + if (grinder_next_pipe(port, subport, pos)) { + grinder_prefetch_pipe(subport, pos); grinder->state = e_GRINDER_PREFETCH_TC_QUEUE_ARRAYS; return result; } /* No active pipe found */ - port->busy_grinders--; + subport->busy_grinders--; grinder->state = e_GRINDER_PREFETCH_PIPE; return result; -- 2.21.0
Modify scheduler packet dequeue operation to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 51 ++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index d7abe9661..e14506b2d 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -243,6 +243,7 @@ struct rte_sched_port { uint32_t busy_grinders; struct rte_mbuf **pkts_out; uint32_t n_pkts_out; + uint32_t subport_id; /* Queue base calculation */ uint32_t qsize_add[RTE_SCHED_QUEUES_PER_PIPE]; @@ -898,6 +899,7 @@ rte_sched_port_config(struct rte_sched_port_params *params) /* Grinders */ port->pkts_out = NULL; port->n_pkts_out = 0; + port->subport_id = 0; return port; } @@ -2603,9 +2605,9 @@ grinder_prefetch_mbuf(struct rte_sched_subport *subport, uint32_t pos) } static inline uint32_t -grinder_handle(struct rte_sched_port *port, uint32_t pos) +grinder_handle(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_subport *subport = port->subport; struct rte_sched_grinder *grinder = subport->grinder + pos; switch (grinder->state) { @@ -2704,6 +2706,7 @@ rte_sched_port_time_resync(struct rte_sched_port *port) uint64_t cycles = rte_get_tsc_cycles(); uint64_t cycles_diff = cycles - port->time_cpu_cycles; uint64_t bytes_diff; + uint32_t i; /* Compute elapsed time in bytes */ bytes_diff = rte_reciprocal_divide(cycles_diff << RTE_SCHED_TIME_SHIFT, @@ -2716,20 +2719,21 @@ rte_sched_port_time_resync(struct rte_sched_port *port) port->time = port->time_cpu_bytes; /* Reset pipe loop detection */ - port->pipe_loop = RTE_SCHED_PIPE_INVALID; + for (i = 0; i < port->n_subports_per_port; i++) + port->subports[i]->pipe_loop = RTE_SCHED_PIPE_INVALID; } static inline int -rte_sched_port_exceptions(struct rte_sched_port *port, int second_pass) +rte_sched_port_exceptions(struct rte_sched_subport *subport, int second_pass) { int exceptions; /* Check if any exception flag is set */ - exceptions = (second_pass && port->busy_grinders == 0) || - (port->pipe_exhaustion == 1); + exceptions = (second_pass && subport->busy_grinders == 0) || + (subport->pipe_exhaustion == 1); /* Clear exception flags */ - port->pipe_exhaustion = 0; + subport->pipe_exhaustion = 0; return exceptions; } @@ -2737,7 +2741,9 @@ rte_sched_port_exceptions(struct rte_sched_port *port, int second_pass) int rte_sched_port_dequeue(struct rte_sched_port *port, struct rte_mbuf **pkts, uint32_t n_pkts) { - uint32_t i, count; + struct rte_sched_subport *subport; + uint32_t subport_id = port->subport_id; + uint32_t i, n_subports = 0, count; port->pkts_out = pkts; port->n_pkts_out = 0; @@ -2746,9 +2752,32 @@ rte_sched_port_dequeue(struct rte_sched_port *port, struct rte_mbuf **pkts, uint /* Take each queue in the grinder one step further */ for (i = 0, count = 0; ; i++) { - count += grinder_handle(port, i & (RTE_SCHED_PORT_N_GRINDERS - 1)); - if ((count == n_pkts) || - rte_sched_port_exceptions(port, i >= RTE_SCHED_PORT_N_GRINDERS)) { + subport = port->subports[subport_id]; + + count += grinder_handle(port, subport, + i & (RTE_SCHED_PORT_N_GRINDERS - 1)); + + if (count == n_pkts) { + subport_id++; + + if (subport_id == port->n_subports_per_port) + subport_id = 0; + + port->subport_id = subport_id; + break; + } + + if (rte_sched_port_exceptions(subport, i >= RTE_SCHED_PORT_N_GRINDERS)) { + i = 0; + subport_id++; + n_subports++; + } + + if (subport_id == port->n_subports_per_port) + subport_id = 0; + + if (n_subports == port->n_subports_per_port) { + port->subport_id = subport_id; break; } } -- 2.21.0
Modify pipe queue stats read function to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index e14506b2d..1faa580d0 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -282,16 +282,6 @@ enum rte_sched_subport_array { e_RTE_SCHED_SUBPORT_ARRAY_TOTAL, }; -#ifdef RTE_SCHED_COLLECT_STATS - -static inline uint32_t -rte_sched_port_queues_per_subport(struct rte_sched_port *port) -{ - return RTE_SCHED_QUEUES_PER_PIPE * port->n_pipes_per_subport; -} - -#endif - static inline uint32_t rte_sched_subport_pipe_queues(struct rte_sched_subport *subport) { @@ -320,7 +310,12 @@ struct rte_sched_subport *subport, uint32_t qindex) static inline uint32_t rte_sched_port_queues_per_port(struct rte_sched_port *port) { - return RTE_SCHED_QUEUES_PER_PIPE * port->n_pipes_per_subport * port->n_subports_per_port; + uint32_t n_queues = 0, i; + + for (i = 0; i < port->n_subports_per_port; i++) + n_queues += rte_sched_subport_pipe_queues(port->subports[i]); + + return n_queues; } static inline uint16_t @@ -1474,8 +1469,10 @@ rte_sched_queue_read_stats(struct rte_sched_port *port, struct rte_sched_queue_stats *stats, uint16_t *qlen) { + struct rte_sched_subport *s; struct rte_sched_queue *q; struct rte_sched_queue_extra *qe; + uint32_t subport_id, subport_qmask, subport_qindex; /* Check user parameters */ if (port == NULL) { @@ -1501,8 +1498,13 @@ rte_sched_queue_read_stats(struct rte_sched_port *port, "%s: Incorrect value for parameter qlen\n", __func__); return -EINVAL; } - q = port->queue + queue_id; - qe = port->queue_extra + queue_id; + subport_qmask = port->n_pipes_per_subport_log2 + 4; + subport_id = (queue_id >> subport_qmask) & (port->n_subports_per_port - 1); + + s = port->subports[subport_id]; + subport_qindex = ((1 << subport_qmask) - 1) & queue_id; + q = s->queue + subport_qindex; + qe = s->queue_extra + subport_qindex; /* Copy queue stats and clear */ memcpy(stats, &qe->stats, sizeof(struct rte_sched_queue_stats)); -- 2.21.0
Modify tests function to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- app/test/test_sched.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/app/test/test_sched.c b/app/test/test_sched.c index afe0b0765..fc31080ef 100644 --- a/app/test/test_sched.c +++ b/app/test/test_sched.c @@ -22,18 +22,6 @@ #define TC 2 #define QUEUE 0 -static struct rte_sched_subport_params subport_param[] = { - { - .tb_rate = 1250000000, - .tb_size = 1000000, - - .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000, - 1250000000, 1250000000, 1250000000, 1250000000, 1250000000, - 1250000000, 1250000000, 1250000000, 1250000000}, - .tc_period = 10, - }, -}; - static struct rte_sched_pipe_params pipe_profile[] = { { /* Profile #0 */ .tb_rate = 305175, @@ -48,6 +36,23 @@ static struct rte_sched_pipe_params pipe_profile[] = { }, }; +static struct rte_sched_subport_params subport_param[] = { + { + .tb_rate = 1250000000, + .tb_size = 1000000, + + .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000, + 1250000000, 1250000000, 1250000000, 1250000000, 1250000000, + 1250000000, 1250000000, 1250000000, 1250000000}, + .tc_period = 10, + .n_pipes_per_subport_enabled = 1024, + .qsize = {32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}, + .pipe_profiles = pipe_profile, + .n_pipe_profiles = 1, + .n_max_pipe_profiles = 1, + }, +}; + static struct rte_sched_port_params port_param = { .socket = 0, /* computed */ .rate = 0, /* computed */ @@ -55,10 +60,6 @@ static struct rte_sched_port_params port_param = { .frame_overhead = RTE_SCHED_FRAME_OVERHEAD_DEFAULT, .n_subports_per_port = 1, .n_pipes_per_subport = 1024, - .qsize = {32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}, - .pipe_profiles = pipe_profile, - .n_pipe_profiles = 1, - .n_max_pipe_profiles = 1, }; #define NB_MBUF 32 @@ -140,7 +141,7 @@ test_sched(void) err = rte_sched_subport_config(port, SUBPORT, subport_param); TEST_ASSERT_SUCCESS(err, "Error config sched, err=%d\n", err); - for (pipe = 0; pipe < port_param.n_pipes_per_subport; pipe ++) { + for (pipe = 0; pipe < subport_param[0].n_pipes_per_subport_enabled; pipe++) { err = rte_sched_pipe_config(port, SUBPORT, pipe, 0); TEST_ASSERT_SUCCESS(err, "Error config sched pipe %u, err=%d\n", pipe, err); } -- 2.21.0
Modify softnic traffic management function to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- drivers/net/softnic/rte_eth_softnic_tm.c | 54 ++++++++++++------------ 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/drivers/net/softnic/rte_eth_softnic_tm.c b/drivers/net/softnic/rte_eth_softnic_tm.c index 61c3adc82..80a470c9e 100644 --- a/drivers/net/softnic/rte_eth_softnic_tm.c +++ b/drivers/net/softnic/rte_eth_softnic_tm.c @@ -85,7 +85,8 @@ softnic_tmgr_port_create(struct pmd_internals *p, /* Subport */ n_subports = t->port_params.n_subports_per_port; for (subport_id = 0; subport_id < n_subports; subport_id++) { - uint32_t n_pipes_per_subport = t->port_params.n_pipes_per_subport; + uint32_t n_pipes_per_subport = + t->subport_params[subport_id].n_pipes_per_subport_enabled; uint32_t pipe_id; int status; @@ -2211,10 +2212,11 @@ tm_tc_wred_profile_get(struct rte_eth_dev *dev, uint32_t tc_id) #ifdef RTE_SCHED_RED static void -wred_profiles_set(struct rte_eth_dev *dev) +wred_profiles_set(struct rte_eth_dev *dev, uint32_t subport_id) { struct pmd_internals *p = dev->data->dev_private; - struct rte_sched_port_params *pp = &p->soft.tm.params.port_params; + struct rte_sched_subport_params *pp = + &p->soft.tm.params.subport_params[subport_id]; uint32_t tc_id; enum rte_color color; @@ -2234,7 +2236,7 @@ wred_profiles_set(struct rte_eth_dev *dev) #else -#define wred_profiles_set(dev) +#define wred_profiles_set(dev, subport_id) #endif @@ -2526,29 +2528,9 @@ hierarchy_blueprints_create(struct rte_eth_dev *dev) .frame_overhead = root->shaper_profile->params.pkt_length_adjust, .n_subports_per_port = root->n_children, - .n_pipes_per_subport = h->n_tm_nodes[TM_NODE_LEVEL_PIPE] / - h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT], - .qsize = {p->params.tm.qsize[0], - p->params.tm.qsize[1], - p->params.tm.qsize[2], - p->params.tm.qsize[3], - p->params.tm.qsize[4], - p->params.tm.qsize[5], - p->params.tm.qsize[6], - p->params.tm.qsize[7], - p->params.tm.qsize[8], - p->params.tm.qsize[9], - p->params.tm.qsize[10], - p->params.tm.qsize[11], - p->params.tm.qsize[12], - }, - .pipe_profiles = t->pipe_profiles, - .n_pipe_profiles = t->n_pipe_profiles, - .n_max_pipe_profiles = TM_MAX_PIPE_PROFILE, + .n_pipes_per_subport = TM_MAX_PIPES_PER_SUBPORT, }; - wred_profiles_set(dev); - subport_id = 0; TAILQ_FOREACH(n, nl, node) { uint64_t tc_rate[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; @@ -2588,8 +2570,28 @@ hierarchy_blueprints_create(struct rte_eth_dev *dev) tc_rate[12], }, .tc_period = SUBPORT_TC_PERIOD, + .n_pipes_per_subport_enabled = + h->n_tm_nodes[TM_NODE_LEVEL_PIPE] / + h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT], + .qsize = {p->params.tm.qsize[0], + p->params.tm.qsize[1], + p->params.tm.qsize[2], + p->params.tm.qsize[3], + p->params.tm.qsize[4], + p->params.tm.qsize[5], + p->params.tm.qsize[6], + p->params.tm.qsize[7], + p->params.tm.qsize[8], + p->params.tm.qsize[9], + p->params.tm.qsize[10], + p->params.tm.qsize[11], + p->params.tm.qsize[12], + }, + .pipe_profiles = t->pipe_profiles, + .n_pipe_profiles = t->n_pipe_profiles, + .n_max_pipe_profiles = TM_MAX_PIPE_PROFILE, }; - + wred_profiles_set(dev, subport_id); subport_id++; } } -- 2.21.0
Modify ip pipeline traffic management function to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- examples/ip_pipeline/cli.c | 71 ++++++++++++++++++------------------- examples/ip_pipeline/tmgr.c | 25 +++++++------ examples/ip_pipeline/tmgr.h | 7 ++-- 3 files changed, 51 insertions(+), 52 deletions(-) diff --git a/examples/ip_pipeline/cli.c b/examples/ip_pipeline/cli.c index 02dc11495..c72030682 100644 --- a/examples/ip_pipeline/cli.c +++ b/examples/ip_pipeline/cli.c @@ -393,7 +393,12 @@ static const char cmd_tmgr_subport_profile_help[] = " <tc0_rate> <tc1_rate> <tc2_rate> <tc3_rate> <tc4_rate>" " <tc5_rate> <tc6_rate> <tc7_rate> <tc8_rate>" " <tc9_rate> <tc10_rate> <tc11_rate> <tc12_rate>\n" -" <tc_period>\n"; +" <tc_period>\n" +" pps <n_pipes_per_subport>\n" +" qsize <qsize_tc0> <qsize_tc1> <qsize_tc2>" +" <qsize_tc3> <qsize_tc4> <qsize_tc5> <qsize_tc6>" +" <qsize_tc7> <qsize_tc8> <qsize_tc9> <qsize_tc10>" +" <qsize_tc11> <qsize_tc12>"; static void cmd_tmgr_subport_profile(char **tokens, @@ -404,7 +409,7 @@ cmd_tmgr_subport_profile(char **tokens, struct rte_sched_subport_params p; int status, i; - if (n_tokens != 19) { + if (n_tokens != 35) { snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); return; } @@ -430,6 +435,27 @@ cmd_tmgr_subport_profile(char **tokens, return; } + if (strcmp(tokens[19], "pps") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps"); + return; + } + + if (parser_read_uint32(&p.n_pipes_per_subport_enabled, tokens[20]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "n_pipes_per_subport"); + return; + } + + if (strcmp(tokens[21], "qsize") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "qsize"); + return; + } + + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) + if (parser_read_uint16(&p.qsize[i], tokens[22 + i]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "qsize"); + return; + } + status = tmgr_subport_profile_add(&p); if (status != 0) { snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); @@ -504,11 +530,6 @@ static const char cmd_tmgr_help[] = "tmgr <tmgr_name>\n" " rate <rate>\n" " spp <n_subports_per_port>\n" -" pps <n_pipes_per_subport>\n" -" qsize <qsize_tc0> <qsize_tc1> <qsize_tc2>" -" <qsize_tc3> <qsize_tc4> <qsize_tc5> <qsize_tc6>" -" <qsize_tc7> <qsize_tc8> <qsize_tc9> <qsize_tc10>" -" <qsize_tc11> <qsize_tc12>\n" " fo <frame_overhead>\n" " mtu <mtu>\n" " cpu <cpu_id>\n"; @@ -522,9 +543,8 @@ cmd_tmgr(char **tokens, struct tmgr_port_params p; char *name; struct tmgr_port *tmgr_port; - int i; - if (n_tokens != 28) { + if (n_tokens != 12) { snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); return; } @@ -551,53 +571,32 @@ cmd_tmgr(char **tokens, return; } - if (strcmp(tokens[6], "pps") != 0) { - snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps"); - return; - } - - if (parser_read_uint32(&p.n_pipes_per_subport, tokens[7]) != 0) { - snprintf(out, out_size, MSG_ARG_INVALID, "n_pipes_per_subport"); - return; - } - - if (strcmp(tokens[8], "qsize") != 0) { - snprintf(out, out_size, MSG_ARG_NOT_FOUND, "qsize"); - return; - } - - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - if (parser_read_uint16(&p.qsize[i], tokens[9 + i]) != 0) { - snprintf(out, out_size, MSG_ARG_INVALID, "qsize"); - return; - } - - if (strcmp(tokens[22], "fo") != 0) { + if (strcmp(tokens[6], "fo") != 0) { snprintf(out, out_size, MSG_ARG_NOT_FOUND, "fo"); return; } - if (parser_read_uint32(&p.frame_overhead, tokens[23]) != 0) { + if (parser_read_uint32(&p.frame_overhead, tokens[7]) != 0) { snprintf(out, out_size, MSG_ARG_INVALID, "frame_overhead"); return; } - if (strcmp(tokens[24], "mtu") != 0) { + if (strcmp(tokens[8], "mtu") != 0) { snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mtu"); return; } - if (parser_read_uint32(&p.mtu, tokens[25]) != 0) { + if (parser_read_uint32(&p.mtu, tokens[9]) != 0) { snprintf(out, out_size, MSG_ARG_INVALID, "mtu"); return; } - if (strcmp(tokens[26], "cpu") != 0) { + if (strcmp(tokens[10], "cpu") != 0) { snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu"); return; } - if (parser_read_uint32(&p.cpu_id, tokens[27]) != 0) { + if (parser_read_uint32(&p.cpu_id, tokens[11]) != 0) { snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id"); return; } diff --git a/examples/ip_pipeline/tmgr.c b/examples/ip_pipeline/tmgr.c index 40cbf1d0a..91ccbf60f 100644 --- a/examples/ip_pipeline/tmgr.c +++ b/examples/ip_pipeline/tmgr.c @@ -47,7 +47,8 @@ int tmgr_subport_profile_add(struct rte_sched_subport_params *p) { /* Check input params */ - if (p == NULL) + if (p == NULL || + p->n_pipes_per_subport_enabled == 0) return -1; /* Save profile */ @@ -90,7 +91,6 @@ tmgr_port_create(const char *name, struct tmgr_port_params *params) tmgr_port_find(name) || (params == NULL) || (params->n_subports_per_port == 0) || - (params->n_pipes_per_subport == 0) || (params->cpu_id >= RTE_MAX_NUMA_NODES) || (n_subport_profiles == 0) || (n_pipe_profiles == 0)) @@ -103,18 +103,16 @@ tmgr_port_create(const char *name, struct tmgr_port_params *params) p.mtu = params->mtu; p.frame_overhead = params->frame_overhead; p.n_subports_per_port = params->n_subports_per_port; - p.n_pipes_per_subport = params->n_pipes_per_subport; - - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - p.qsize[i] = params->qsize[i]; - - p.pipe_profiles = pipe_profile; - p.n_pipe_profiles = n_pipe_profiles; + p.n_pipes_per_subport = TMGR_PIPE_SUBPORT_MAX; s = rte_sched_port_config(&p); if (s == NULL) return NULL; + subport_profile[0].pipe_profiles = pipe_profile; + subport_profile[0].n_pipe_profiles = n_pipe_profiles; + subport_profile[0].n_max_pipe_profiles = TMGR_PIPE_PROFILE_MAX; + for (i = 0; i < params->n_subports_per_port; i++) { int status; @@ -128,7 +126,7 @@ tmgr_port_create(const char *name, struct tmgr_port_params *params) return NULL; } - for (j = 0; j < params->n_pipes_per_subport; j++) { + for (j = 0; j < subport_profile[0].n_pipes_per_subport_enabled; j++) { status = rte_sched_pipe_config( s, i, @@ -153,7 +151,6 @@ tmgr_port_create(const char *name, struct tmgr_port_params *params) strlcpy(tmgr_port->name, name, sizeof(tmgr_port->name)); tmgr_port->s = s; tmgr_port->n_subports_per_port = params->n_subports_per_port; - tmgr_port->n_pipes_per_subport = params->n_pipes_per_subport; /* Node add to list */ TAILQ_INSERT_TAIL(&tmgr_port_list, tmgr_port, node); @@ -205,8 +202,10 @@ tmgr_pipe_config(const char *port_name, port = tmgr_port_find(port_name); if ((port == NULL) || (subport_id >= port->n_subports_per_port) || - (pipe_id_first >= port->n_pipes_per_subport) || - (pipe_id_last >= port->n_pipes_per_subport) || + (pipe_id_first >= + subport_profile[subport_id].n_pipes_per_subport_enabled) || + (pipe_id_last >= + subport_profile[subport_id].n_pipes_per_subport_enabled) || (pipe_id_first > pipe_id_last) || (pipe_profile_id >= n_pipe_profiles)) return -1; diff --git a/examples/ip_pipeline/tmgr.h b/examples/ip_pipeline/tmgr.h index 8703a2e00..1fcf66ee1 100644 --- a/examples/ip_pipeline/tmgr.h +++ b/examples/ip_pipeline/tmgr.h @@ -12,6 +12,10 @@ #include "common.h" +#ifndef TMGR_PIPE_SUBPORT_MAX +#define TMGR_PIPE_SUBPORT_MAX 4096 +#endif + #ifndef TMGR_SUBPORT_PROFILE_MAX #define TMGR_SUBPORT_PROFILE_MAX 256 #endif @@ -25,7 +29,6 @@ struct tmgr_port { char name[NAME_SIZE]; struct rte_sched_port *s; uint32_t n_subports_per_port; - uint32_t n_pipes_per_subport; }; TAILQ_HEAD(tmgr_port_list, tmgr_port); @@ -42,8 +45,6 @@ struct tmgr_port_params { uint32_t frame_overhead; uint32_t mtu; uint32_t cpu_id; - uint32_t n_pipes_per_subport; - uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; }; int -- 2.21.0
Modify qos sample app to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- examples/qos_sched/app_thread.c | 20 ++- examples/qos_sched/cfg_file.c | 229 ++++++++++++++++-------------- examples/qos_sched/init.c | 54 +++---- examples/qos_sched/main.h | 1 + examples/qos_sched/profile.cfg | 5 +- examples/qos_sched/profile_ov.cfg | 5 +- examples/qos_sched/stats.c | 44 +++--- 7 files changed, 203 insertions(+), 155 deletions(-) diff --git a/examples/qos_sched/app_thread.c b/examples/qos_sched/app_thread.c index 18b734a14..dbc878b55 100644 --- a/examples/qos_sched/app_thread.c +++ b/examples/qos_sched/app_thread.c @@ -35,15 +35,25 @@ get_pkt_sched(struct rte_mbuf *m, uint32_t *subport, uint32_t *pipe, uint16_t *pdata = rte_pktmbuf_mtod(m, uint16_t *); uint16_t pipe_queue; + /* Outer VLAN ID*/ *subport = (rte_be_to_cpu_16(pdata[SUBPORT_OFFSET]) & 0x0FFF) & - (port_params.n_subports_per_port - 1); /* Outer VLAN ID*/ + (port_params.n_subports_per_port - 1); + + /* Inner VLAN ID */ *pipe = (rte_be_to_cpu_16(pdata[PIPE_OFFSET]) & 0x0FFF) & - (port_params.n_pipes_per_subport - 1); /* Inner VLAN ID */ + (subport_params[*subport].n_pipes_per_subport_enabled - 1); + pipe_queue = active_queues[(pdata[QUEUE_OFFSET] >> 8) % n_active_queues]; + + /* Traffic class (Destination IP) */ *traffic_class = pipe_queue > RTE_SCHED_TRAFFIC_CLASS_BE ? - RTE_SCHED_TRAFFIC_CLASS_BE : pipe_queue; /* Destination IP */ - *queue = pipe_queue - *traffic_class; /* Destination IP */ - *color = pdata[COLOR_OFFSET] & 0x03; /* Destination IP */ + RTE_SCHED_TRAFFIC_CLASS_BE : pipe_queue; + + /* Traffic class queue (Destination IP) */ + *queue = pipe_queue - *traffic_class; + + /* Color (Destination IP) */ + *color = pdata[COLOR_OFFSET] & 0x03; return 0; } diff --git a/examples/qos_sched/cfg_file.c b/examples/qos_sched/cfg_file.c index 45bf599e4..c6d3f5ab6 100644 --- a/examples/qos_sched/cfg_file.c +++ b/examples/qos_sched/cfg_file.c @@ -24,14 +24,10 @@ int cfg_load_port(struct rte_cfgfile *cfg, struct rte_sched_port_params *port_params) { const char *entry; - int j; if (!cfg || !port_params) return -1; - memset(active_queues, 0, sizeof(active_queues)); - n_active_queues = 0; - entry = rte_cfgfile_get_entry(cfg, "port", "frame overhead"); if (entry) port_params->frame_overhead = (uint32_t)atoi(entry); @@ -40,106 +36,6 @@ cfg_load_port(struct rte_cfgfile *cfg, struct rte_sched_port_params *port_params if (entry) port_params->n_subports_per_port = (uint32_t)atoi(entry); - entry = rte_cfgfile_get_entry(cfg, "port", "number of pipes per subport"); - if (entry) - port_params->n_pipes_per_subport = (uint32_t)atoi(entry); - - entry = rte_cfgfile_get_entry(cfg, "port", "queue sizes"); - if (entry) { - char *next; - - for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { - port_params->qsize[j] = (uint16_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - - for (j = 0; j < RTE_SCHED_TRAFFIC_CLASS_BE; j++) - if (port_params->qsize[j]) { - active_queues[n_active_queues] = j; - n_active_queues++; - } - - if (port_params->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]) - for (j = 0; j < RTE_SCHED_BE_QUEUES_PER_PIPE; j++) { - active_queues[n_active_queues] = - RTE_SCHED_TRAFFIC_CLASS_BE + j; - n_active_queues++; - } - } - -#ifdef RTE_SCHED_RED - for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { - char str[32]; - - /* Parse WRED min thresholds */ - snprintf(str, sizeof(str), "tc %d wred min", j); - entry = rte_cfgfile_get_entry(cfg, "red", str); - if (entry) { - char *next; - int k; - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < RTE_COLORS; k++) { - port_params->red_params[j][k].min_th - = (uint16_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - } - - /* Parse WRED max thresholds */ - snprintf(str, sizeof(str), "tc %d wred max", j); - entry = rte_cfgfile_get_entry(cfg, "red", str); - if (entry) { - char *next; - int k; - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < RTE_COLORS; k++) { - port_params->red_params[j][k].max_th - = (uint16_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - } - - /* Parse WRED inverse mark probabilities */ - snprintf(str, sizeof(str), "tc %d wred inv prob", j); - entry = rte_cfgfile_get_entry(cfg, "red", str); - if (entry) { - char *next; - int k; - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < RTE_COLORS; k++) { - port_params->red_params[j][k].maxp_inv - = (uint8_t)strtol(entry, &next, 10); - - if (next == NULL) - break; - entry = next; - } - } - - /* Parse WRED EWMA filter weights */ - snprintf(str, sizeof(str), "tc %d wred weight", j); - entry = rte_cfgfile_get_entry(cfg, "red", str); - if (entry) { - char *next; - int k; - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < RTE_COLORS; k++) { - port_params->red_params[j][k].wq_log2 - = (uint8_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - } - } -#endif /* RTE_SCHED_RED */ - return 0; } @@ -155,7 +51,7 @@ cfg_load_pipe(struct rte_cfgfile *cfg, struct rte_sched_pipe_params *pipe_params return -1; profiles = rte_cfgfile_num_sections(cfg, "pipe profile", sizeof("pipe profile") - 1); - port_params.n_pipe_profiles = profiles; + subport_params[0].n_pipe_profiles = profiles; for (j = 0; j < profiles; j++) { char pipe_name[32]; @@ -253,12 +149,121 @@ cfg_load_subport(struct rte_cfgfile *cfg, struct rte_sched_subport_params *subpo return -1; memset(app_pipe_to_profile, -1, sizeof(app_pipe_to_profile)); + memset(active_queues, 0, sizeof(active_queues)); + n_active_queues = 0; + +#ifdef RTE_SCHED_RED + char sec_name[CFG_NAME_LEN]; + struct rte_red_params red_params[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; + + snprintf(sec_name, sizeof(sec_name), "red"); + + if (rte_cfgfile_has_section(cfg, sec_name)) { + + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + char str[32]; + + /* Parse WRED min thresholds */ + snprintf(str, sizeof(str), "tc %d wred min", i); + entry = rte_cfgfile_get_entry(cfg, sec_name, str); + if (entry) { + char *next; + /* for each packet colour (green, yellow, red) */ + for (j = 0; j < RTE_COLORS; j++) { + red_params[i][j].min_th + = (uint16_t)strtol(entry, &next, 10); + if (next == NULL) + break; + entry = next; + } + } + + /* Parse WRED max thresholds */ + snprintf(str, sizeof(str), "tc %d wred max", i); + entry = rte_cfgfile_get_entry(cfg, "red", str); + if (entry) { + char *next; + /* for each packet colour (green, yellow, red) */ + for (j = 0; j < RTE_COLORS; j++) { + red_params[i][j].max_th + = (uint16_t)strtol(entry, &next, 10); + if (next == NULL) + break; + entry = next; + } + } + + /* Parse WRED inverse mark probabilities */ + snprintf(str, sizeof(str), "tc %d wred inv prob", i); + entry = rte_cfgfile_get_entry(cfg, "red", str); + if (entry) { + char *next; + /* for each packet colour (green, yellow, red) */ + for (j = 0; j < RTE_COLORS; j++) { + red_params[i][j].maxp_inv + = (uint8_t)strtol(entry, &next, 10); + + if (next == NULL) + break; + entry = next; + } + } + + /* Parse WRED EWMA filter weights */ + snprintf(str, sizeof(str), "tc %d wred weight", i); + entry = rte_cfgfile_get_entry(cfg, "red", str); + if (entry) { + char *next; + /* for each packet colour (green, yellow, red) */ + for (j = 0; j < RTE_COLORS; j++) { + red_params[i][j].wq_log2 + = (uint8_t)strtol(entry, &next, 10); + if (next == NULL) + break; + entry = next; + } + } + } + } +#endif /* RTE_SCHED_RED */ for (i = 0; i < MAX_SCHED_SUBPORTS; i++) { char sec_name[CFG_NAME_LEN]; snprintf(sec_name, sizeof(sec_name), "subport %d", i); if (rte_cfgfile_has_section(cfg, sec_name)) { + entry = rte_cfgfile_get_entry(cfg, sec_name, + "number of pipes per subport"); + if (entry) + subport_params[i].n_pipes_per_subport_enabled = + (uint32_t)atoi(entry); + + entry = rte_cfgfile_get_entry(cfg, sec_name, "queue sizes"); + if (entry) { + char *next; + + for (j = 0; j < RTE_SCHED_TRAFFIC_CLASS_BE; j++) { + subport_params[i].qsize[j] = + (uint16_t)strtol(entry, &next, 10); + if (subport_params[i].qsize[j] != 0) { + active_queues[n_active_queues] = j; + n_active_queues++; + } + if (next == NULL) + break; + entry = next; + } + + subport_params[i].qsize[RTE_SCHED_TRAFFIC_CLASS_BE] = + (uint16_t)strtol(entry, &next, 10); + + for (j = 0; j < RTE_SCHED_BE_QUEUES_PER_PIPE; j++) { + active_queues[n_active_queues] = + RTE_SCHED_TRAFFIC_CLASS_BE + j; + n_active_queues++; + } + } + entry = rte_cfgfile_get_entry(cfg, sec_name, "tb rate"); if (entry) subport_params[i].tb_rate = (uint32_t)atoi(entry); @@ -362,6 +367,20 @@ cfg_load_subport(struct rte_cfgfile *cfg, struct rte_sched_subport_params *subpo } } } +#ifdef RTE_SCHED_RED + for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { + for (k = 0; k < RTE_COLORS; k++) { + subport_params[i].red_params[j][k].min_th = + red_params[j][k].min_th; + subport_params[i].red_params[j][k].max_th = + red_params[j][k].max_th; + subport_params[i].red_params[j][k].maxp_inv = + red_params[j][k].maxp_inv; + subport_params[i].red_params[j][k].wq_log2 = + red_params[j][k].wq_log2; + } + } +#endif } } diff --git a/examples/qos_sched/init.c b/examples/qos_sched/init.c index 32e6e1ba2..0a17e0d4d 100644 --- a/examples/qos_sched/init.c +++ b/examples/qos_sched/init.c @@ -180,18 +180,6 @@ app_init_port(uint16_t portid, struct rte_mempool *mp) return 0; } -static struct rte_sched_subport_params subport_params[MAX_SCHED_SUBPORTS] = { - { - .tb_rate = 1250000000, - .tb_size = 1000000, - - .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000, - 1250000000, 1250000000, 1250000000, 1250000000, 1250000000, - 1250000000, 1250000000, 1250000000, 1250000000}, - .tc_period = 10, - }, -}; - static struct rte_sched_pipe_params pipe_profiles[MAX_SCHED_PIPE_PROFILES] = { { /* Profile #0 */ .tb_rate = 305175, @@ -208,19 +196,21 @@ static struct rte_sched_pipe_params pipe_profiles[MAX_SCHED_PIPE_PROFILES] = { }, }; -struct rte_sched_port_params port_params = { - .name = "port_scheduler_0", - .socket = 0, /* computed */ - .rate = 0, /* computed */ - .mtu = 6 + 6 + 4 + 4 + 2 + 1500, - .frame_overhead = RTE_SCHED_FRAME_OVERHEAD_DEFAULT, - .n_subports_per_port = 1, - .n_pipes_per_subport = 4096, - .qsize = {64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}, - .pipe_profiles = pipe_profiles, - .n_pipe_profiles = sizeof(pipe_profiles) / sizeof(struct rte_sched_pipe_params), - .n_max_pipe_profiles = MAX_SCHED_PIPE_PROFILES, +struct rte_sched_subport_params subport_params[MAX_SCHED_SUBPORTS] = { + { + .tb_rate = 1250000000, + .tb_size = 1000000, + .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000, + 1250000000, 1250000000, 1250000000, 1250000000, 1250000000, + 1250000000, 1250000000, 1250000000, 1250000000}, + .tc_period = 10, + .n_pipes_per_subport_enabled = 4096, + .qsize = {64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}, + .pipe_profiles = pipe_profiles, + .n_pipe_profiles = sizeof(pipe_profiles) / + sizeof(struct rte_sched_pipe_params), + .n_max_pipe_profiles = MAX_SCHED_PIPE_PROFILES, #ifdef RTE_SCHED_RED .red_params = { /* Traffic Class 0 Colors Green / Yellow / Red */ @@ -289,6 +279,17 @@ struct rte_sched_port_params port_params = { [12][2] = {.min_th = 32, .max_th = 64, .maxp_inv = 10, .wq_log2 = 9}, }, #endif /* RTE_SCHED_RED */ + }, +}; + +struct rte_sched_port_params port_params = { + .name = "port_scheduler_0", + .socket = 0, /* computed */ + .rate = 0, /* computed */ + .mtu = 6 + 6 + 4 + 4 + 2 + 1500, + .frame_overhead = RTE_SCHED_FRAME_OVERHEAD_DEFAULT, + .n_subports_per_port = 1, + .n_pipes_per_subport = MAX_SCHED_PIPES, }; static struct rte_sched_port * @@ -323,7 +324,10 @@ app_init_sched_port(uint32_t portid, uint32_t socketid) subport, err); } - for (pipe = 0; pipe < port_params.n_pipes_per_subport; pipe++) { + uint32_t n_pipes_per_subport = + subport_params[subport].n_pipes_per_subport_enabled; + + for (pipe = 0; pipe < n_pipes_per_subport; pipe++) { if (app_pipe_to_profile[subport][pipe] != -1) { err = rte_sched_pipe_config(port, subport, pipe, app_pipe_to_profile[subport][pipe]); diff --git a/examples/qos_sched/main.h b/examples/qos_sched/main.h index d8f890b64..baa2b3ead 100644 --- a/examples/qos_sched/main.h +++ b/examples/qos_sched/main.h @@ -152,6 +152,7 @@ uint32_t active_queues[RTE_SCHED_QUEUES_PER_PIPE]; uint32_t n_active_queues; extern struct rte_sched_port_params port_params; +extern struct rte_sched_subport_params subport_params[MAX_SCHED_SUBPORTS]; int app_parse_args(int argc, char **argv); int app_init(void); diff --git a/examples/qos_sched/profile.cfg b/examples/qos_sched/profile.cfg index 335561370..61b8b7071 100644 --- a/examples/qos_sched/profile.cfg +++ b/examples/qos_sched/profile.cfg @@ -20,11 +20,12 @@ [port] frame overhead = 24 number of subports per port = 1 -number of pipes per subport = 4096 -queue sizes = 64 64 64 64 64 64 64 64 64 64 64 64 64 ; Subport configuration [subport 0] +number of pipes per subport = 4096 +queue sizes = 64 64 64 64 64 64 64 64 64 64 64 64 64 + tb rate = 1250000000 ; Bytes per second tb size = 1000000 ; Bytes diff --git a/examples/qos_sched/profile_ov.cfg b/examples/qos_sched/profile_ov.cfg index 394987399..ab509d28d 100644 --- a/examples/qos_sched/profile_ov.cfg +++ b/examples/qos_sched/profile_ov.cfg @@ -5,11 +5,12 @@ [port] frame overhead = 24 number of subports per port = 1 -number of pipes per subport = 32 -queue sizes = 64 64 64 64 64 64 64 64 64 64 64 64 64 ; Subport configuration [subport 0] +number of pipes per subport = 32 +queue sizes = 64 64 64 64 64 64 64 64 64 64 64 64 64 + tb rate = 8400000 ; Bytes per second tb size = 100000 ; Bytes diff --git a/examples/qos_sched/stats.c b/examples/qos_sched/stats.c index e62e4a2f6..ce34b6c7c 100644 --- a/examples/qos_sched/stats.c +++ b/examples/qos_sched/stats.c @@ -24,7 +24,7 @@ qavg_q(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id, uint8_t tc, if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || - pipe_id >= port_params.n_pipes_per_subport || + pipe_id >= subport_params[subport_id].n_pipes_per_subport_enabled || tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE || q >= RTE_SCHED_BE_QUEUES_PER_PIPE || (tc < RTE_SCHED_TRAFFIC_CLASS_BE && q > 0)) @@ -32,7 +32,7 @@ qavg_q(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id, uint8_t tc, port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - queue_id += port_params.n_pipes_per_subport * + queue_id += subport_params[i].n_pipes_per_subport_enabled * RTE_SCHED_QUEUES_PER_PIPE; if (tc < RTE_SCHED_TRAFFIC_CLASS_BE) queue_id += pipe_id * RTE_SCHED_QUEUES_PER_PIPE + tc; @@ -69,14 +69,16 @@ qavg_tcpipe(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id, } if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || - pipe_id >= port_params.n_pipes_per_subport || + pipe_id >= subport_params[subport_id].n_pipes_per_subport_enabled || tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE) return -1; port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - queue_id += port_params.n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; + queue_id += + subport_params[i].n_pipes_per_subport_enabled * + RTE_SCHED_QUEUES_PER_PIPE; queue_id += pipe_id * RTE_SCHED_QUEUES_PER_PIPE + tc; @@ -123,13 +125,13 @@ qavg_pipe(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id) if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || - pipe_id >= port_params.n_pipes_per_subport) + pipe_id >= subport_params[subport_id].n_pipes_per_subport_enabled) return -1; port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - queue_id += port_params.n_pipes_per_subport * + queue_id += subport_params[i].n_pipes_per_subport_enabled * RTE_SCHED_QUEUES_PER_PIPE; queue_id += pipe_id * RTE_SCHED_QUEUES_PER_PIPE; @@ -177,13 +179,17 @@ qavg_tcsubport(uint16_t port_id, uint32_t subport_id, uint8_t tc) for (i = 0; i < subport_id; i++) subport_queue_id += - port_params.n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; + subport_params[i].n_pipes_per_subport_enabled * + RTE_SCHED_QUEUES_PER_PIPE; average = 0; for (count = 0; count < qavg_ntimes; count++) { + uint32_t n_pipes_per_subport = + subport_params[subport_id].n_pipes_per_subport_enabled; + part_average = 0; - for (i = 0; i < port_params.n_pipes_per_subport; i++) { + for (i = 0; i < n_pipes_per_subport; i++) { if (tc < RTE_SCHED_TRAFFIC_CLASS_BE) { queue_id = subport_queue_id + i * RTE_SCHED_QUEUES_PER_PIPE + tc; @@ -203,10 +209,11 @@ qavg_tcsubport(uint16_t port_id, uint32_t subport_id, uint8_t tc) } if (tc < RTE_SCHED_TRAFFIC_CLASS_BE) - average += part_average / (port_params.n_pipes_per_subport); + average += part_average / + (subport_params[subport_id].n_pipes_per_subport_enabled); else - average += - part_average / (port_params.n_pipes_per_subport) * + average += part_average / + (subport_params[subport_id].n_pipes_per_subport_enabled) * RTE_SCHED_BE_QUEUES_PER_PIPE; usleep(qavg_period); @@ -240,14 +247,17 @@ qavg_subport(uint16_t port_id, uint32_t subport_id) port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - subport_queue_id += port_params.n_pipes_per_subport * + subport_queue_id += subport_params[i].n_pipes_per_subport_enabled * RTE_SCHED_QUEUES_PER_PIPE; average = 0; for (count = 0; count < qavg_ntimes; count++) { + uint32_t n_pipes_per_subport = + subport_params[subport_id].n_pipes_per_subport_enabled; + part_average = 0; - for (i = 0; i < port_params.n_pipes_per_subport; i++) { + for (i = 0; i < n_pipes_per_subport; i++) { queue_id = subport_queue_id + i * RTE_SCHED_QUEUES_PER_PIPE; for (j = 0; j < RTE_SCHED_QUEUES_PER_PIPE; j++) { @@ -258,7 +268,8 @@ qavg_subport(uint16_t port_id, uint32_t subport_id) } average += part_average / - (port_params.n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE); + (subport_params[subport_id].n_pipes_per_subport_enabled * + RTE_SCHED_QUEUES_PER_PIPE); usleep(qavg_period); } @@ -322,12 +333,13 @@ pipe_stat(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id) if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || - pipe_id >= port_params.n_pipes_per_subport) + pipe_id >= subport_params[subport_id].n_pipes_per_subport_enabled) return -1; port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - queue_id += port_params.n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; + queue_id += subport_params[i].n_pipes_per_subport_enabled * + RTE_SCHED_QUEUES_PER_PIPE; queue_id += pipe_id * RTE_SCHED_QUEUES_PER_PIPE; -- 2.21.0
Remove redundant data structure fields from port level data structures and update the release notes. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- doc/guides/rel_notes/release_19_11.rst | 7 ++++- lib/librte_sched/rte_sched.c | 42 +------------------------- lib/librte_sched/rte_sched.h | 22 -------------- 3 files changed, 7 insertions(+), 64 deletions(-) diff --git a/doc/guides/rel_notes/release_19_11.rst b/doc/guides/rel_notes/release_19_11.rst index 23ceb8f67..87812b32c 100644 --- a/doc/guides/rel_notes/release_19_11.rst +++ b/doc/guides/rel_notes/release_19_11.rst @@ -172,6 +172,11 @@ API Changes * ethdev: changed ``rte_eth_dev_owner_delete`` return value from ``void`` to ``int`` to provide a way to report various error conditions. +* sched: The pipe nodes configuration parameters such as number of pipes, + pipe queue sizes, pipe profiles, etc., are moved from port level structure + to subport level. This allows different subports of the same port to + have different configuration for the pipe nodes. + ABI Changes ----------- @@ -259,7 +264,7 @@ The libraries prepended with a plus sign were incremented in this version. librte_rcu.so.1 librte_reorder.so.1 librte_ring.so.2 - librte_sched.so.3 + + librte_sched.so.4 librte_security.so.2 librte_stack.so.1 librte_table.so.3 diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 1faa580d0..710ecf65a 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -216,13 +216,6 @@ struct rte_sched_port { uint32_t mtu; uint32_t frame_overhead; int socket; - uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - uint32_t n_pipe_profiles; - uint32_t n_max_pipe_profiles; - uint32_t pipe_tc_be_rate_max; -#ifdef RTE_SCHED_RED - struct rte_red_config red_config[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; -#endif /* Timing */ uint64_t time_cpu_cycles; /* Current CPU time measured in CPU cyles */ @@ -230,48 +223,15 @@ struct rte_sched_port { uint64_t time; /* Current NIC TX time measured in bytes */ struct rte_reciprocal inv_cycles_per_byte; /* CPU cycles per byte */ - /* Scheduling loop detection */ - uint32_t pipe_loop; - uint32_t pipe_exhaustion; - - /* Bitmap */ - struct rte_bitmap *bmp; - uint32_t grinder_base_bmp_pos[RTE_SCHED_PORT_N_GRINDERS] __rte_aligned_16; - /* Grinders */ - struct rte_sched_grinder grinder[RTE_SCHED_PORT_N_GRINDERS]; - uint32_t busy_grinders; struct rte_mbuf **pkts_out; uint32_t n_pkts_out; uint32_t subport_id; - /* Queue base calculation */ - uint32_t qsize_add[RTE_SCHED_QUEUES_PER_PIPE]; - uint32_t qsize_sum; - /* Large data structures */ - struct rte_sched_subport *subports[0]; - struct rte_sched_subport *subport; - struct rte_sched_pipe *pipe; - struct rte_sched_queue *queue; - struct rte_sched_queue_extra *queue_extra; - struct rte_sched_pipe_profile *pipe_profiles; - uint8_t *bmp_array; - struct rte_mbuf **queue_array; - uint8_t memory[0] __rte_cache_aligned; + struct rte_sched_subport *subports[0] __rte_cache_aligned; } __rte_cache_aligned; -enum rte_sched_port_array { - e_RTE_SCHED_PORT_ARRAY_SUBPORT = 0, - e_RTE_SCHED_PORT_ARRAY_PIPE, - e_RTE_SCHED_PORT_ARRAY_QUEUE, - e_RTE_SCHED_PORT_ARRAY_QUEUE_EXTRA, - e_RTE_SCHED_PORT_ARRAY_PIPE_PROFILES, - e_RTE_SCHED_PORT_ARRAY_BMP_ARRAY, - e_RTE_SCHED_PORT_ARRAY_QUEUE_ARRAY, - e_RTE_SCHED_PORT_ARRAY_TOTAL, -}; - enum rte_sched_subport_array { e_RTE_SCHED_SUBPORT_ARRAY_PIPE = 0, e_RTE_SCHED_SUBPORT_ARRAY_QUEUE, diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index 40f02f124..c82c23c14 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -260,28 +260,6 @@ struct rte_sched_port_params { * the subports of the same port. */ uint32_t n_pipes_per_subport; - - /** Packet queue size for each traffic class. - * All the pipes within the same subport share the similar - * configuration for the queues. - */ - uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - - /** Pipe profile table. - * Every pipe is configured using one of the profiles from this table. - */ - struct rte_sched_pipe_params *pipe_profiles; - - /** Profiles in the pipe profile table */ - uint32_t n_pipe_profiles; - - /** Max profiles allowed in the pipe profile table */ - uint32_t n_max_pipe_profiles; - -#ifdef RTE_SCHED_RED - /** RED parameters */ - struct rte_red_params red_params[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; -#endif }; /* -- 2.21.0
14/10/2019 19:23, Jasvinder Singh: > Modify scheduler packet enqueue operation of the scheduler to allow > different subports of the same port to have different configuration > in terms of number of pipes, pipe queue sizes, etc. > > Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> > Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> > --- [..] > - struct rte_sched_subport *s = port->subport + (qindex / rte_sched_port_queues_per_subport(port)); fatal error: unused function 'rte_sched_port_queues_per_subport' Looks like we need a v6 :)
> -----Original Message-----
> From: Thomas Monjalon <thomas@monjalon.net>
> Sent: Thursday, October 24, 2019 5:45 PM
> To: Singh, Jasvinder <jasvinder.singh@intel.com>
> Cc: dev@dpdk.org; Dumitrescu, Cristian <cristian.dumitrescu@intel.com>;
> Krakowiak, LukaszX <lukaszx.krakowiak@intel.com>
> Subject: Re: [dpdk-dev] [PATCH v5 06/15] sched: modify pkt enqueue for
> config flexibility
>
> 14/10/2019 19:23, Jasvinder Singh:
> > Modify scheduler packet enqueue operation of the scheduler to allow
> > different subports of the same port to have different configuration in
> > terms of number of pipes, pipe queue sizes, etc.
> >
> > Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com>
> > Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com>
> > ---
> [..]
> > - struct rte_sched_subport *s = port->subport + (qindex /
> rte_sched_port_queues_per_subport(port));
>
> fatal error: unused function 'rte_sched_port_queues_per_subport'
>
> Looks like we need a v6 :)
>
Thanks, v6 has been sent out.
This patchset refactors the dpdk qos sched library to allow subport level configuration flexibility of the pipe nodes. Currently, all parameters for the pipe nodes (subscribers) configuration are part of the port level structure which forces all groups of subscribers (pipes) in different subports to have similar configurations in terms of their number, queue sizes, traffic-classes, etc. The new implementation moves pipe nodes configuration parameters from port level to subport level structure. This allows different subports of the same port to have different configuration for the pipe nodes, for examples- number of pipes, queue sizes, pipe profiles, etc. In order to keep the implementation complexity under control, all pipes within the same subport share the same configuration for queue sizes. v6: - fix build issue with patchset v5: - remove patches on 64-bit values support, sent separately v4: - remove deprecation note - rebase on current dpdk head - add 64-bit values support v3: - improve doxygen comments v2: - fix qsize parsing in sample application - fix checkpatch warnings Jasvinder Singh (15): sched: add pipe config params to subport struct sched: modify internal structs for config flexibility sched: remove pipe params config from port level sched: add pipe config to subport level sched: modify pipe functions for config flexibility sched: modify pkt enqueue for config flexibility sched: update memory compute to support flexiblity sched: update grinder functions for config flexibility sched: update pkt dequeue for flexible config sched: update queue stats read for config flexibility test/sched: modify tests for subport config flexibility net/softnic: add subport config flexibility to TM ip_pipeline: add subport config flexibility to TM examples/qos_sched: add subport configuration flexibility sched: remove redundant code app/test/test_sched.c | 35 +- doc/guides/rel_notes/release_19_11.rst | 7 +- drivers/net/softnic/rte_eth_softnic_tm.c | 54 +- examples/ip_pipeline/cli.c | 71 +- examples/ip_pipeline/tmgr.c | 25 +- examples/ip_pipeline/tmgr.h | 7 +- examples/qos_sched/app_thread.c | 20 +- examples/qos_sched/cfg_file.c | 229 ++-- examples/qos_sched/init.c | 54 +- examples/qos_sched/main.h | 1 + examples/qos_sched/profile.cfg | 5 +- examples/qos_sched/profile_ov.cfg | 5 +- examples/qos_sched/stats.c | 44 +- lib/librte_sched/Makefile | 2 +- lib/librte_sched/meson.build | 2 +- lib/librte_sched/rte_sched.c | 1394 +++++++++++++--------- lib/librte_sched/rte_sched.h | 129 +- lib/librte_sched/rte_sched_version.map | 2 +- 18 files changed, 1213 insertions(+), 873 deletions(-) -- 2.21.0
Add pipe configuration parameters to subport level structure to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/Makefile | 2 +- lib/librte_sched/meson.build | 2 +- lib/librte_sched/rte_sched.h | 92 ++++++++++++++++++++++++------------ 3 files changed, 65 insertions(+), 31 deletions(-) diff --git a/lib/librte_sched/Makefile b/lib/librte_sched/Makefile index 3d7f410e1..6e4a72d89 100644 --- a/lib/librte_sched/Makefile +++ b/lib/librte_sched/Makefile @@ -18,7 +18,7 @@ LDLIBS += -lrte_timer EXPORT_MAP := rte_sched_version.map -LIBABIVER := 3 +LIBABIVER := 4 # # all source are stored in SRCS-y diff --git a/lib/librte_sched/meson.build b/lib/librte_sched/meson.build index 59d43c6d8..9f40a2368 100644 --- a/lib/librte_sched/meson.build +++ b/lib/librte_sched/meson.build @@ -1,7 +1,7 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2017 Intel Corporation -version = 3 +version = 4 sources = files('rte_sched.c', 'rte_red.c', 'rte_approx.c') headers = files('rte_sched.h', 'rte_sched_common.h', 'rte_red.h', 'rte_approx.h') diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index eac6db274..fbb0e23fa 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -111,7 +111,7 @@ extern "C" { #endif /* - * Subport configuration parameters. The period and credits_per_period + * Pipe configuration parameters. The period and credits_per_period * parameters are measured in bytes, with one byte meaning the time * duration associated with the transmission of one byte on the * physical medium of the output port, with pipe or pipe traffic class @@ -119,7 +119,7 @@ extern "C" { * credits_per_period divided by period. One credit represents one * byte. */ -struct rte_sched_subport_params { +struct rte_sched_pipe_params { /** Token bucket rate (measured in bytes per second) */ uint32_t tb_rate; @@ -129,32 +129,18 @@ struct rte_sched_subport_params { /** Traffic class rates (measured in bytes per second) */ uint32_t tc_rate[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - /** Enforcement period for rates (measured in milliseconds) */ + /** Enforcement period (measured in milliseconds) */ uint32_t tc_period; -}; - -/** Subport statistics */ -struct rte_sched_subport_stats { - /** Number of packets successfully written */ - uint32_t n_pkts_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - - /** Number of packets dropped */ - uint32_t n_pkts_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - /** Number of bytes successfully written for each traffic class */ - uint32_t n_bytes_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - - /** Number of bytes dropped for each traffic class */ - uint32_t n_bytes_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + /** Best-effort traffic class oversubscription weight */ + uint8_t tc_ov_weight; -#ifdef RTE_SCHED_RED - /** Number of packets dropped by red */ - uint32_t n_pkts_red_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; -#endif + /** WRR weights of best-effort traffic class queues */ + uint8_t wrr_weights[RTE_SCHED_BE_QUEUES_PER_PIPE]; }; /* - * Pipe configuration parameters. The period and credits_per_period + * Subport configuration parameters. The period and credits_per_period * parameters are measured in bytes, with one byte meaning the time * duration associated with the transmission of one byte on the * physical medium of the output port, with pipe or pipe traffic class @@ -162,7 +148,7 @@ struct rte_sched_subport_stats { * credits_per_period divided by period. One credit represents one * byte. */ -struct rte_sched_pipe_params { +struct rte_sched_subport_params { /** Token bucket rate (measured in bytes per second) */ uint32_t tb_rate; @@ -172,14 +158,58 @@ struct rte_sched_pipe_params { /** Traffic class rates (measured in bytes per second) */ uint32_t tc_rate[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - /** Enforcement period (measured in milliseconds) */ + /** Enforcement period for rates (measured in milliseconds) */ uint32_t tc_period; - /** Best-effort traffic class oversubscription weight */ - uint8_t tc_ov_weight; + /** Number of subport pipes. + * The subport can enable/allocate fewer pipes than the maximum + * number set through struct port_params::n_max_pipes_per_subport, + * as needed, to avoid memory allocation for the queues of the + * pipes that are not really needed. + */ + uint32_t n_pipes_per_subport_enabled; - /** WRR weights of best-effort traffic class queues */ - uint8_t wrr_weights[RTE_SCHED_BE_QUEUES_PER_PIPE]; + /** Packet queue size for each traffic class. + * All the pipes within the same subport share the similar + * configuration for the queues. + */ + uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + + /** Pipe profile table. + * Every pipe is configured using one of the profiles from this table. + */ + struct rte_sched_pipe_params *pipe_profiles; + + /** Profiles in the pipe profile table */ + uint32_t n_pipe_profiles; + + /** Max allowed profiles in the pipe profile table */ + uint32_t n_max_pipe_profiles; + +#ifdef RTE_SCHED_RED + /** RED parameters */ + struct rte_red_params red_params[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; +#endif +}; + +/** Subport statistics */ +struct rte_sched_subport_stats { + /** Number of packets successfully written */ + uint32_t n_pkts_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + + /** Number of packets dropped */ + uint32_t n_pkts_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + + /** Number of bytes successfully written for each traffic class */ + uint32_t n_bytes_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + + /** Number of bytes dropped for each traffic class */ + uint32_t n_bytes_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + +#ifdef RTE_SCHED_RED + /** Number of packets dropped by red */ + uint32_t n_pkts_red_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; +#endif }; /** Queue statistics */ @@ -224,7 +254,11 @@ struct rte_sched_port_params { /** Number of subports */ uint32_t n_subports_per_port; - /** Number of subport_pipes */ + /** 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 + * the subports of the same port. + */ uint32_t n_pipes_per_subport; /** Packet queue size for each traffic class. -- 2.21.0
Update internal structures related to port and subport to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 106 ++++++++++++++++++++++++++--------- 1 file changed, 78 insertions(+), 28 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index d8ab21d64..672412b77 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -47,33 +47,6 @@ */ #define RTE_SCHED_TIME_SHIFT 8 -struct rte_sched_subport { - /* Token bucket (TB) */ - uint64_t tb_time; /* time of last update */ - uint32_t tb_period; - uint32_t tb_credits_per_period; - uint32_t tb_size; - uint32_t tb_credits; - - /* Traffic classes (TCs) */ - uint64_t tc_time; /* time of next update */ - uint32_t tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - uint32_t tc_credits[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - uint32_t tc_period; - - /* TC oversubscription */ - uint32_t tc_ov_wm; - uint32_t tc_ov_wm_min; - uint32_t tc_ov_wm_max; - uint8_t tc_ov_period_id; - uint8_t tc_ov; - uint32_t tc_ov_n; - double tc_ov_rate; - - /* Statistics */ - struct rte_sched_subport_stats stats; -}; - struct rte_sched_pipe_profile { /* Token bucket (TB) */ uint32_t tb_period; @@ -107,7 +80,6 @@ struct rte_sched_pipe { /* TC oversubscription */ uint32_t tc_ov_credits; uint8_t tc_ov_period_id; - uint8_t reserved[3]; } __rte_cache_aligned; struct rte_sched_queue { @@ -166,6 +138,72 @@ struct rte_sched_grinder { uint8_t wrr_cost[RTE_SCHED_BE_QUEUES_PER_PIPE]; }; +struct rte_sched_subport { + /* Token bucket (TB) */ + uint64_t tb_time; /* time of last update */ + uint32_t tb_period; + uint32_t tb_credits_per_period; + uint32_t tb_size; + uint32_t tb_credits; + + /* Traffic classes (TCs) */ + uint64_t tc_time; /* time of next update */ + uint32_t tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + uint32_t tc_credits[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + uint32_t tc_period; + + /* TC oversubscription */ + uint32_t tc_ov_wm; + uint32_t tc_ov_wm_min; + uint32_t tc_ov_wm_max; + uint8_t tc_ov_period_id; + uint8_t tc_ov; + uint32_t tc_ov_n; + double tc_ov_rate; + + /* Statistics */ + struct rte_sched_subport_stats stats; + + /* Subport pipes */ + uint32_t n_pipes_per_subport_enabled; + uint32_t n_pipe_profiles; + uint32_t n_max_pipe_profiles; + + /* Pipe best-effort TC rate */ + uint32_t pipe_tc_be_rate_max; + + /* Pipe queues size */ + uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + +#ifdef RTE_SCHED_RED + struct rte_red_config red_config[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; +#endif + + /* Scheduling loop detection */ + uint32_t pipe_loop; + uint32_t pipe_exhaustion; + + /* Bitmap */ + struct rte_bitmap *bmp; + uint32_t grinder_base_bmp_pos[RTE_SCHED_PORT_N_GRINDERS] __rte_aligned_16; + + /* Grinders */ + struct rte_sched_grinder grinder[RTE_SCHED_PORT_N_GRINDERS]; + uint32_t busy_grinders; + + /* Queue base calculation */ + uint32_t qsize_add[RTE_SCHED_QUEUES_PER_PIPE]; + uint32_t qsize_sum; + + struct rte_sched_pipe *pipe; + struct rte_sched_queue *queue; + struct rte_sched_queue_extra *queue_extra; + struct rte_sched_pipe_profile *pipe_profiles; + uint8_t *bmp_array; + struct rte_mbuf **queue_array; + uint8_t memory[0] __rte_cache_aligned; +} __rte_cache_aligned; + struct rte_sched_port { /* User parameters */ uint32_t n_subports_per_port; @@ -177,6 +215,7 @@ struct rte_sched_port { uint32_t rate; uint32_t mtu; uint32_t frame_overhead; + int socket; uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; uint32_t n_pipe_profiles; uint32_t n_max_pipe_profiles; @@ -210,6 +249,7 @@ struct rte_sched_port { uint32_t qsize_sum; /* Large data structures */ + struct rte_sched_subport *subports[0]; struct rte_sched_subport *subport; struct rte_sched_pipe *pipe; struct rte_sched_queue *queue; @@ -231,6 +271,16 @@ enum rte_sched_port_array { e_RTE_SCHED_PORT_ARRAY_TOTAL, }; +enum rte_sched_subport_array { + e_RTE_SCHED_SUBPORT_ARRAY_PIPE = 0, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_EXTRA, + e_RTE_SCHED_SUBPORT_ARRAY_PIPE_PROFILES, + e_RTE_SCHED_SUBPORT_ARRAY_BMP_ARRAY, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_ARRAY, + e_RTE_SCHED_SUBPORT_ARRAY_TOTAL, +}; + #ifdef RTE_SCHED_COLLECT_STATS static inline uint32_t -- 2.21.0
Remove pipes configuration from the port level to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 254 ++++++++++------------------------- 1 file changed, 71 insertions(+), 183 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 672412b77..952e449f7 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -291,6 +291,31 @@ rte_sched_port_queues_per_subport(struct rte_sched_port *port) #endif +static inline uint32_t +rte_sched_subport_pipe_queues(struct rte_sched_subport *subport) +{ + return RTE_SCHED_QUEUES_PER_PIPE * subport->n_pipes_per_subport_enabled; +} + +static inline struct rte_mbuf ** +rte_sched_subport_pipe_qbase(struct rte_sched_subport *subport, uint32_t qindex) +{ + uint32_t pindex = qindex >> 4; + uint32_t qpos = qindex & (RTE_SCHED_QUEUES_PER_PIPE - 1); + + return (subport->queue_array + pindex * + subport->qsize_sum + subport->qsize_add[qpos]); +} + +static inline uint16_t +rte_sched_subport_pipe_qsize(struct rte_sched_port *port, +struct rte_sched_subport *subport, uint32_t qindex) +{ + uint32_t tc = port->pipe_tc[qindex & (RTE_SCHED_QUEUES_PER_PIPE - 1)]; + + return subport->qsize[tc]; +} + static inline uint32_t rte_sched_port_queues_per_port(struct rte_sched_port *port) { @@ -414,8 +439,6 @@ pipe_profile_check(struct rte_sched_pipe_params *params, 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__); @@ -456,45 +479,10 @@ rte_sched_port_check_params(struct rte_sched_port_params *params) if (params->n_pipes_per_subport == 0 || !rte_is_power_of_2(params->n_pipes_per_subport)) { RTE_LOG(ERR, SCHED, - "%s: Incorrect value for pipes number\n", __func__); - return -EINVAL; - } - - /* qsize: if non-zero, power of 2, - * no bigger than 32K (due to 16-bit read/write pointers) - */ - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - uint16_t qsize = params->qsize[i]; - - if ((qsize != 0 && !rte_is_power_of_2(qsize)) || - ((i == RTE_SCHED_TRAFFIC_CLASS_BE) && (qsize == 0))) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tc rate\n", __func__); - return -EINVAL; - } - } - - /* pipe_profiles and n_pipe_profiles */ - if (params->pipe_profiles == NULL || - params->n_pipe_profiles == 0 || - params->n_pipe_profiles > params->n_max_pipe_profiles) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for number of pipe profiles\n", __func__); + "%s: Incorrect value for maximum pipes number\n", __func__); return -EINVAL; } - for (i = 0; i < params->n_pipe_profiles; i++) { - struct rte_sched_pipe_params *p = params->pipe_profiles + i; - int status; - - status = pipe_profile_check(p, params->rate, ¶ms->qsize[0]); - if (status != 0) { - RTE_LOG(ERR, SCHED, - "%s: Pipe profile check failed(%d)\n", __func__, status); - return -EINVAL; - } - } - return 0; } @@ -582,32 +570,6 @@ rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params) return size0 + size1; } -static void -rte_sched_port_config_qsize(struct rte_sched_port *port) -{ - uint32_t i; - - port->qsize_add[0] = 0; - - /* Strict prority traffic class */ - for (i = 1; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - port->qsize_add[i] = port->qsize_add[i-1] + port->qsize[i-1]; - - /* Best-effort traffic class */ - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 1] = - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE] + - port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 2] = - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 1] + - port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 3] = - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 2] + - port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; - - port->qsize_sum = port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 3] + - port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; -} - static void rte_sched_port_log_pipe_profile(struct rte_sched_port *port, uint32_t i) { @@ -717,56 +679,41 @@ rte_sched_pipe_profile_convert(struct rte_sched_port *port, dst->wrr_cost[3] = (uint8_t) wrr_cost[3]; } -static void -rte_sched_port_config_pipe_profile_table(struct rte_sched_port *port, - struct rte_sched_port_params *params) -{ - uint32_t i; - - for (i = 0; i < port->n_pipe_profiles; i++) { - struct rte_sched_pipe_params *src = params->pipe_profiles + i; - struct rte_sched_pipe_profile *dst = port->pipe_profiles + i; - - rte_sched_pipe_profile_convert(port, src, dst, params->rate); - rte_sched_port_log_pipe_profile(port, i); - } - - port->pipe_tc_be_rate_max = 0; - for (i = 0; i < port->n_pipe_profiles; i++) { - struct rte_sched_pipe_params *src = params->pipe_profiles + i; - uint32_t pipe_tc_be_rate = src->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; - - if (port->pipe_tc_be_rate_max < pipe_tc_be_rate) - port->pipe_tc_be_rate_max = pipe_tc_be_rate; - } -} - struct rte_sched_port * rte_sched_port_config(struct rte_sched_port_params *params) { struct rte_sched_port *port = NULL; - uint32_t mem_size, bmp_mem_size, n_queues_per_port, i, j, cycles_per_byte; + uint32_t size0, size1; + uint32_t cycles_per_byte; + uint32_t i, j; + int status; - /* Check user parameters. Determine the amount of memory to allocate */ - mem_size = rte_sched_port_get_memory_footprint(params); - if (mem_size == 0) + status = rte_sched_port_check_params(params); + if (status != 0) { + RTE_LOG(ERR, SCHED, + "%s: Port scheduler params check failed (%d)\n", + __func__, status); return NULL; + } + + size0 = sizeof(struct rte_sched_port); + size1 = params->n_subports_per_port * sizeof(struct rte_sched_subport *); /* Allocate memory to store the data structures */ - port = rte_zmalloc_socket("qos_params", mem_size, RTE_CACHE_LINE_SIZE, + port = rte_zmalloc_socket("qos_params", size0 + size1, RTE_CACHE_LINE_SIZE, params->socket); - if (port == NULL) - return NULL; + if (port == NULL) { + RTE_LOG(ERR, SCHED, "%s: Memory allocation fails\n", __func__); - /* compile time checks */ - RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS == 0); - RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS & (RTE_SCHED_PORT_N_GRINDERS - 1)); + return NULL; + } /* User parameters */ port->n_subports_per_port = params->n_subports_per_port; port->n_pipes_per_subport = params->n_pipes_per_subport; port->n_pipes_per_subport_log2 = __builtin_ctz(params->n_pipes_per_subport); + port->socket = params->socket; for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) port->pipe_queue[i] = i; @@ -787,32 +734,6 @@ rte_sched_port_config(struct rte_sched_port_params *params) port->rate = params->rate; port->mtu = params->mtu + params->frame_overhead; port->frame_overhead = params->frame_overhead; - memcpy(port->qsize, params->qsize, sizeof(params->qsize)); - port->n_pipe_profiles = params->n_pipe_profiles; - port->n_max_pipe_profiles = params->n_max_pipe_profiles; - -#ifdef RTE_SCHED_RED - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - uint32_t j; - - for (j = 0; j < RTE_COLORS; j++) { - /* if min/max are both zero, then RED is disabled */ - if ((params->red_params[i][j].min_th | - params->red_params[i][j].max_th) == 0) { - continue; - } - - if (rte_red_config_init(&port->red_config[i][j], - params->red_params[i][j].wq_log2, - params->red_params[i][j].min_th, - params->red_params[i][j].max_th, - params->red_params[i][j].maxp_inv) != 0) { - rte_free(port); - return NULL; - } - } - } -#endif /* Timing */ port->time_cpu_cycles = rte_get_tsc_cycles(); @@ -823,79 +744,32 @@ rte_sched_port_config(struct rte_sched_port_params *params) / params->rate; port->inv_cycles_per_byte = rte_reciprocal_value(cycles_per_byte); - /* Scheduling loop detection */ - port->pipe_loop = RTE_SCHED_PIPE_INVALID; - port->pipe_exhaustion = 0; - /* Grinders */ - port->busy_grinders = 0; port->pkts_out = NULL; port->n_pkts_out = 0; - /* Queue base calculation */ - rte_sched_port_config_qsize(port); - - /* Large data structures */ - port->subport = (struct rte_sched_subport *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_SUBPORT)); - port->pipe = (struct rte_sched_pipe *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_PIPE)); - port->queue = (struct rte_sched_queue *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_QUEUE)); - port->queue_extra = (struct rte_sched_queue_extra *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_QUEUE_EXTRA)); - port->pipe_profiles = (struct rte_sched_pipe_profile *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_PIPE_PROFILES)); - port->bmp_array = port->memory - + rte_sched_port_get_array_base(params, e_RTE_SCHED_PORT_ARRAY_BMP_ARRAY); - port->queue_array = (struct rte_mbuf **) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_QUEUE_ARRAY)); - - /* Pipe profile table */ - rte_sched_port_config_pipe_profile_table(port, params); - - /* Bitmap */ - n_queues_per_port = rte_sched_port_queues_per_port(port); - bmp_mem_size = rte_bitmap_get_memory_footprint(n_queues_per_port); - port->bmp = rte_bitmap_init(n_queues_per_port, port->bmp_array, - bmp_mem_size); - if (port->bmp == NULL) { - RTE_LOG(ERR, SCHED, "Bitmap init error\n"); - rte_free(port); - return NULL; - } - - for (i = 0; i < RTE_SCHED_PORT_N_GRINDERS; i++) - port->grinder_base_bmp_pos[i] = RTE_SCHED_PIPE_INVALID; - - return port; } -void -rte_sched_port_free(struct rte_sched_port *port) +static inline void +rte_sched_subport_free(struct rte_sched_port *port, + struct rte_sched_subport *subport) { + uint32_t n_subport_pipe_queues; uint32_t qindex; - uint32_t n_queues_per_port; - /* Check user parameters */ - if (port == NULL) + if (subport == NULL) return; - n_queues_per_port = rte_sched_port_queues_per_port(port); + n_subport_pipe_queues = rte_sched_subport_pipe_queues(subport); /* Free enqueued mbufs */ - for (qindex = 0; qindex < n_queues_per_port; qindex++) { - struct rte_mbuf **mbufs = rte_sched_port_qbase(port, qindex); - uint16_t qsize = rte_sched_port_qsize(port, qindex); + for (qindex = 0; qindex < n_subport_pipe_queues; qindex++) { + struct rte_mbuf **mbufs = + rte_sched_subport_pipe_qbase(subport, qindex); + uint16_t qsize = rte_sched_subport_pipe_qsize(port, subport, qindex); if (qsize != 0) { - struct rte_sched_queue *queue = port->queue + qindex; + struct rte_sched_queue *queue = subport->queue + qindex; uint16_t qr = queue->qr & (qsize - 1); uint16_t qw = queue->qw & (qsize - 1); @@ -904,7 +778,21 @@ rte_sched_port_free(struct rte_sched_port *port) } } - rte_bitmap_free(port->bmp); + rte_bitmap_free(subport->bmp); +} + +void +rte_sched_port_free(struct rte_sched_port *port) +{ + uint32_t i; + + /* Check user parameters */ + if (port == NULL) + return; + + for (i = 0; i < port->n_subports_per_port; i++) + rte_sched_subport_free(port, port->subports[i]); + rte_free(port); } -- 2.21.0
Add pipes configuration from the port level to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 388 ++++++++++++++++++++++++++++++----- 1 file changed, 332 insertions(+), 56 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 952e449f7..60dfc6232 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -550,24 +550,91 @@ rte_sched_port_get_array_base(struct rte_sched_port_params *params, enum rte_sch return base; } -uint32_t -rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params) +static uint32_t +rte_sched_subport_get_array_base(struct rte_sched_subport_params *params, + enum rte_sched_subport_array array) { - uint32_t size0, size1; - int status; + uint32_t n_pipes_per_subport = params->n_pipes_per_subport_enabled; + uint32_t n_subport_pipe_queues = + RTE_SCHED_QUEUES_PER_PIPE * n_pipes_per_subport; - status = rte_sched_port_check_params(params); - if (status != 0) { - RTE_LOG(NOTICE, SCHED, - "Port scheduler params check failed (%d)\n", status); + uint32_t size_pipe = n_pipes_per_subport * sizeof(struct rte_sched_pipe); + uint32_t size_queue = + n_subport_pipe_queues * sizeof(struct rte_sched_queue); + uint32_t size_queue_extra + = n_subport_pipe_queues * sizeof(struct rte_sched_queue_extra); + uint32_t size_pipe_profiles = params->n_max_pipe_profiles * + sizeof(struct rte_sched_pipe_profile); + uint32_t size_bmp_array = + rte_bitmap_get_memory_footprint(n_subport_pipe_queues); + uint32_t size_per_pipe_queue_array, size_queue_array; - return 0; + uint32_t base, i; + + size_per_pipe_queue_array = 0; + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + if (i < RTE_SCHED_TRAFFIC_CLASS_BE) + size_per_pipe_queue_array += + params->qsize[i] * sizeof(struct rte_mbuf *); + else + size_per_pipe_queue_array += RTE_SCHED_MAX_QUEUES_PER_TC * + params->qsize[i] * sizeof(struct rte_mbuf *); } + size_queue_array = n_pipes_per_subport * size_per_pipe_queue_array; - size0 = sizeof(struct rte_sched_port); - size1 = rte_sched_port_get_array_base(params, e_RTE_SCHED_PORT_ARRAY_TOTAL); + base = 0; - return size0 + size1; + if (array == e_RTE_SCHED_SUBPORT_ARRAY_PIPE) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_pipe); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_QUEUE) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_queue); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_EXTRA) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_queue_extra); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_PIPE_PROFILES) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_pipe_profiles); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_BMP_ARRAY) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_bmp_array); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_ARRAY) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_queue_array); + + return base; +} + +static void +rte_sched_subport_config_qsize(struct rte_sched_subport *subport) +{ + uint32_t i; + + subport->qsize_add[0] = 0; + + /* Strict prority traffic class */ + for (i = 1; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) + subport->qsize_add[i] = subport->qsize_add[i-1] + subport->qsize[i-1]; + + /* Best-effort traffic class */ + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 1] = + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE] + + subport->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 2] = + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 1] + + subport->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 3] = + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 2] + + subport->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; + + subport->qsize_sum = subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 3] + + subport->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; } static void @@ -679,6 +746,126 @@ rte_sched_pipe_profile_convert(struct rte_sched_port *port, dst->wrr_cost[3] = (uint8_t) wrr_cost[3]; } +static int +rte_sched_subport_check_params(struct rte_sched_subport_params *params, + uint32_t n_max_pipes_per_subport, + uint32_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; + } + + /* qsize: if non-zero, power of 2, + * no bigger than 32K (due to 16-bit read/write pointers) + */ + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + uint16_t qsize = params->qsize[i]; + + if (qsize != 0 && !rte_is_power_of_2(qsize)) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for qsize\n", __func__); + return -EINVAL; + } + } + + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + uint32_t tc_rate = params->tc_rate[i]; + uint16_t qsize = params->qsize[i]; + + if ((qsize == 0 && tc_rate != 0) || + (qsize != 0 && tc_rate == 0) || + (tc_rate > params->tb_rate)) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for tc rate\n", __func__); + return -EINVAL; + } + } + + if (params->qsize[RTE_SCHED_TRAFFIC_CLASS_BE] == 0 || + params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE] == 0) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect qsize or 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; + } + + /* n_pipes_per_subport: non-zero, power of 2 */ + if (params->n_pipes_per_subport_enabled == 0 || + params->n_pipes_per_subport_enabled > n_max_pipes_per_subport || + !rte_is_power_of_2(params->n_pipes_per_subport_enabled)) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for pipes number\n", __func__); + return -EINVAL; + } + + /* pipe_profiles and n_pipe_profiles */ + if (params->pipe_profiles == NULL || + params->n_pipe_profiles == 0 || + params->n_max_pipe_profiles == 0 || + params->n_pipe_profiles > params->n_max_pipe_profiles) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for pipe profiles\n", __func__); + return -EINVAL; + } + + for (i = 0; i < params->n_pipe_profiles; i++) { + struct rte_sched_pipe_params *p = params->pipe_profiles + i; + int status; + + status = pipe_profile_check(p, rate, ¶ms->qsize[0]); + if (status != 0) { + RTE_LOG(ERR, SCHED, + "%s: Pipe profile check failed(%d)\n", __func__, status); + return -EINVAL; + } + } + + return 0; +} + +uint32_t +rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params) +{ + uint32_t size0, size1; + int status; + + status = rte_sched_port_check_params(params); + if (status != 0) { + RTE_LOG(NOTICE, SCHED, + "Port scheduler params check failed (%d)\n", status); + + return 0; + } + + size0 = sizeof(struct rte_sched_port); + size1 = rte_sched_port_get_array_base(params, + e_RTE_SCHED_PORT_ARRAY_TOTAL); + + return size0 + size1; +} + struct rte_sched_port * rte_sched_port_config(struct rte_sched_port_params *params) { @@ -799,7 +986,7 @@ rte_sched_port_free(struct rte_sched_port *port) static void rte_sched_port_log_subport_config(struct rte_sched_port *port, uint32_t i) { - struct rte_sched_subport *s = port->subport + i; + struct rte_sched_subport *s = port->subports[i]; RTE_LOG(DEBUG, SCHED, "Low level config for subport %u:\n" " Token bucket: period = %u, credits per period = %u, size = %u\n" @@ -834,72 +1021,78 @@ rte_sched_port_log_subport_config(struct rte_sched_port *port, uint32_t i) s->tc_ov_wm_max); } +static void +rte_sched_free_memory(struct rte_sched_port *port, uint32_t n_subports) +{ + uint32_t i; + + for (i = 0; i < n_subports; i++) { + struct rte_sched_subport *subport = port->subports[i]; + + rte_sched_subport_free(port, subport); + } + + rte_free(port); +} + int rte_sched_subport_config(struct rte_sched_port *port, uint32_t subport_id, struct rte_sched_subport_params *params) { - struct rte_sched_subport *s; - uint32_t i; + struct rte_sched_subport *s = NULL; + uint32_t n_subports = subport_id; + uint32_t n_subport_pipe_queues, i; + uint32_t size0, size1, bmp_mem_size; + int status; /* Check user parameters */ if (port == NULL) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for parameter port\n", __func__); - return -EINVAL; + return 0; } if (subport_id >= port->n_subports_per_port) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for subport id\n", __func__); - return -EINVAL; - } - if (params == NULL) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for parameter params\n", __func__); + rte_sched_free_memory(port, n_subports); return -EINVAL; } - if (params->tb_rate == 0 || params->tb_rate > port->rate) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tb rate\n", __func__); - return -EINVAL; - } + status = rte_sched_subport_check_params(params, + port->n_pipes_per_subport, + port->rate); + if (status != 0) { + RTE_LOG(NOTICE, SCHED, + "%s: Port scheduler params check failed (%d)\n", + __func__, status); - if (params->tb_size == 0) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tb size\n", __func__); + rte_sched_free_memory(port, n_subports); return -EINVAL; } - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - uint32_t tc_rate = params->tc_rate[i]; - uint16_t qsize = port->qsize[i]; + /* Determine the amount of memory to allocate */ + size0 = sizeof(struct rte_sched_subport); + size1 = rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_TOTAL); - if ((qsize == 0 && tc_rate != 0) || - (qsize != 0 && tc_rate == 0) || - (tc_rate > params->tb_rate)) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tc rate\n", __func__); - return -EINVAL; - } - } - - if (port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE] == 0 || - params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE] == 0) { + /* Allocate memory to store the data structures */ + s = rte_zmalloc_socket("subport_params", size0 + size1, + RTE_CACHE_LINE_SIZE, port->socket); + if (s == NULL) { RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tc rate(best effort)\n", __func__); - return -EINVAL; - } + "%s: Memory allocation fails\n", __func__); - if (params->tc_period == 0) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tc period\n", __func__); - return -EINVAL; + rte_sched_free_memory(port, n_subports); + return -ENOMEM; } - s = port->subport + subport_id; + n_subports++; + + /* Port */ + port->subports[subport_id] = s; /* Token Bucket (TB) */ if (params->tb_rate == port->rate) { @@ -919,26 +1112,109 @@ rte_sched_subport_config(struct rte_sched_port *port, /* Traffic Classes (TCs) */ s->tc_period = rte_sched_time_ms_to_bytes(params->tc_period, port->rate); for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - if (port->qsize[i]) + if (params->qsize[i]) s->tc_credits_per_period[i] = rte_sched_time_ms_to_bytes(params->tc_period, - params->tc_rate[i]); - + params->tc_rate[i]); } s->tc_time = port->time + s->tc_period; for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - if (port->qsize[i]) + if (params->qsize[i]) s->tc_credits[i] = s->tc_credits_per_period[i]; + /* compile time checks */ + RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS == 0); + RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS & + (RTE_SCHED_PORT_N_GRINDERS - 1)); + + /* User parameters */ + s->n_pipes_per_subport_enabled = params->n_pipes_per_subport_enabled; + memcpy(s->qsize, params->qsize, sizeof(params->qsize)); + s->n_pipe_profiles = params->n_pipe_profiles; + s->n_max_pipe_profiles = params->n_max_pipe_profiles; + +#ifdef RTE_SCHED_RED + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + uint32_t j; + + for (j = 0; j < RTE_COLORS; j++) { + /* if min/max are both zero, then RED is disabled */ + if ((params->red_params[i][j].min_th | + params->red_params[i][j].max_th) == 0) { + continue; + } + + if (rte_red_config_init(&s->red_config[i][j], + params->red_params[i][j].wq_log2, + params->red_params[i][j].min_th, + params->red_params[i][j].max_th, + params->red_params[i][j].maxp_inv) != 0) { + rte_sched_free_memory(port, n_subports); + + RTE_LOG(NOTICE, SCHED, + "%s: RED configuration init fails\n", __func__); + return -EINVAL; + } + } + } +#endif + + /* Scheduling loop detection */ + s->pipe_loop = RTE_SCHED_PIPE_INVALID; + s->pipe_exhaustion = 0; + + /* Grinders */ + s->busy_grinders = 0; + + /* Queue base calculation */ + rte_sched_subport_config_qsize(s); + + /* Large data structures */ + s->pipe = (struct rte_sched_pipe *) + (s->memory + rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_PIPE)); + s->queue = (struct rte_sched_queue *) + (s->memory + rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE)); + s->queue_extra = (struct rte_sched_queue_extra *) + (s->memory + rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_EXTRA)); + s->pipe_profiles = (struct rte_sched_pipe_profile *) + (s->memory + rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_PIPE_PROFILES)); + s->bmp_array = s->memory + rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_BMP_ARRAY); + s->queue_array = (struct rte_mbuf **) + (s->memory + rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_ARRAY)); + + /* Bitmap */ + n_subport_pipe_queues = rte_sched_subport_pipe_queues(s); + bmp_mem_size = rte_bitmap_get_memory_footprint(n_subport_pipe_queues); + s->bmp = rte_bitmap_init(n_subport_pipe_queues, s->bmp_array, + bmp_mem_size); + if (s->bmp == NULL) { + RTE_LOG(ERR, SCHED, + "%s: Subport bitmap init error\n", __func__); + + rte_sched_free_memory(port, n_subports); + return -EINVAL; + } + + for (i = 0; i < RTE_SCHED_PORT_N_GRINDERS; i++) + s->grinder_base_bmp_pos[i] = RTE_SCHED_PIPE_INVALID; + +#ifdef RTE_SCHED_SUBPORT_TC_OV /* TC oversubscription */ s->tc_ov_wm_min = port->mtu; s->tc_ov_wm_max = rte_sched_time_ms_to_bytes(params->tc_period, - port->pipe_tc_be_rate_max); + s->pipe_tc_be_rate_max); s->tc_ov_wm = s->tc_ov_wm_max; s->tc_ov_period_id = 0; s->tc_ov = 0; s->tc_ov_n = 0; s->tc_ov_rate = 0; +#endif rte_sched_port_log_subport_config(port, subport_id); -- 2.21.0
Modify pipe level functions to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 103 +++++++++++++++++-------- lib/librte_sched/rte_sched.h | 7 +- lib/librte_sched/rte_sched_version.map | 2 +- 3 files changed, 76 insertions(+), 36 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 60dfc6232..6b6219e45 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -638,9 +638,9 @@ rte_sched_subport_config_qsize(struct rte_sched_subport *subport) } static void -rte_sched_port_log_pipe_profile(struct rte_sched_port *port, uint32_t i) +rte_sched_port_log_pipe_profile(struct rte_sched_subport *subport, uint32_t i) { - struct rte_sched_pipe_profile *p = port->pipe_profiles + i; + struct rte_sched_pipe_profile *p = subport->pipe_profiles + i; RTE_LOG(DEBUG, SCHED, "Low level config for pipe profile %u:\n" " Token bucket: period = %u, credits per period = %u, size = %u\n" @@ -689,7 +689,7 @@ rte_sched_time_ms_to_bytes(uint32_t time_ms, uint32_t rate) } static void -rte_sched_pipe_profile_convert(struct rte_sched_port *port, +rte_sched_pipe_profile_convert(struct rte_sched_subport *subport, struct rte_sched_pipe_params *src, struct rte_sched_pipe_profile *dst, uint32_t rate) @@ -718,7 +718,7 @@ rte_sched_pipe_profile_convert(struct rte_sched_port *port, rate); for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - if (port->qsize[i]) + if (subport->qsize[i]) dst->tc_credits_per_period[i] = rte_sched_time_ms_to_bytes(src->tc_period, src->tc_rate[i]); @@ -746,6 +746,30 @@ rte_sched_pipe_profile_convert(struct rte_sched_port *port, dst->wrr_cost[3] = (uint8_t) wrr_cost[3]; } +static void +rte_sched_subport_config_pipe_profile_table(struct rte_sched_subport *subport, + struct rte_sched_subport_params *params, uint32_t rate) +{ + uint32_t i; + + for (i = 0; i < subport->n_pipe_profiles; i++) { + struct rte_sched_pipe_params *src = params->pipe_profiles + i; + struct rte_sched_pipe_profile *dst = subport->pipe_profiles + i; + + rte_sched_pipe_profile_convert(subport, src, dst, rate); + rte_sched_port_log_pipe_profile(subport, i); + } + + subport->pipe_tc_be_rate_max = 0; + for (i = 0; i < subport->n_pipe_profiles; i++) { + struct rte_sched_pipe_params *src = params->pipe_profiles + i; + uint32_t pipe_tc_be_rate = src->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; + + if (subport->pipe_tc_be_rate_max < pipe_tc_be_rate) + subport->pipe_tc_be_rate_max = pipe_tc_be_rate; + } +} + static int rte_sched_subport_check_params(struct rte_sched_subport_params *params, uint32_t n_max_pipes_per_subport, @@ -1188,6 +1212,9 @@ rte_sched_subport_config(struct rte_sched_port *port, (s->memory + rte_sched_subport_get_array_base(params, e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_ARRAY)); + /* Pipe profile table */ + rte_sched_subport_config_pipe_profile_table(s, params, port->rate); + /* Bitmap */ n_subport_pipe_queues = rte_sched_subport_pipe_queues(s); bmp_mem_size = rte_bitmap_get_memory_footprint(n_subport_pipe_queues); @@ -1230,6 +1257,7 @@ rte_sched_pipe_config(struct rte_sched_port *port, struct rte_sched_subport *s; struct rte_sched_pipe *p; struct rte_sched_pipe_profile *params; + uint32_t n_subports = subport_id + 1; uint32_t deactivate, profile, i; /* Check user parameters */ @@ -1245,34 +1273,32 @@ rte_sched_pipe_config(struct rte_sched_port *port, if (subport_id >= port->n_subports_per_port) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for parameter subport id\n", __func__); + + rte_sched_free_memory(port, n_subports); return -EINVAL; } - if (pipe_id >= port->n_pipes_per_subport) { + s = port->subports[subport_id]; + if (pipe_id >= s->n_pipes_per_subport_enabled) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for parameter pipe id\n", __func__); + + rte_sched_free_memory(port, n_subports); return -EINVAL; } - if (!deactivate && profile >= port->n_pipe_profiles) { + if (!deactivate && profile >= s->n_pipe_profiles) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for parameter pipe profile\n", __func__); - return -EINVAL; - } - /* Check that subport configuration is valid */ - s = port->subport + subport_id; - if (s->tb_period == 0) { - RTE_LOG(ERR, SCHED, - "%s: Subport configuration invalid\n", __func__); + rte_sched_free_memory(port, n_subports); return -EINVAL; } - p = port->pipe + (subport_id * port->n_pipes_per_subport + pipe_id); - /* Handle the case when pipe already has a valid configuration */ + p = s->pipe + pipe_id; if (p->tb_time) { - params = port->pipe_profiles + p->profile; + params = s->pipe_profiles + p->profile; double subport_tc_be_rate = (double) s->tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASS_BE] @@ -1302,7 +1328,7 @@ rte_sched_pipe_config(struct rte_sched_port *port, /* Apply the new pipe configuration */ p->profile = profile; - params = port->pipe_profiles + p->profile; + params = s->pipe_profiles + p->profile; /* Token Bucket (TB) */ p->tb_time = port->time; @@ -1312,7 +1338,7 @@ rte_sched_pipe_config(struct rte_sched_port *port, p->tc_time = port->time + params->tc_period; for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - if (port->qsize[i]) + if (s->qsize[i]) p->tc_credits[i] = params->tc_credits_per_period[i]; { @@ -1342,10 +1368,12 @@ rte_sched_pipe_config(struct rte_sched_port *port, } int -rte_sched_port_pipe_profile_add(struct rte_sched_port *port, +rte_sched_subport_pipe_profile_add(struct rte_sched_port *port, + uint32_t subport_id, struct rte_sched_pipe_params *params, uint32_t *pipe_profile_id) { + struct rte_sched_subport *s; struct rte_sched_pipe_profile *pp; uint32_t i; int status; @@ -1357,40 +1385,49 @@ rte_sched_port_pipe_profile_add(struct rte_sched_port *port, return -EINVAL; } - /* Pipe profiles not exceeds the max limit */ - if (port->n_pipe_profiles >= port->n_max_pipe_profiles) { + /* Subport id not exceeds the max limit */ + if (subport_id > port->n_subports_per_port) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for subport id\n", __func__); + return -EINVAL; + } + + s = port->subports[subport_id]; + + /* Pipe profiles exceeds the max limit */ + if (s->n_pipe_profiles >= s->n_max_pipe_profiles) { RTE_LOG(ERR, SCHED, "%s: Number of pipe profiles exceeds the max limit\n", __func__); return -EINVAL; } /* Pipe params */ - status = pipe_profile_check(params, port->rate, &port->qsize[0]); + status = pipe_profile_check(params, port->rate, &s->qsize[0]); if (status != 0) { RTE_LOG(ERR, SCHED, "%s: Pipe profile check failed(%d)\n", __func__, status); return -EINVAL; } - pp = &port->pipe_profiles[port->n_pipe_profiles]; - rte_sched_pipe_profile_convert(port, params, pp, port->rate); + pp = &s->pipe_profiles[s->n_pipe_profiles]; + rte_sched_pipe_profile_convert(s, params, pp, port->rate); - /* Pipe profile not exists */ - for (i = 0; i < port->n_pipe_profiles; i++) - if (memcmp(port->pipe_profiles + i, pp, sizeof(*pp)) == 0) { + /* Pipe profile should not exists */ + for (i = 0; i < s->n_pipe_profiles; i++) + if (memcmp(s->pipe_profiles + i, pp, sizeof(*pp)) == 0) { RTE_LOG(ERR, SCHED, - "%s: Pipe profile doesn't exist\n", __func__); + "%s: Pipe profile exists\n", __func__); return -EINVAL; } /* Pipe profile commit */ - *pipe_profile_id = port->n_pipe_profiles; - port->n_pipe_profiles++; + *pipe_profile_id = s->n_pipe_profiles; + s->n_pipe_profiles++; - if (port->pipe_tc_be_rate_max < params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]) - port->pipe_tc_be_rate_max = params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; + if (s->pipe_tc_be_rate_max < params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]) + s->pipe_tc_be_rate_max = params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; - rte_sched_port_log_pipe_profile(port, *pipe_profile_id); + rte_sched_port_log_pipe_profile(s, *pipe_profile_id); return 0; } diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index fbb0e23fa..5001f09ed 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -317,6 +317,8 @@ rte_sched_port_free(struct rte_sched_port *port); * * @param port * Handle to port scheduler instance + * @param subport_id + * Subport ID * @param params * Pipe profile parameters * @param pipe_profile_id @@ -326,7 +328,8 @@ rte_sched_port_free(struct rte_sched_port *port); */ __rte_experimental int -rte_sched_port_pipe_profile_add(struct rte_sched_port *port, +rte_sched_subport_pipe_profile_add(struct rte_sched_port *port, + uint32_t subport_id, struct rte_sched_pipe_params *params, uint32_t *pipe_profile_id); @@ -357,7 +360,7 @@ rte_sched_subport_config(struct rte_sched_port *port, * @param pipe_id * Pipe ID within subport * @param pipe_profile - * ID of port-level pre-configured pipe profile + * ID of subport-level pre-configured pipe profile * @return * 0 upon success, error code otherwise */ diff --git a/lib/librte_sched/rte_sched_version.map b/lib/librte_sched/rte_sched_version.map index 729588794..f33761e63 100644 --- a/lib/librte_sched/rte_sched_version.map +++ b/lib/librte_sched/rte_sched_version.map @@ -33,5 +33,5 @@ DPDK_2.1 { EXPERIMENTAL { global: - rte_sched_port_pipe_profile_add; + rte_sched_subport_pipe_profile_add; }; -- 2.21.0
Modify scheduler packet enqueue operation of the scheduler to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 277 ++++++++++++++++++++++------------- 1 file changed, 178 insertions(+), 99 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 6b6219e45..a8174afad 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -1440,10 +1440,11 @@ rte_sched_port_qindex(struct rte_sched_port *port, 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) | - ((rte_sched_port_pipe_queue(port, traffic_class) + queue) & - (RTE_SCHED_QUEUES_PER_PIPE - 1)); + (port->n_pipes_per_subport_log2 + 4)) | + ((pipe & + (port->subports[subport]->n_pipes_per_subport_enabled - 1)) << 4) | + ((rte_sched_port_pipe_queue(port, traffic_class) + queue) & + (RTE_SCHED_QUEUES_PER_PIPE - 1)); } void @@ -1468,7 +1469,8 @@ rte_sched_port_pkt_read_tree_path(struct rte_sched_port *port, uint32_t queue_id = rte_mbuf_sched_queue_get(pkt); *subport = queue_id >> (port->n_pipes_per_subport_log2 + 4); - *pipe = (queue_id >> 4) & (port->n_pipes_per_subport - 1); + *pipe = (queue_id >> 4) & + (port->subports[*subport]->n_pipes_per_subport_enabled - 1); *traffic_class = rte_sched_port_pipe_tc(port, queue_id); *queue = rte_sched_port_tc_queue(port, queue_id); } @@ -1512,7 +1514,7 @@ rte_sched_subport_read_stats(struct rte_sched_port *port, return -EINVAL; } - s = port->subport + subport_id; + s = port->subports[subport_id]; /* Copy subport stats and clear */ memcpy(stats, &s->stats, sizeof(struct rte_sched_subport_stats)); @@ -1585,43 +1587,50 @@ rte_sched_port_queue_is_empty(struct rte_sched_port *port, uint32_t qindex) #ifdef RTE_SCHED_COLLECT_STATS static inline void -rte_sched_port_update_subport_stats(struct rte_sched_port *port, uint32_t qindex, struct rte_mbuf *pkt) +rte_sched_port_update_subport_stats(struct rte_sched_port *port, + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt) { - struct rte_sched_subport *s = port->subport + (qindex / rte_sched_port_queues_per_subport(port)); uint32_t tc_index = rte_sched_port_pipe_tc(port, qindex); uint32_t pkt_len = pkt->pkt_len; - s->stats.n_pkts_tc[tc_index] += 1; - s->stats.n_bytes_tc[tc_index] += pkt_len; + subport->stats.n_pkts_tc[tc_index] += 1; + subport->stats.n_bytes_tc[tc_index] += pkt_len; } #ifdef RTE_SCHED_RED static inline void rte_sched_port_update_subport_stats_on_drop(struct rte_sched_port *port, - uint32_t qindex, - struct rte_mbuf *pkt, uint32_t red) + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt, + uint32_t red) #else static inline void rte_sched_port_update_subport_stats_on_drop(struct rte_sched_port *port, - uint32_t qindex, - struct rte_mbuf *pkt, __rte_unused uint32_t red) + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt, + __rte_unused uint32_t red) #endif { - struct rte_sched_subport *s = port->subport + (qindex / rte_sched_port_queues_per_subport(port)); uint32_t tc_index = rte_sched_port_pipe_tc(port, qindex); uint32_t pkt_len = pkt->pkt_len; - s->stats.n_pkts_tc_dropped[tc_index] += 1; - s->stats.n_bytes_tc_dropped[tc_index] += pkt_len; + subport->stats.n_pkts_tc_dropped[tc_index] += 1; + subport->stats.n_bytes_tc_dropped[tc_index] += pkt_len; #ifdef RTE_SCHED_RED - s->stats.n_pkts_red_dropped[tc_index] += red; + subport->stats.n_pkts_red_dropped[tc_index] += red; #endif } static inline void -rte_sched_port_update_queue_stats(struct rte_sched_port *port, uint32_t qindex, struct rte_mbuf *pkt) +rte_sched_port_update_queue_stats(struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt) { - struct rte_sched_queue_extra *qe = port->queue_extra + qindex; + struct rte_sched_queue_extra *qe = subport->queue_extra + qindex; uint32_t pkt_len = pkt->pkt_len; qe->stats.n_pkts += 1; @@ -1630,17 +1639,19 @@ rte_sched_port_update_queue_stats(struct rte_sched_port *port, uint32_t qindex, #ifdef RTE_SCHED_RED static inline void -rte_sched_port_update_queue_stats_on_drop(struct rte_sched_port *port, - uint32_t qindex, - struct rte_mbuf *pkt, uint32_t red) +rte_sched_port_update_queue_stats_on_drop(struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt, + uint32_t red) #else static inline void -rte_sched_port_update_queue_stats_on_drop(struct rte_sched_port *port, - uint32_t qindex, - struct rte_mbuf *pkt, __rte_unused uint32_t red) +rte_sched_port_update_queue_stats_on_drop(struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt, + __rte_unused uint32_t red) #endif { - struct rte_sched_queue_extra *qe = port->queue_extra + qindex; + struct rte_sched_queue_extra *qe = subport->queue_extra + qindex; uint32_t pkt_len = pkt->pkt_len; qe->stats.n_pkts_dropped += 1; @@ -1655,7 +1666,11 @@ rte_sched_port_update_queue_stats_on_drop(struct rte_sched_port *port, #ifdef RTE_SCHED_RED static inline int -rte_sched_port_red_drop(struct rte_sched_port *port, struct rte_mbuf *pkt, uint32_t qindex, uint16_t qlen) +rte_sched_port_red_drop(struct rte_sched_port *port, + struct rte_sched_subport *subport, + struct rte_mbuf *pkt, + uint32_t qindex, + uint16_t qlen) { struct rte_sched_queue_extra *qe; struct rte_red_config *red_cfg; @@ -1665,12 +1680,12 @@ rte_sched_port_red_drop(struct rte_sched_port *port, struct rte_mbuf *pkt, uint3 tc_index = rte_sched_port_pipe_tc(port, qindex); color = rte_sched_port_pkt_read_color(pkt); - red_cfg = &port->red_config[tc_index][color]; + red_cfg = &subport->red_config[tc_index][color]; if ((red_cfg->min_th | red_cfg->max_th) == 0) return 0; - qe = port->queue_extra + qindex; + qe = subport->queue_extra + qindex; red = &qe->red; return rte_red_enqueue(red_cfg, red, qlen, port->time); @@ -1687,7 +1702,14 @@ rte_sched_port_set_queue_empty_timestamp(struct rte_sched_port *port, uint32_t q #else -#define rte_sched_port_red_drop(port, pkt, qindex, qlen) 0 +static inline int rte_sched_port_red_drop(struct rte_sched_port *port __rte_unused, + struct rte_sched_subport *subport __rte_unused, + struct rte_mbuf *pkt __rte_unused, + uint32_t qindex __rte_unused, + uint16_t qlen __rte_unused) +{ + return 0; +} #define rte_sched_port_set_queue_empty_timestamp(port, qindex) @@ -1722,63 +1744,79 @@ debug_check_queue_slab(struct rte_sched_port *port, uint32_t bmp_pos, #endif /* RTE_SCHED_DEBUG */ +static inline struct rte_sched_subport * +rte_sched_port_subport(struct rte_sched_port *port, + struct rte_mbuf *pkt) +{ + uint32_t queue_id = rte_mbuf_sched_queue_get(pkt); + uint32_t subport_id = queue_id >> (port->n_pipes_per_subport_log2 + 4); + + return port->subports[subport_id]; +} + static inline uint32_t -rte_sched_port_enqueue_qptrs_prefetch0(struct rte_sched_port *port, - struct rte_mbuf *pkt) +rte_sched_port_enqueue_qptrs_prefetch0(struct rte_sched_subport *subport, + struct rte_mbuf *pkt, uint32_t subport_qmask) { struct rte_sched_queue *q; #ifdef RTE_SCHED_COLLECT_STATS struct rte_sched_queue_extra *qe; #endif uint32_t qindex = rte_mbuf_sched_queue_get(pkt); + uint32_t subport_queue_id = subport_qmask & qindex; - q = port->queue + qindex; + q = subport->queue + subport_queue_id; rte_prefetch0(q); #ifdef RTE_SCHED_COLLECT_STATS - qe = port->queue_extra + qindex; + qe = subport->queue_extra + subport_queue_id; rte_prefetch0(qe); #endif - return qindex; + return subport_queue_id; } static inline void rte_sched_port_enqueue_qwa_prefetch0(struct rte_sched_port *port, - uint32_t qindex, struct rte_mbuf **qbase) + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf **qbase) { struct rte_sched_queue *q; struct rte_mbuf **q_qw; uint16_t qsize; - q = port->queue + qindex; - qsize = rte_sched_port_qsize(port, qindex); + q = subport->queue + qindex; + qsize = rte_sched_subport_pipe_qsize(port, subport, qindex); q_qw = qbase + (q->qw & (qsize - 1)); rte_prefetch0(q_qw); - rte_bitmap_prefetch0(port->bmp, qindex); + rte_bitmap_prefetch0(subport->bmp, qindex); } static inline int -rte_sched_port_enqueue_qwa(struct rte_sched_port *port, uint32_t qindex, - struct rte_mbuf **qbase, struct rte_mbuf *pkt) +rte_sched_port_enqueue_qwa(struct rte_sched_port *port, + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf **qbase, + struct rte_mbuf *pkt) { struct rte_sched_queue *q; uint16_t qsize; uint16_t qlen; - q = port->queue + qindex; - qsize = rte_sched_port_qsize(port, qindex); + q = subport->queue + qindex; + qsize = rte_sched_subport_pipe_qsize(port, subport, qindex); qlen = q->qw - q->qr; /* Drop the packet (and update drop stats) when queue is full */ - if (unlikely(rte_sched_port_red_drop(port, pkt, qindex, qlen) || + if (unlikely(rte_sched_port_red_drop(port, subport, pkt, qindex, qlen) || (qlen >= qsize))) { rte_pktmbuf_free(pkt); #ifdef RTE_SCHED_COLLECT_STATS - rte_sched_port_update_subport_stats_on_drop(port, qindex, pkt, - qlen < qsize); - rte_sched_port_update_queue_stats_on_drop(port, qindex, pkt, - qlen < qsize); + rte_sched_port_update_subport_stats_on_drop(port, subport, + qindex, pkt, qlen < qsize); + rte_sched_port_update_queue_stats_on_drop(subport, qindex, pkt, + qlen < qsize); #endif return 0; } @@ -1787,13 +1825,13 @@ rte_sched_port_enqueue_qwa(struct rte_sched_port *port, uint32_t qindex, qbase[q->qw & (qsize - 1)] = pkt; q->qw++; - /* Activate queue in the port bitmap */ - rte_bitmap_set(port->bmp, qindex); + /* Activate queue in the subport bitmap */ + rte_bitmap_set(subport->bmp, qindex); /* Statistics */ #ifdef RTE_SCHED_COLLECT_STATS - rte_sched_port_update_subport_stats(port, qindex, pkt); - rte_sched_port_update_queue_stats(port, qindex, pkt); + rte_sched_port_update_subport_stats(port, subport, qindex, pkt); + rte_sched_port_update_queue_stats(subport, qindex, pkt); #endif return 1; @@ -1821,17 +1859,22 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, *pkt30, *pkt31, *pkt_last; struct rte_mbuf **q00_base, **q01_base, **q10_base, **q11_base, **q20_base, **q21_base, **q30_base, **q31_base, **q_last_base; + struct rte_sched_subport *subport00, *subport01, *subport10, *subport11, + *subport20, *subport21, *subport30, *subport31, *subport_last; uint32_t q00, q01, q10, q11, q20, q21, q30, q31, q_last; uint32_t r00, r01, r10, r11, r20, r21, r30, r31, r_last; + uint32_t subport_qmask; uint32_t result, i; result = 0; + subport_qmask = (1 << (port->n_pipes_per_subport_log2 + 4)) - 1; /* * Less then 6 input packets available, which is not enough to * feed the pipeline */ if (unlikely(n_pkts < 6)) { + struct rte_sched_subport *subports[5]; struct rte_mbuf **q_base[5]; uint32_t q[5]; @@ -1839,22 +1882,26 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, for (i = 0; i < n_pkts; i++) rte_prefetch0(pkts[i]); + /* Prefetch the subport structure for each packet */ + for (i = 0; i < n_pkts; i++) + subports[i] = rte_sched_port_subport(port, pkts[i]); + /* Prefetch the queue structure for each queue */ for (i = 0; i < n_pkts; i++) - q[i] = rte_sched_port_enqueue_qptrs_prefetch0(port, - pkts[i]); + q[i] = rte_sched_port_enqueue_qptrs_prefetch0(subports[i], + pkts[i], subport_qmask); /* Prefetch the write pointer location of each queue */ for (i = 0; i < n_pkts; i++) { - q_base[i] = rte_sched_port_qbase(port, q[i]); - rte_sched_port_enqueue_qwa_prefetch0(port, q[i], - q_base[i]); + q_base[i] = rte_sched_subport_pipe_qbase(subports[i], q[i]); + rte_sched_port_enqueue_qwa_prefetch0(port, subports[i], + q[i], q_base[i]); } /* Write each packet to its queue */ for (i = 0; i < n_pkts; i++) - result += rte_sched_port_enqueue_qwa(port, q[i], - q_base[i], pkts[i]); + result += rte_sched_port_enqueue_qwa(port, subports[i], + q[i], q_base[i], pkts[i]); return result; } @@ -1870,21 +1917,29 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, rte_prefetch0(pkt10); rte_prefetch0(pkt11); - q20 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt20); - q21 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt21); + subport20 = rte_sched_port_subport(port, pkt20); + subport21 = rte_sched_port_subport(port, pkt21); + q20 = rte_sched_port_enqueue_qptrs_prefetch0(subport20, + pkt20, subport_qmask); + q21 = rte_sched_port_enqueue_qptrs_prefetch0(subport21, + pkt21, subport_qmask); pkt00 = pkts[4]; pkt01 = pkts[5]; rte_prefetch0(pkt00); rte_prefetch0(pkt01); - q10 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt10); - q11 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt11); + subport10 = rte_sched_port_subport(port, pkt10); + subport11 = rte_sched_port_subport(port, pkt11); + q10 = rte_sched_port_enqueue_qptrs_prefetch0(subport10, + pkt10, subport_qmask); + q11 = rte_sched_port_enqueue_qptrs_prefetch0(subport11, + pkt11, subport_qmask); - q20_base = rte_sched_port_qbase(port, q20); - q21_base = rte_sched_port_qbase(port, q21); - rte_sched_port_enqueue_qwa_prefetch0(port, q20, q20_base); - rte_sched_port_enqueue_qwa_prefetch0(port, q21, q21_base); + q20_base = rte_sched_subport_pipe_qbase(subport20, q20); + q21_base = rte_sched_subport_pipe_qbase(subport21, q21); + rte_sched_port_enqueue_qwa_prefetch0(port, subport20, q20, q20_base); + rte_sched_port_enqueue_qwa_prefetch0(port, subport21, q21, q21_base); /* Run the pipeline */ for (i = 6; i < (n_pkts & (~1)); i += 2) { @@ -1899,6 +1954,10 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, q31 = q21; q20 = q10; q21 = q11; + subport30 = subport20; + subport31 = subport21; + subport20 = subport10; + subport21 = subport11; q30_base = q20_base; q31_base = q21_base; @@ -1908,19 +1967,25 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, rte_prefetch0(pkt00); rte_prefetch0(pkt01); - /* Stage 1: Prefetch queue structure storing queue pointers */ - q10 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt10); - q11 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt11); + /* Stage 1: Prefetch subport and queue structure storing queue pointers */ + subport10 = rte_sched_port_subport(port, pkt10); + subport11 = rte_sched_port_subport(port, pkt11); + q10 = rte_sched_port_enqueue_qptrs_prefetch0(subport10, + pkt10, subport_qmask); + q11 = rte_sched_port_enqueue_qptrs_prefetch0(subport11, + pkt11, subport_qmask); /* Stage 2: Prefetch queue write location */ - q20_base = rte_sched_port_qbase(port, q20); - q21_base = rte_sched_port_qbase(port, q21); - rte_sched_port_enqueue_qwa_prefetch0(port, q20, q20_base); - rte_sched_port_enqueue_qwa_prefetch0(port, q21, q21_base); + q20_base = rte_sched_subport_pipe_qbase(subport20, q20); + q21_base = rte_sched_subport_pipe_qbase(subport21, q21); + rte_sched_port_enqueue_qwa_prefetch0(port, subport20, q20, q20_base); + rte_sched_port_enqueue_qwa_prefetch0(port, subport21, q21, q21_base); /* Stage 3: Write packet to queue and activate queue */ - r30 = rte_sched_port_enqueue_qwa(port, q30, q30_base, pkt30); - r31 = rte_sched_port_enqueue_qwa(port, q31, q31_base, pkt31); + r30 = rte_sched_port_enqueue_qwa(port, subport30, + q30, q30_base, pkt30); + r31 = rte_sched_port_enqueue_qwa(port, subport31, + q31, q31_base, pkt31); result += r30 + r31; } @@ -1932,38 +1997,52 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, pkt_last = pkts[n_pkts - 1]; rte_prefetch0(pkt_last); - q00 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt00); - q01 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt01); - - q10_base = rte_sched_port_qbase(port, q10); - q11_base = rte_sched_port_qbase(port, q11); - rte_sched_port_enqueue_qwa_prefetch0(port, q10, q10_base); - rte_sched_port_enqueue_qwa_prefetch0(port, q11, q11_base); - - r20 = rte_sched_port_enqueue_qwa(port, q20, q20_base, pkt20); - r21 = rte_sched_port_enqueue_qwa(port, q21, q21_base, pkt21); + subport00 = rte_sched_port_subport(port, pkt00); + subport01 = rte_sched_port_subport(port, pkt01); + q00 = rte_sched_port_enqueue_qptrs_prefetch0(subport00, + pkt00, subport_qmask); + q01 = rte_sched_port_enqueue_qptrs_prefetch0(subport01, + pkt01, subport_qmask); + + q10_base = rte_sched_subport_pipe_qbase(subport10, q10); + q11_base = rte_sched_subport_pipe_qbase(subport11, q11); + rte_sched_port_enqueue_qwa_prefetch0(port, subport10, q10, q10_base); + rte_sched_port_enqueue_qwa_prefetch0(port, subport11, q11, q11_base); + + r20 = rte_sched_port_enqueue_qwa(port, subport20, + q20, q20_base, pkt20); + r21 = rte_sched_port_enqueue_qwa(port, subport21, + q21, q21_base, pkt21); result += r20 + r21; - q_last = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt_last); + subport_last = rte_sched_port_subport(port, pkt_last); + q_last = rte_sched_port_enqueue_qptrs_prefetch0(subport_last, + pkt_last, subport_qmask); - q00_base = rte_sched_port_qbase(port, q00); - q01_base = rte_sched_port_qbase(port, q01); - rte_sched_port_enqueue_qwa_prefetch0(port, q00, q00_base); - rte_sched_port_enqueue_qwa_prefetch0(port, q01, q01_base); + q00_base = rte_sched_subport_pipe_qbase(subport00, q00); + q01_base = rte_sched_subport_pipe_qbase(subport01, q01); + rte_sched_port_enqueue_qwa_prefetch0(port, subport00, q00, q00_base); + rte_sched_port_enqueue_qwa_prefetch0(port, subport01, q01, q01_base); - r10 = rte_sched_port_enqueue_qwa(port, q10, q10_base, pkt10); - r11 = rte_sched_port_enqueue_qwa(port, q11, q11_base, pkt11); + r10 = rte_sched_port_enqueue_qwa(port, subport10, q10, + q10_base, pkt10); + r11 = rte_sched_port_enqueue_qwa(port, subport11, q11, + q11_base, pkt11); result += r10 + r11; - q_last_base = rte_sched_port_qbase(port, q_last); - rte_sched_port_enqueue_qwa_prefetch0(port, q_last, q_last_base); + q_last_base = rte_sched_subport_pipe_qbase(subport_last, q_last); + rte_sched_port_enqueue_qwa_prefetch0(port, subport_last, + q_last, q_last_base); - r00 = rte_sched_port_enqueue_qwa(port, q00, q00_base, pkt00); - r01 = rte_sched_port_enqueue_qwa(port, q01, q01_base, pkt01); + r00 = rte_sched_port_enqueue_qwa(port, subport00, q00, + q00_base, pkt00); + r01 = rte_sched_port_enqueue_qwa(port, subport01, q01, + q01_base, pkt01); result += r00 + r01; if (n_pkts & 1) { - r_last = rte_sched_port_enqueue_qwa(port, q_last, q_last_base, pkt_last); + r_last = rte_sched_port_enqueue_qwa(port, subport_last, + q_last, q_last_base, pkt_last); result += r_last; } -- 2.21.0
Update memory footprint compute function for allowing subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 110 +++++++++-------------------------- lib/librte_sched/rte_sched.h | 8 ++- 2 files changed, 34 insertions(+), 84 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index a8174afad..fdcbb214e 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -281,16 +281,6 @@ enum rte_sched_subport_array { e_RTE_SCHED_SUBPORT_ARRAY_TOTAL, }; -#ifdef RTE_SCHED_COLLECT_STATS - -static inline uint32_t -rte_sched_port_queues_per_subport(struct rte_sched_port *port) -{ - return RTE_SCHED_QUEUES_PER_PIPE * port->n_pipes_per_subport; -} - -#endif - static inline uint32_t rte_sched_subport_pipe_queues(struct rte_sched_subport *subport) { @@ -486,70 +476,6 @@ rte_sched_port_check_params(struct rte_sched_port_params *params) return 0; } -static uint32_t -rte_sched_port_get_array_base(struct rte_sched_port_params *params, enum rte_sched_port_array array) -{ - uint32_t n_subports_per_port = params->n_subports_per_port; - uint32_t n_pipes_per_subport = params->n_pipes_per_subport; - uint32_t n_pipes_per_port = n_pipes_per_subport * n_subports_per_port; - uint32_t n_queues_per_port = RTE_SCHED_QUEUES_PER_PIPE * n_pipes_per_subport * n_subports_per_port; - - uint32_t size_subport = n_subports_per_port * sizeof(struct rte_sched_subport); - uint32_t size_pipe = n_pipes_per_port * sizeof(struct rte_sched_pipe); - uint32_t size_queue = n_queues_per_port * sizeof(struct rte_sched_queue); - uint32_t size_queue_extra - = n_queues_per_port * sizeof(struct rte_sched_queue_extra); - uint32_t size_pipe_profiles - = params->n_max_pipe_profiles * sizeof(struct rte_sched_pipe_profile); - uint32_t size_bmp_array = rte_bitmap_get_memory_footprint(n_queues_per_port); - uint32_t size_per_pipe_queue_array, size_queue_array; - - uint32_t base, i; - - size_per_pipe_queue_array = 0; - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - if (i < RTE_SCHED_TRAFFIC_CLASS_BE) - size_per_pipe_queue_array += - params->qsize[i] * sizeof(struct rte_mbuf *); - else - size_per_pipe_queue_array += RTE_SCHED_MAX_QUEUES_PER_TC * - params->qsize[i] * sizeof(struct rte_mbuf *); - } - size_queue_array = n_pipes_per_port * size_per_pipe_queue_array; - - base = 0; - - if (array == e_RTE_SCHED_PORT_ARRAY_SUBPORT) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_subport); - - if (array == e_RTE_SCHED_PORT_ARRAY_PIPE) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_pipe); - - if (array == e_RTE_SCHED_PORT_ARRAY_QUEUE) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_queue); - - if (array == e_RTE_SCHED_PORT_ARRAY_QUEUE_EXTRA) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_queue_extra); - - if (array == e_RTE_SCHED_PORT_ARRAY_PIPE_PROFILES) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_pipe_profiles); - - if (array == e_RTE_SCHED_PORT_ARRAY_BMP_ARRAY) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_bmp_array); - - if (array == e_RTE_SCHED_PORT_ARRAY_QUEUE_ARRAY) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_queue_array); - - return base; -} - static uint32_t rte_sched_subport_get_array_base(struct rte_sched_subport_params *params, enum rte_sched_subport_array array) @@ -870,22 +796,44 @@ rte_sched_subport_check_params(struct rte_sched_subport_params *params, } uint32_t -rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params) +rte_sched_port_get_memory_footprint(struct rte_sched_port_params *port_params, + struct rte_sched_subport_params **subport_params) { - uint32_t size0, size1; + uint32_t size0 = 0, size1 = 0, i; int status; - status = rte_sched_port_check_params(params); + status = rte_sched_port_check_params(port_params); if (status != 0) { - RTE_LOG(NOTICE, SCHED, - "Port scheduler params check failed (%d)\n", status); + RTE_LOG(ERR, SCHED, + "%s: Port scheduler port params check failed (%d)\n", + __func__, status); return 0; } + for (i = 0; i < port_params->n_subports_per_port; i++) { + struct rte_sched_subport_params *sp = subport_params[i]; + + status = rte_sched_subport_check_params(sp, + port_params->n_pipes_per_subport, + port_params->rate); + if (status != 0) { + RTE_LOG(ERR, SCHED, + "%s: Port scheduler subport params check failed (%d)\n", + __func__, status); + + return 0; + } + } + size0 = sizeof(struct rte_sched_port); - size1 = rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_TOTAL); + + for (i = 0; i < port_params->n_subports_per_port; i++) { + struct rte_sched_subport_params *sp = subport_params[i]; + + size1 += rte_sched_subport_get_array_base(sp, + e_RTE_SCHED_SUBPORT_ARRAY_TOTAL); + } return size0 + size1; } diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index 5001f09ed..40f02f124 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -373,14 +373,16 @@ rte_sched_pipe_config(struct rte_sched_port *port, /** * Hierarchical scheduler memory footprint size per port * - * @param params + * @param port_params * Port scheduler configuration parameter structure + * @param subport_params + * Array of subport parameter structures * @return * Memory footprint size in bytes upon success, 0 otherwise */ uint32_t -rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params); - +rte_sched_port_get_memory_footprint(struct rte_sched_port_params *port_params, + struct rte_sched_subport_params **subport_params); /* * Statistics * -- 2.21.0
Modify packet grinder functions of the schedule to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 223 +++++++++++++++++------------------ 1 file changed, 106 insertions(+), 117 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index fdcbb214e..6eba69d99 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -312,24 +312,6 @@ rte_sched_port_queues_per_port(struct rte_sched_port *port) return RTE_SCHED_QUEUES_PER_PIPE * port->n_pipes_per_subport * port->n_subports_per_port; } -static inline struct rte_mbuf ** -rte_sched_port_qbase(struct rte_sched_port *port, uint32_t qindex) -{ - uint32_t pindex = qindex >> 4; - uint32_t qpos = qindex & 0xF; - - return (port->queue_array + pindex * - port->qsize_sum + port->qsize_add[qpos]); -} - -static inline uint16_t -rte_sched_port_qsize(struct rte_sched_port *port, uint32_t qindex) -{ - uint32_t tc = port->pipe_tc[qindex & (RTE_SCHED_QUEUES_PER_PIPE - 1)]; - - return port->qsize[tc]; -} - static inline uint16_t rte_sched_port_pipe_queue(struct rte_sched_port *port, uint32_t traffic_class) { @@ -1523,9 +1505,10 @@ rte_sched_queue_read_stats(struct rte_sched_port *port, #ifdef RTE_SCHED_DEBUG static inline int -rte_sched_port_queue_is_empty(struct rte_sched_port *port, uint32_t qindex) +rte_sched_port_queue_is_empty(struct rte_sched_subport *subport, + uint32_t qindex) { - struct rte_sched_queue *queue = port->queue + qindex; + struct rte_sched_queue *queue = subport->queue + qindex; return queue->qr == queue->qw; } @@ -1640,9 +1623,10 @@ rte_sched_port_red_drop(struct rte_sched_port *port, } static inline void -rte_sched_port_set_queue_empty_timestamp(struct rte_sched_port *port, uint32_t qindex) +rte_sched_port_set_queue_empty_timestamp(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t qindex) { - struct rte_sched_queue_extra *qe = port->queue_extra + qindex; + struct rte_sched_queue_extra *qe = subport->queue_extra + qindex; struct rte_red *red = &qe->red; rte_red_mark_queue_empty(red, port->time); @@ -1659,14 +1643,14 @@ static inline int rte_sched_port_red_drop(struct rte_sched_port *port __rte_unus return 0; } -#define rte_sched_port_set_queue_empty_timestamp(port, qindex) +#define rte_sched_port_set_queue_empty_timestamp(port, subport, qindex) #endif /* RTE_SCHED_RED */ #ifdef RTE_SCHED_DEBUG static inline void -debug_check_queue_slab(struct rte_sched_port *port, uint32_t bmp_pos, +debug_check_queue_slab(struct rte_sched_subport *subport, uint32_t bmp_pos, uint64_t bmp_slab) { uint64_t mask; @@ -1678,7 +1662,7 @@ debug_check_queue_slab(struct rte_sched_port *port, uint32_t bmp_pos, panic = 0; for (i = 0, mask = 1; i < 64; i++, mask <<= 1) { if (mask & bmp_slab) { - if (rte_sched_port_queue_is_empty(port, bmp_pos + i)) { + if (rte_sched_port_queue_is_empty(subport, bmp_pos + i)) { printf("Queue %u (slab offset %u) is empty\n", bmp_pos + i, i); panic = 1; } @@ -2000,10 +1984,10 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, #ifndef RTE_SCHED_SUBPORT_TC_OV static inline void -grinder_credits_update(struct rte_sched_port *port, uint32_t pos) +grinder_credits_update(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; struct rte_sched_pipe_profile *params = grinder->pipe_params; uint64_t n_periods; @@ -2041,10 +2025,9 @@ grinder_credits_update(struct rte_sched_port *port, uint32_t pos) #else static inline uint32_t -grinder_tc_ov_credits_update(struct rte_sched_port *port, uint32_t pos) +grinder_tc_ov_credits_update(struct rte_sched_port *port, + struct rte_sched_subport *subport) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; uint32_t tc_ov_consumption[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; uint32_t tc_consumption = 0, tc_ov_consumption_max; uint32_t tc_ov_wm = subport->tc_ov_wm; @@ -2084,10 +2067,10 @@ grinder_tc_ov_credits_update(struct rte_sched_port *port, uint32_t pos) } static inline void -grinder_credits_update(struct rte_sched_port *port, uint32_t pos) +grinder_credits_update(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; struct rte_sched_pipe_profile *params = grinder->pipe_params; uint64_t n_periods; @@ -2107,7 +2090,7 @@ grinder_credits_update(struct rte_sched_port *port, uint32_t pos) /* Subport TCs */ if (unlikely(port->time >= subport->tc_time)) { - subport->tc_ov_wm = grinder_tc_ov_credits_update(port, pos); + subport->tc_ov_wm = grinder_tc_ov_credits_update(port, subport); for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) subport->tc_credits[i] = subport->tc_credits_per_period[i]; @@ -2137,10 +2120,10 @@ grinder_credits_update(struct rte_sched_port *port, uint32_t pos) #ifndef RTE_SCHED_SUBPORT_TC_OV static inline int -grinder_credits_check(struct rte_sched_port *port, uint32_t pos) +grinder_credits_check(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; + 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; @@ -2172,10 +2155,10 @@ grinder_credits_check(struct rte_sched_port *port, uint32_t pos) #else static inline int -grinder_credits_check(struct rte_sched_port *port, uint32_t pos) +grinder_credits_check(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; + 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; @@ -2220,15 +2203,16 @@ grinder_credits_check(struct rte_sched_port *port, uint32_t pos) static inline int -grinder_schedule(struct rte_sched_port *port, uint32_t pos) +grinder_schedule(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_queue *queue = grinder->queue[grinder->qpos]; struct rte_mbuf *pkt = grinder->pkt; uint32_t pkt_len = pkt->pkt_len + port->frame_overhead; uint32_t be_tc_active; - if (!grinder_credits_check(port, pos)) + if (!grinder_credits_check(port, subport, pos)) return 0; /* Advance port time */ @@ -2245,15 +2229,15 @@ grinder_schedule(struct rte_sched_port *port, uint32_t pos) if (queue->qr == queue->qw) { uint32_t qindex = grinder->qindex[grinder->qpos]; - rte_bitmap_clear(port->bmp, qindex); + rte_bitmap_clear(subport->bmp, qindex); grinder->qmask &= ~(1 << grinder->qpos); if (be_tc_active) grinder->wrr_mask[grinder->qpos] = 0; - rte_sched_port_set_queue_empty_timestamp(port, qindex); + rte_sched_port_set_queue_empty_timestamp(port, subport, qindex); } /* Reset pipe loop detection */ - port->pipe_loop = RTE_SCHED_PIPE_INVALID; + subport->pipe_loop = RTE_SCHED_PIPE_INVALID; grinder->productive = 1; return 1; @@ -2262,13 +2246,13 @@ grinder_schedule(struct rte_sched_port *port, uint32_t pos) #ifdef SCHED_VECTOR_SSE4 static inline int -grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) +grinder_pipe_exists(struct rte_sched_subport *subport, uint32_t base_pipe) { __m128i index = _mm_set1_epi32(base_pipe); - __m128i pipes = _mm_load_si128((__m128i *)port->grinder_base_bmp_pos); + __m128i pipes = _mm_load_si128((__m128i *)subport->grinder_base_bmp_pos); __m128i res = _mm_cmpeq_epi32(pipes, index); - pipes = _mm_load_si128((__m128i *)(port->grinder_base_bmp_pos + 4)); + pipes = _mm_load_si128((__m128i *)(subport->grinder_base_bmp_pos + 4)); pipes = _mm_cmpeq_epi32(pipes, index); res = _mm_or_si128(res, pipes); @@ -2281,10 +2265,10 @@ grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) #elif defined(SCHED_VECTOR_NEON) static inline int -grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) +grinder_pipe_exists(struct rte_sched_subport *subport, uint32_t base_pipe) { uint32x4_t index, pipes; - uint32_t *pos = (uint32_t *)port->grinder_base_bmp_pos; + uint32_t *pos = (uint32_t *)subport->grinder_base_bmp_pos; index = vmovq_n_u32(base_pipe); pipes = vld1q_u32(pos); @@ -2301,12 +2285,12 @@ grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) #else static inline int -grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) +grinder_pipe_exists(struct rte_sched_subport *subport, uint32_t base_pipe) { uint32_t i; for (i = 0; i < RTE_SCHED_PORT_N_GRINDERS; i++) { - if (port->grinder_base_bmp_pos[i] == base_pipe) + if (subport->grinder_base_bmp_pos[i] == base_pipe) return 1; } @@ -2316,9 +2300,10 @@ grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) #endif /* RTE_SCHED_OPTIMIZATIONS */ static inline void -grinder_pcache_populate(struct rte_sched_port *port, uint32_t pos, uint32_t bmp_pos, uint64_t bmp_slab) +grinder_pcache_populate(struct rte_sched_subport *subport, + uint32_t pos, uint32_t bmp_pos, uint64_t bmp_slab) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint16_t w[4]; grinder->pcache_w = 0; @@ -2347,9 +2332,10 @@ grinder_pcache_populate(struct rte_sched_port *port, uint32_t pos, uint32_t bmp_ } static inline void -grinder_tccache_populate(struct rte_sched_port *port, uint32_t pos, uint32_t qindex, uint16_t qmask) +grinder_tccache_populate(struct rte_sched_subport *subport, + uint32_t pos, uint32_t qindex, uint16_t qmask) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint8_t b, i; grinder->tccache_w = 0; @@ -2370,9 +2356,10 @@ grinder_tccache_populate(struct rte_sched_port *port, uint32_t pos, uint32_t qin } static inline int -grinder_next_tc(struct rte_sched_port *port, uint32_t pos) +grinder_next_tc(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_mbuf **qbase; uint32_t qindex; uint16_t qsize; @@ -2381,15 +2368,15 @@ grinder_next_tc(struct rte_sched_port *port, uint32_t pos) return 0; qindex = grinder->tccache_qindex[grinder->tccache_r]; - qbase = rte_sched_port_qbase(port, qindex); - qsize = rte_sched_port_qsize(port, qindex); + qbase = rte_sched_subport_pipe_qbase(subport, qindex); + qsize = rte_sched_subport_pipe_qsize(port, subport, qindex); grinder->tc_index = rte_sched_port_pipe_tc(port, qindex); grinder->qmask = grinder->tccache_qmask[grinder->tccache_r]; grinder->qsize = qsize; if (grinder->tc_index < RTE_SCHED_TRAFFIC_CLASS_BE) { - grinder->queue[0] = port->queue + qindex; + grinder->queue[0] = subport->queue + qindex; grinder->qbase[0] = qbase; grinder->qindex[0] = qindex; grinder->tccache_r++; @@ -2397,10 +2384,10 @@ grinder_next_tc(struct rte_sched_port *port, uint32_t pos) return 1; } - grinder->queue[0] = port->queue + qindex; - grinder->queue[1] = port->queue + qindex + 1; - grinder->queue[2] = port->queue + qindex + 2; - grinder->queue[3] = port->queue + qindex + 3; + grinder->queue[0] = subport->queue + qindex; + grinder->queue[1] = subport->queue + qindex + 1; + grinder->queue[2] = subport->queue + qindex + 2; + grinder->queue[3] = subport->queue + qindex + 3; grinder->qbase[0] = qbase; grinder->qbase[1] = qbase + qsize; @@ -2417,9 +2404,10 @@ grinder_next_tc(struct rte_sched_port *port, uint32_t pos) } static inline int -grinder_next_pipe(struct rte_sched_port *port, uint32_t pos) +grinder_next_pipe(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint32_t pipe_qindex; uint16_t pipe_qmask; @@ -2432,22 +2420,22 @@ grinder_next_pipe(struct rte_sched_port *port, uint32_t pos) uint32_t bmp_pos = 0; /* Get another non-empty pipe group */ - if (unlikely(rte_bitmap_scan(port->bmp, &bmp_pos, &bmp_slab) <= 0)) + if (unlikely(rte_bitmap_scan(subport->bmp, &bmp_pos, &bmp_slab) <= 0)) return 0; #ifdef RTE_SCHED_DEBUG - debug_check_queue_slab(port, bmp_pos, bmp_slab); + debug_check_queue_slab(subport, bmp_pos, bmp_slab); #endif /* Return if pipe group already in one of the other grinders */ - port->grinder_base_bmp_pos[pos] = RTE_SCHED_BMP_POS_INVALID; - if (unlikely(grinder_pipe_exists(port, bmp_pos))) + subport->grinder_base_bmp_pos[pos] = RTE_SCHED_BMP_POS_INVALID; + if (unlikely(grinder_pipe_exists(subport, bmp_pos))) return 0; - port->grinder_base_bmp_pos[pos] = bmp_pos; + subport->grinder_base_bmp_pos[pos] = bmp_pos; /* Install new pipe group into grinder's pipe cache */ - grinder_pcache_populate(port, pos, bmp_pos, bmp_slab); + grinder_pcache_populate(subport, pos, bmp_pos, bmp_slab); pipe_qmask = grinder->pcache_qmask[0]; pipe_qindex = grinder->pcache_qindex[0]; @@ -2456,18 +2444,18 @@ grinder_next_pipe(struct rte_sched_port *port, uint32_t pos) /* Install new pipe in the grinder */ grinder->pindex = pipe_qindex >> 4; - grinder->subport = port->subport + (grinder->pindex / port->n_pipes_per_subport); - grinder->pipe = port->pipe + grinder->pindex; + grinder->subport = subport; + grinder->pipe = subport->pipe + grinder->pindex; grinder->pipe_params = NULL; /* to be set after the pipe structure is prefetched */ grinder->productive = 0; - grinder_tccache_populate(port, pos, pipe_qindex, pipe_qmask); - grinder_next_tc(port, pos); + grinder_tccache_populate(subport, pos, pipe_qindex, pipe_qmask); + grinder_next_tc(port, subport, pos); /* Check for pipe exhaustion */ - if (grinder->pindex == port->pipe_loop) { - port->pipe_exhaustion = 1; - port->pipe_loop = RTE_SCHED_PIPE_INVALID; + if (grinder->pindex == subport->pipe_loop) { + subport->pipe_exhaustion = 1; + subport->pipe_loop = RTE_SCHED_PIPE_INVALID; } return 1; @@ -2475,9 +2463,9 @@ grinder_next_pipe(struct rte_sched_port *port, uint32_t pos) static inline void -grinder_wrr_load(struct rte_sched_port *port, uint32_t pos) +grinder_wrr_load(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; struct rte_sched_pipe_profile *pipe_params = grinder->pipe_params; uint32_t qmask = grinder->qmask; @@ -2503,9 +2491,9 @@ grinder_wrr_load(struct rte_sched_port *port, uint32_t pos) } static inline void -grinder_wrr_store(struct rte_sched_port *port, uint32_t pos) +grinder_wrr_store(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; pipe->wrr_tokens[0] = @@ -2523,9 +2511,9 @@ grinder_wrr_store(struct rte_sched_port *port, uint32_t pos) } static inline void -grinder_wrr(struct rte_sched_port *port, uint32_t pos) +grinder_wrr(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint16_t wrr_tokens_min; grinder->wrr_tokens[0] |= ~grinder->wrr_mask[0]; @@ -2543,21 +2531,21 @@ grinder_wrr(struct rte_sched_port *port, uint32_t pos) } -#define grinder_evict(port, pos) +#define grinder_evict(subport, pos) static inline void -grinder_prefetch_pipe(struct rte_sched_port *port, uint32_t pos) +grinder_prefetch_pipe(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; rte_prefetch0(grinder->pipe); rte_prefetch0(grinder->queue[0]); } static inline void -grinder_prefetch_tc_queue_arrays(struct rte_sched_port *port, uint32_t pos) +grinder_prefetch_tc_queue_arrays(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint16_t qsize, qr[RTE_SCHED_MAX_QUEUES_PER_TC]; qsize = grinder->qsize; @@ -2578,17 +2566,17 @@ grinder_prefetch_tc_queue_arrays(struct rte_sched_port *port, uint32_t pos) rte_prefetch0(grinder->qbase[0] + qr[0]); rte_prefetch0(grinder->qbase[1] + qr[1]); - grinder_wrr_load(port, pos); - grinder_wrr(port, pos); + grinder_wrr_load(subport, pos); + grinder_wrr(subport, pos); rte_prefetch0(grinder->qbase[2] + qr[2]); rte_prefetch0(grinder->qbase[3] + qr[3]); } static inline void -grinder_prefetch_mbuf(struct rte_sched_port *port, uint32_t pos) +grinder_prefetch_mbuf(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint32_t qpos = grinder->qpos; struct rte_mbuf **qbase = grinder->qbase[qpos]; uint16_t qsize = grinder->qsize; @@ -2607,14 +2595,15 @@ grinder_prefetch_mbuf(struct rte_sched_port *port, uint32_t pos) static inline uint32_t grinder_handle(struct rte_sched_port *port, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_subport *subport = port->subport; + struct rte_sched_grinder *grinder = subport->grinder + pos; switch (grinder->state) { case e_GRINDER_PREFETCH_PIPE: { - if (grinder_next_pipe(port, pos)) { - grinder_prefetch_pipe(port, pos); - port->busy_grinders++; + if (grinder_next_pipe(port, subport, pos)) { + grinder_prefetch_pipe(subport, pos); + subport->busy_grinders++; grinder->state = e_GRINDER_PREFETCH_TC_QUEUE_ARRAYS; return 0; @@ -2627,9 +2616,9 @@ grinder_handle(struct rte_sched_port *port, uint32_t pos) { struct rte_sched_pipe *pipe = grinder->pipe; - grinder->pipe_params = port->pipe_profiles + pipe->profile; - grinder_prefetch_tc_queue_arrays(port, pos); - grinder_credits_update(port, pos); + grinder->pipe_params = subport->pipe_profiles + pipe->profile; + grinder_prefetch_tc_queue_arrays(subport, pos); + grinder_credits_update(port, subport, pos); grinder->state = e_GRINDER_PREFETCH_MBUF; return 0; @@ -2637,7 +2626,7 @@ grinder_handle(struct rte_sched_port *port, uint32_t pos) case e_GRINDER_PREFETCH_MBUF: { - grinder_prefetch_mbuf(port, pos); + grinder_prefetch_mbuf(subport, pos); grinder->state = e_GRINDER_READ_MBUF; return 0; @@ -2647,47 +2636,47 @@ grinder_handle(struct rte_sched_port *port, uint32_t pos) { uint32_t wrr_active, result = 0; - result = grinder_schedule(port, pos); + result = grinder_schedule(port, subport, pos); wrr_active = (grinder->tc_index == RTE_SCHED_TRAFFIC_CLASS_BE); /* Look for next packet within the same TC */ if (result && grinder->qmask) { if (wrr_active) - grinder_wrr(port, pos); + grinder_wrr(subport, pos); - grinder_prefetch_mbuf(port, pos); + grinder_prefetch_mbuf(subport, pos); return 1; } if (wrr_active) - grinder_wrr_store(port, pos); + grinder_wrr_store(subport, pos); /* Look for another active TC within same pipe */ - if (grinder_next_tc(port, pos)) { - grinder_prefetch_tc_queue_arrays(port, pos); + if (grinder_next_tc(port, subport, pos)) { + grinder_prefetch_tc_queue_arrays(subport, pos); grinder->state = e_GRINDER_PREFETCH_MBUF; return result; } if (grinder->productive == 0 && - port->pipe_loop == RTE_SCHED_PIPE_INVALID) - port->pipe_loop = grinder->pindex; + subport->pipe_loop == RTE_SCHED_PIPE_INVALID) + subport->pipe_loop = grinder->pindex; - grinder_evict(port, pos); + grinder_evict(subport, pos); /* Look for another active pipe */ - if (grinder_next_pipe(port, pos)) { - grinder_prefetch_pipe(port, pos); + if (grinder_next_pipe(port, subport, pos)) { + grinder_prefetch_pipe(subport, pos); grinder->state = e_GRINDER_PREFETCH_TC_QUEUE_ARRAYS; return result; } /* No active pipe found */ - port->busy_grinders--; + subport->busy_grinders--; grinder->state = e_GRINDER_PREFETCH_PIPE; return result; -- 2.21.0
Modify scheduler packet dequeue operation to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 51 ++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 6eba69d99..28df34447 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -243,6 +243,7 @@ struct rte_sched_port { uint32_t busy_grinders; struct rte_mbuf **pkts_out; uint32_t n_pkts_out; + uint32_t subport_id; /* Queue base calculation */ uint32_t qsize_add[RTE_SCHED_QUEUES_PER_PIPE]; @@ -888,6 +889,7 @@ rte_sched_port_config(struct rte_sched_port_params *params) /* Grinders */ port->pkts_out = NULL; port->n_pkts_out = 0; + port->subport_id = 0; return port; } @@ -2593,9 +2595,9 @@ grinder_prefetch_mbuf(struct rte_sched_subport *subport, uint32_t pos) } static inline uint32_t -grinder_handle(struct rte_sched_port *port, uint32_t pos) +grinder_handle(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_subport *subport = port->subport; struct rte_sched_grinder *grinder = subport->grinder + pos; switch (grinder->state) { @@ -2694,6 +2696,7 @@ rte_sched_port_time_resync(struct rte_sched_port *port) uint64_t cycles = rte_get_tsc_cycles(); uint64_t cycles_diff = cycles - port->time_cpu_cycles; uint64_t bytes_diff; + uint32_t i; /* Compute elapsed time in bytes */ bytes_diff = rte_reciprocal_divide(cycles_diff << RTE_SCHED_TIME_SHIFT, @@ -2706,20 +2709,21 @@ rte_sched_port_time_resync(struct rte_sched_port *port) port->time = port->time_cpu_bytes; /* Reset pipe loop detection */ - port->pipe_loop = RTE_SCHED_PIPE_INVALID; + for (i = 0; i < port->n_subports_per_port; i++) + port->subports[i]->pipe_loop = RTE_SCHED_PIPE_INVALID; } static inline int -rte_sched_port_exceptions(struct rte_sched_port *port, int second_pass) +rte_sched_port_exceptions(struct rte_sched_subport *subport, int second_pass) { int exceptions; /* Check if any exception flag is set */ - exceptions = (second_pass && port->busy_grinders == 0) || - (port->pipe_exhaustion == 1); + exceptions = (second_pass && subport->busy_grinders == 0) || + (subport->pipe_exhaustion == 1); /* Clear exception flags */ - port->pipe_exhaustion = 0; + subport->pipe_exhaustion = 0; return exceptions; } @@ -2727,7 +2731,9 @@ rte_sched_port_exceptions(struct rte_sched_port *port, int second_pass) int rte_sched_port_dequeue(struct rte_sched_port *port, struct rte_mbuf **pkts, uint32_t n_pkts) { - uint32_t i, count; + struct rte_sched_subport *subport; + uint32_t subport_id = port->subport_id; + uint32_t i, n_subports = 0, count; port->pkts_out = pkts; port->n_pkts_out = 0; @@ -2736,9 +2742,32 @@ rte_sched_port_dequeue(struct rte_sched_port *port, struct rte_mbuf **pkts, uint /* Take each queue in the grinder one step further */ for (i = 0, count = 0; ; i++) { - count += grinder_handle(port, i & (RTE_SCHED_PORT_N_GRINDERS - 1)); - if ((count == n_pkts) || - rte_sched_port_exceptions(port, i >= RTE_SCHED_PORT_N_GRINDERS)) { + subport = port->subports[subport_id]; + + count += grinder_handle(port, subport, + i & (RTE_SCHED_PORT_N_GRINDERS - 1)); + + if (count == n_pkts) { + subport_id++; + + if (subport_id == port->n_subports_per_port) + subport_id = 0; + + port->subport_id = subport_id; + break; + } + + if (rte_sched_port_exceptions(subport, i >= RTE_SCHED_PORT_N_GRINDERS)) { + i = 0; + subport_id++; + n_subports++; + } + + if (subport_id == port->n_subports_per_port) + subport_id = 0; + + if (n_subports == port->n_subports_per_port) { + port->subport_id = subport_id; break; } } -- 2.21.0
Modify pipe queue stats read function to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 28df34447..1faa580d0 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -310,7 +310,12 @@ struct rte_sched_subport *subport, uint32_t qindex) static inline uint32_t rte_sched_port_queues_per_port(struct rte_sched_port *port) { - return RTE_SCHED_QUEUES_PER_PIPE * port->n_pipes_per_subport * port->n_subports_per_port; + uint32_t n_queues = 0, i; + + for (i = 0; i < port->n_subports_per_port; i++) + n_queues += rte_sched_subport_pipe_queues(port->subports[i]); + + return n_queues; } static inline uint16_t @@ -1464,8 +1469,10 @@ rte_sched_queue_read_stats(struct rte_sched_port *port, struct rte_sched_queue_stats *stats, uint16_t *qlen) { + struct rte_sched_subport *s; struct rte_sched_queue *q; struct rte_sched_queue_extra *qe; + uint32_t subport_id, subport_qmask, subport_qindex; /* Check user parameters */ if (port == NULL) { @@ -1491,8 +1498,13 @@ rte_sched_queue_read_stats(struct rte_sched_port *port, "%s: Incorrect value for parameter qlen\n", __func__); return -EINVAL; } - q = port->queue + queue_id; - qe = port->queue_extra + queue_id; + subport_qmask = port->n_pipes_per_subport_log2 + 4; + subport_id = (queue_id >> subport_qmask) & (port->n_subports_per_port - 1); + + s = port->subports[subport_id]; + subport_qindex = ((1 << subport_qmask) - 1) & queue_id; + q = s->queue + subport_qindex; + qe = s->queue_extra + subport_qindex; /* Copy queue stats and clear */ memcpy(stats, &qe->stats, sizeof(struct rte_sched_queue_stats)); -- 2.21.0
Modify tests function to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- app/test/test_sched.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/app/test/test_sched.c b/app/test/test_sched.c index afe0b0765..fc31080ef 100644 --- a/app/test/test_sched.c +++ b/app/test/test_sched.c @@ -22,18 +22,6 @@ #define TC 2 #define QUEUE 0 -static struct rte_sched_subport_params subport_param[] = { - { - .tb_rate = 1250000000, - .tb_size = 1000000, - - .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000, - 1250000000, 1250000000, 1250000000, 1250000000, 1250000000, - 1250000000, 1250000000, 1250000000, 1250000000}, - .tc_period = 10, - }, -}; - static struct rte_sched_pipe_params pipe_profile[] = { { /* Profile #0 */ .tb_rate = 305175, @@ -48,6 +36,23 @@ static struct rte_sched_pipe_params pipe_profile[] = { }, }; +static struct rte_sched_subport_params subport_param[] = { + { + .tb_rate = 1250000000, + .tb_size = 1000000, + + .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000, + 1250000000, 1250000000, 1250000000, 1250000000, 1250000000, + 1250000000, 1250000000, 1250000000, 1250000000}, + .tc_period = 10, + .n_pipes_per_subport_enabled = 1024, + .qsize = {32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}, + .pipe_profiles = pipe_profile, + .n_pipe_profiles = 1, + .n_max_pipe_profiles = 1, + }, +}; + static struct rte_sched_port_params port_param = { .socket = 0, /* computed */ .rate = 0, /* computed */ @@ -55,10 +60,6 @@ static struct rte_sched_port_params port_param = { .frame_overhead = RTE_SCHED_FRAME_OVERHEAD_DEFAULT, .n_subports_per_port = 1, .n_pipes_per_subport = 1024, - .qsize = {32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}, - .pipe_profiles = pipe_profile, - .n_pipe_profiles = 1, - .n_max_pipe_profiles = 1, }; #define NB_MBUF 32 @@ -140,7 +141,7 @@ test_sched(void) err = rte_sched_subport_config(port, SUBPORT, subport_param); TEST_ASSERT_SUCCESS(err, "Error config sched, err=%d\n", err); - for (pipe = 0; pipe < port_param.n_pipes_per_subport; pipe ++) { + for (pipe = 0; pipe < subport_param[0].n_pipes_per_subport_enabled; pipe++) { err = rte_sched_pipe_config(port, SUBPORT, pipe, 0); TEST_ASSERT_SUCCESS(err, "Error config sched pipe %u, err=%d\n", pipe, err); } -- 2.21.0
Modify softnic traffic management function to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- drivers/net/softnic/rte_eth_softnic_tm.c | 54 ++++++++++++------------ 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/drivers/net/softnic/rte_eth_softnic_tm.c b/drivers/net/softnic/rte_eth_softnic_tm.c index 61c3adc82..80a470c9e 100644 --- a/drivers/net/softnic/rte_eth_softnic_tm.c +++ b/drivers/net/softnic/rte_eth_softnic_tm.c @@ -85,7 +85,8 @@ softnic_tmgr_port_create(struct pmd_internals *p, /* Subport */ n_subports = t->port_params.n_subports_per_port; for (subport_id = 0; subport_id < n_subports; subport_id++) { - uint32_t n_pipes_per_subport = t->port_params.n_pipes_per_subport; + uint32_t n_pipes_per_subport = + t->subport_params[subport_id].n_pipes_per_subport_enabled; uint32_t pipe_id; int status; @@ -2211,10 +2212,11 @@ tm_tc_wred_profile_get(struct rte_eth_dev *dev, uint32_t tc_id) #ifdef RTE_SCHED_RED static void -wred_profiles_set(struct rte_eth_dev *dev) +wred_profiles_set(struct rte_eth_dev *dev, uint32_t subport_id) { struct pmd_internals *p = dev->data->dev_private; - struct rte_sched_port_params *pp = &p->soft.tm.params.port_params; + struct rte_sched_subport_params *pp = + &p->soft.tm.params.subport_params[subport_id]; uint32_t tc_id; enum rte_color color; @@ -2234,7 +2236,7 @@ wred_profiles_set(struct rte_eth_dev *dev) #else -#define wred_profiles_set(dev) +#define wred_profiles_set(dev, subport_id) #endif @@ -2526,29 +2528,9 @@ hierarchy_blueprints_create(struct rte_eth_dev *dev) .frame_overhead = root->shaper_profile->params.pkt_length_adjust, .n_subports_per_port = root->n_children, - .n_pipes_per_subport = h->n_tm_nodes[TM_NODE_LEVEL_PIPE] / - h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT], - .qsize = {p->params.tm.qsize[0], - p->params.tm.qsize[1], - p->params.tm.qsize[2], - p->params.tm.qsize[3], - p->params.tm.qsize[4], - p->params.tm.qsize[5], - p->params.tm.qsize[6], - p->params.tm.qsize[7], - p->params.tm.qsize[8], - p->params.tm.qsize[9], - p->params.tm.qsize[10], - p->params.tm.qsize[11], - p->params.tm.qsize[12], - }, - .pipe_profiles = t->pipe_profiles, - .n_pipe_profiles = t->n_pipe_profiles, - .n_max_pipe_profiles = TM_MAX_PIPE_PROFILE, + .n_pipes_per_subport = TM_MAX_PIPES_PER_SUBPORT, }; - wred_profiles_set(dev); - subport_id = 0; TAILQ_FOREACH(n, nl, node) { uint64_t tc_rate[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; @@ -2588,8 +2570,28 @@ hierarchy_blueprints_create(struct rte_eth_dev *dev) tc_rate[12], }, .tc_period = SUBPORT_TC_PERIOD, + .n_pipes_per_subport_enabled = + h->n_tm_nodes[TM_NODE_LEVEL_PIPE] / + h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT], + .qsize = {p->params.tm.qsize[0], + p->params.tm.qsize[1], + p->params.tm.qsize[2], + p->params.tm.qsize[3], + p->params.tm.qsize[4], + p->params.tm.qsize[5], + p->params.tm.qsize[6], + p->params.tm.qsize[7], + p->params.tm.qsize[8], + p->params.tm.qsize[9], + p->params.tm.qsize[10], + p->params.tm.qsize[11], + p->params.tm.qsize[12], + }, + .pipe_profiles = t->pipe_profiles, + .n_pipe_profiles = t->n_pipe_profiles, + .n_max_pipe_profiles = TM_MAX_PIPE_PROFILE, }; - + wred_profiles_set(dev, subport_id); subport_id++; } } -- 2.21.0
Modify ip pipeline traffic management function to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- examples/ip_pipeline/cli.c | 71 ++++++++++++++++++------------------- examples/ip_pipeline/tmgr.c | 25 +++++++------ examples/ip_pipeline/tmgr.h | 7 ++-- 3 files changed, 51 insertions(+), 52 deletions(-) diff --git a/examples/ip_pipeline/cli.c b/examples/ip_pipeline/cli.c index 02dc11495..c72030682 100644 --- a/examples/ip_pipeline/cli.c +++ b/examples/ip_pipeline/cli.c @@ -393,7 +393,12 @@ static const char cmd_tmgr_subport_profile_help[] = " <tc0_rate> <tc1_rate> <tc2_rate> <tc3_rate> <tc4_rate>" " <tc5_rate> <tc6_rate> <tc7_rate> <tc8_rate>" " <tc9_rate> <tc10_rate> <tc11_rate> <tc12_rate>\n" -" <tc_period>\n"; +" <tc_period>\n" +" pps <n_pipes_per_subport>\n" +" qsize <qsize_tc0> <qsize_tc1> <qsize_tc2>" +" <qsize_tc3> <qsize_tc4> <qsize_tc5> <qsize_tc6>" +" <qsize_tc7> <qsize_tc8> <qsize_tc9> <qsize_tc10>" +" <qsize_tc11> <qsize_tc12>"; static void cmd_tmgr_subport_profile(char **tokens, @@ -404,7 +409,7 @@ cmd_tmgr_subport_profile(char **tokens, struct rte_sched_subport_params p; int status, i; - if (n_tokens != 19) { + if (n_tokens != 35) { snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); return; } @@ -430,6 +435,27 @@ cmd_tmgr_subport_profile(char **tokens, return; } + if (strcmp(tokens[19], "pps") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps"); + return; + } + + if (parser_read_uint32(&p.n_pipes_per_subport_enabled, tokens[20]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "n_pipes_per_subport"); + return; + } + + if (strcmp(tokens[21], "qsize") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "qsize"); + return; + } + + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) + if (parser_read_uint16(&p.qsize[i], tokens[22 + i]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "qsize"); + return; + } + status = tmgr_subport_profile_add(&p); if (status != 0) { snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); @@ -504,11 +530,6 @@ static const char cmd_tmgr_help[] = "tmgr <tmgr_name>\n" " rate <rate>\n" " spp <n_subports_per_port>\n" -" pps <n_pipes_per_subport>\n" -" qsize <qsize_tc0> <qsize_tc1> <qsize_tc2>" -" <qsize_tc3> <qsize_tc4> <qsize_tc5> <qsize_tc6>" -" <qsize_tc7> <qsize_tc8> <qsize_tc9> <qsize_tc10>" -" <qsize_tc11> <qsize_tc12>\n" " fo <frame_overhead>\n" " mtu <mtu>\n" " cpu <cpu_id>\n"; @@ -522,9 +543,8 @@ cmd_tmgr(char **tokens, struct tmgr_port_params p; char *name; struct tmgr_port *tmgr_port; - int i; - if (n_tokens != 28) { + if (n_tokens != 12) { snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); return; } @@ -551,53 +571,32 @@ cmd_tmgr(char **tokens, return; } - if (strcmp(tokens[6], "pps") != 0) { - snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps"); - return; - } - - if (parser_read_uint32(&p.n_pipes_per_subport, tokens[7]) != 0) { - snprintf(out, out_size, MSG_ARG_INVALID, "n_pipes_per_subport"); - return; - } - - if (strcmp(tokens[8], "qsize") != 0) { - snprintf(out, out_size, MSG_ARG_NOT_FOUND, "qsize"); - return; - } - - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - if (parser_read_uint16(&p.qsize[i], tokens[9 + i]) != 0) { - snprintf(out, out_size, MSG_ARG_INVALID, "qsize"); - return; - } - - if (strcmp(tokens[22], "fo") != 0) { + if (strcmp(tokens[6], "fo") != 0) { snprintf(out, out_size, MSG_ARG_NOT_FOUND, "fo"); return; } - if (parser_read_uint32(&p.frame_overhead, tokens[23]) != 0) { + if (parser_read_uint32(&p.frame_overhead, tokens[7]) != 0) { snprintf(out, out_size, MSG_ARG_INVALID, "frame_overhead"); return; } - if (strcmp(tokens[24], "mtu") != 0) { + if (strcmp(tokens[8], "mtu") != 0) { snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mtu"); return; } - if (parser_read_uint32(&p.mtu, tokens[25]) != 0) { + if (parser_read_uint32(&p.mtu, tokens[9]) != 0) { snprintf(out, out_size, MSG_ARG_INVALID, "mtu"); return; } - if (strcmp(tokens[26], "cpu") != 0) { + if (strcmp(tokens[10], "cpu") != 0) { snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu"); return; } - if (parser_read_uint32(&p.cpu_id, tokens[27]) != 0) { + if (parser_read_uint32(&p.cpu_id, tokens[11]) != 0) { snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id"); return; } diff --git a/examples/ip_pipeline/tmgr.c b/examples/ip_pipeline/tmgr.c index 40cbf1d0a..91ccbf60f 100644 --- a/examples/ip_pipeline/tmgr.c +++ b/examples/ip_pipeline/tmgr.c @@ -47,7 +47,8 @@ int tmgr_subport_profile_add(struct rte_sched_subport_params *p) { /* Check input params */ - if (p == NULL) + if (p == NULL || + p->n_pipes_per_subport_enabled == 0) return -1; /* Save profile */ @@ -90,7 +91,6 @@ tmgr_port_create(const char *name, struct tmgr_port_params *params) tmgr_port_find(name) || (params == NULL) || (params->n_subports_per_port == 0) || - (params->n_pipes_per_subport == 0) || (params->cpu_id >= RTE_MAX_NUMA_NODES) || (n_subport_profiles == 0) || (n_pipe_profiles == 0)) @@ -103,18 +103,16 @@ tmgr_port_create(const char *name, struct tmgr_port_params *params) p.mtu = params->mtu; p.frame_overhead = params->frame_overhead; p.n_subports_per_port = params->n_subports_per_port; - p.n_pipes_per_subport = params->n_pipes_per_subport; - - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - p.qsize[i] = params->qsize[i]; - - p.pipe_profiles = pipe_profile; - p.n_pipe_profiles = n_pipe_profiles; + p.n_pipes_per_subport = TMGR_PIPE_SUBPORT_MAX; s = rte_sched_port_config(&p); if (s == NULL) return NULL; + subport_profile[0].pipe_profiles = pipe_profile; + subport_profile[0].n_pipe_profiles = n_pipe_profiles; + subport_profile[0].n_max_pipe_profiles = TMGR_PIPE_PROFILE_MAX; + for (i = 0; i < params->n_subports_per_port; i++) { int status; @@ -128,7 +126,7 @@ tmgr_port_create(const char *name, struct tmgr_port_params *params) return NULL; } - for (j = 0; j < params->n_pipes_per_subport; j++) { + for (j = 0; j < subport_profile[0].n_pipes_per_subport_enabled; j++) { status = rte_sched_pipe_config( s, i, @@ -153,7 +151,6 @@ tmgr_port_create(const char *name, struct tmgr_port_params *params) strlcpy(tmgr_port->name, name, sizeof(tmgr_port->name)); tmgr_port->s = s; tmgr_port->n_subports_per_port = params->n_subports_per_port; - tmgr_port->n_pipes_per_subport = params->n_pipes_per_subport; /* Node add to list */ TAILQ_INSERT_TAIL(&tmgr_port_list, tmgr_port, node); @@ -205,8 +202,10 @@ tmgr_pipe_config(const char *port_name, port = tmgr_port_find(port_name); if ((port == NULL) || (subport_id >= port->n_subports_per_port) || - (pipe_id_first >= port->n_pipes_per_subport) || - (pipe_id_last >= port->n_pipes_per_subport) || + (pipe_id_first >= + subport_profile[subport_id].n_pipes_per_subport_enabled) || + (pipe_id_last >= + subport_profile[subport_id].n_pipes_per_subport_enabled) || (pipe_id_first > pipe_id_last) || (pipe_profile_id >= n_pipe_profiles)) return -1; diff --git a/examples/ip_pipeline/tmgr.h b/examples/ip_pipeline/tmgr.h index 8703a2e00..1fcf66ee1 100644 --- a/examples/ip_pipeline/tmgr.h +++ b/examples/ip_pipeline/tmgr.h @@ -12,6 +12,10 @@ #include "common.h" +#ifndef TMGR_PIPE_SUBPORT_MAX +#define TMGR_PIPE_SUBPORT_MAX 4096 +#endif + #ifndef TMGR_SUBPORT_PROFILE_MAX #define TMGR_SUBPORT_PROFILE_MAX 256 #endif @@ -25,7 +29,6 @@ struct tmgr_port { char name[NAME_SIZE]; struct rte_sched_port *s; uint32_t n_subports_per_port; - uint32_t n_pipes_per_subport; }; TAILQ_HEAD(tmgr_port_list, tmgr_port); @@ -42,8 +45,6 @@ struct tmgr_port_params { uint32_t frame_overhead; uint32_t mtu; uint32_t cpu_id; - uint32_t n_pipes_per_subport; - uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; }; int -- 2.21.0
Modify qos sample app to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- examples/qos_sched/app_thread.c | 20 ++- examples/qos_sched/cfg_file.c | 229 ++++++++++++++++-------------- examples/qos_sched/init.c | 54 +++---- examples/qos_sched/main.h | 1 + examples/qos_sched/profile.cfg | 5 +- examples/qos_sched/profile_ov.cfg | 5 +- examples/qos_sched/stats.c | 44 +++--- 7 files changed, 203 insertions(+), 155 deletions(-) diff --git a/examples/qos_sched/app_thread.c b/examples/qos_sched/app_thread.c index 18b734a14..dbc878b55 100644 --- a/examples/qos_sched/app_thread.c +++ b/examples/qos_sched/app_thread.c @@ -35,15 +35,25 @@ get_pkt_sched(struct rte_mbuf *m, uint32_t *subport, uint32_t *pipe, uint16_t *pdata = rte_pktmbuf_mtod(m, uint16_t *); uint16_t pipe_queue; + /* Outer VLAN ID*/ *subport = (rte_be_to_cpu_16(pdata[SUBPORT_OFFSET]) & 0x0FFF) & - (port_params.n_subports_per_port - 1); /* Outer VLAN ID*/ + (port_params.n_subports_per_port - 1); + + /* Inner VLAN ID */ *pipe = (rte_be_to_cpu_16(pdata[PIPE_OFFSET]) & 0x0FFF) & - (port_params.n_pipes_per_subport - 1); /* Inner VLAN ID */ + (subport_params[*subport].n_pipes_per_subport_enabled - 1); + pipe_queue = active_queues[(pdata[QUEUE_OFFSET] >> 8) % n_active_queues]; + + /* Traffic class (Destination IP) */ *traffic_class = pipe_queue > RTE_SCHED_TRAFFIC_CLASS_BE ? - RTE_SCHED_TRAFFIC_CLASS_BE : pipe_queue; /* Destination IP */ - *queue = pipe_queue - *traffic_class; /* Destination IP */ - *color = pdata[COLOR_OFFSET] & 0x03; /* Destination IP */ + RTE_SCHED_TRAFFIC_CLASS_BE : pipe_queue; + + /* Traffic class queue (Destination IP) */ + *queue = pipe_queue - *traffic_class; + + /* Color (Destination IP) */ + *color = pdata[COLOR_OFFSET] & 0x03; return 0; } diff --git a/examples/qos_sched/cfg_file.c b/examples/qos_sched/cfg_file.c index 45bf599e4..c6d3f5ab6 100644 --- a/examples/qos_sched/cfg_file.c +++ b/examples/qos_sched/cfg_file.c @@ -24,14 +24,10 @@ int cfg_load_port(struct rte_cfgfile *cfg, struct rte_sched_port_params *port_params) { const char *entry; - int j; if (!cfg || !port_params) return -1; - memset(active_queues, 0, sizeof(active_queues)); - n_active_queues = 0; - entry = rte_cfgfile_get_entry(cfg, "port", "frame overhead"); if (entry) port_params->frame_overhead = (uint32_t)atoi(entry); @@ -40,106 +36,6 @@ cfg_load_port(struct rte_cfgfile *cfg, struct rte_sched_port_params *port_params if (entry) port_params->n_subports_per_port = (uint32_t)atoi(entry); - entry = rte_cfgfile_get_entry(cfg, "port", "number of pipes per subport"); - if (entry) - port_params->n_pipes_per_subport = (uint32_t)atoi(entry); - - entry = rte_cfgfile_get_entry(cfg, "port", "queue sizes"); - if (entry) { - char *next; - - for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { - port_params->qsize[j] = (uint16_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - - for (j = 0; j < RTE_SCHED_TRAFFIC_CLASS_BE; j++) - if (port_params->qsize[j]) { - active_queues[n_active_queues] = j; - n_active_queues++; - } - - if (port_params->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]) - for (j = 0; j < RTE_SCHED_BE_QUEUES_PER_PIPE; j++) { - active_queues[n_active_queues] = - RTE_SCHED_TRAFFIC_CLASS_BE + j; - n_active_queues++; - } - } - -#ifdef RTE_SCHED_RED - for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { - char str[32]; - - /* Parse WRED min thresholds */ - snprintf(str, sizeof(str), "tc %d wred min", j); - entry = rte_cfgfile_get_entry(cfg, "red", str); - if (entry) { - char *next; - int k; - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < RTE_COLORS; k++) { - port_params->red_params[j][k].min_th - = (uint16_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - } - - /* Parse WRED max thresholds */ - snprintf(str, sizeof(str), "tc %d wred max", j); - entry = rte_cfgfile_get_entry(cfg, "red", str); - if (entry) { - char *next; - int k; - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < RTE_COLORS; k++) { - port_params->red_params[j][k].max_th - = (uint16_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - } - - /* Parse WRED inverse mark probabilities */ - snprintf(str, sizeof(str), "tc %d wred inv prob", j); - entry = rte_cfgfile_get_entry(cfg, "red", str); - if (entry) { - char *next; - int k; - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < RTE_COLORS; k++) { - port_params->red_params[j][k].maxp_inv - = (uint8_t)strtol(entry, &next, 10); - - if (next == NULL) - break; - entry = next; - } - } - - /* Parse WRED EWMA filter weights */ - snprintf(str, sizeof(str), "tc %d wred weight", j); - entry = rte_cfgfile_get_entry(cfg, "red", str); - if (entry) { - char *next; - int k; - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < RTE_COLORS; k++) { - port_params->red_params[j][k].wq_log2 - = (uint8_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - } - } -#endif /* RTE_SCHED_RED */ - return 0; } @@ -155,7 +51,7 @@ cfg_load_pipe(struct rte_cfgfile *cfg, struct rte_sched_pipe_params *pipe_params return -1; profiles = rte_cfgfile_num_sections(cfg, "pipe profile", sizeof("pipe profile") - 1); - port_params.n_pipe_profiles = profiles; + subport_params[0].n_pipe_profiles = profiles; for (j = 0; j < profiles; j++) { char pipe_name[32]; @@ -253,12 +149,121 @@ cfg_load_subport(struct rte_cfgfile *cfg, struct rte_sched_subport_params *subpo return -1; memset(app_pipe_to_profile, -1, sizeof(app_pipe_to_profile)); + memset(active_queues, 0, sizeof(active_queues)); + n_active_queues = 0; + +#ifdef RTE_SCHED_RED + char sec_name[CFG_NAME_LEN]; + struct rte_red_params red_params[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; + + snprintf(sec_name, sizeof(sec_name), "red"); + + if (rte_cfgfile_has_section(cfg, sec_name)) { + + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + char str[32]; + + /* Parse WRED min thresholds */ + snprintf(str, sizeof(str), "tc %d wred min", i); + entry = rte_cfgfile_get_entry(cfg, sec_name, str); + if (entry) { + char *next; + /* for each packet colour (green, yellow, red) */ + for (j = 0; j < RTE_COLORS; j++) { + red_params[i][j].min_th + = (uint16_t)strtol(entry, &next, 10); + if (next == NULL) + break; + entry = next; + } + } + + /* Parse WRED max thresholds */ + snprintf(str, sizeof(str), "tc %d wred max", i); + entry = rte_cfgfile_get_entry(cfg, "red", str); + if (entry) { + char *next; + /* for each packet colour (green, yellow, red) */ + for (j = 0; j < RTE_COLORS; j++) { + red_params[i][j].max_th + = (uint16_t)strtol(entry, &next, 10); + if (next == NULL) + break; + entry = next; + } + } + + /* Parse WRED inverse mark probabilities */ + snprintf(str, sizeof(str), "tc %d wred inv prob", i); + entry = rte_cfgfile_get_entry(cfg, "red", str); + if (entry) { + char *next; + /* for each packet colour (green, yellow, red) */ + for (j = 0; j < RTE_COLORS; j++) { + red_params[i][j].maxp_inv + = (uint8_t)strtol(entry, &next, 10); + + if (next == NULL) + break; + entry = next; + } + } + + /* Parse WRED EWMA filter weights */ + snprintf(str, sizeof(str), "tc %d wred weight", i); + entry = rte_cfgfile_get_entry(cfg, "red", str); + if (entry) { + char *next; + /* for each packet colour (green, yellow, red) */ + for (j = 0; j < RTE_COLORS; j++) { + red_params[i][j].wq_log2 + = (uint8_t)strtol(entry, &next, 10); + if (next == NULL) + break; + entry = next; + } + } + } + } +#endif /* RTE_SCHED_RED */ for (i = 0; i < MAX_SCHED_SUBPORTS; i++) { char sec_name[CFG_NAME_LEN]; snprintf(sec_name, sizeof(sec_name), "subport %d", i); if (rte_cfgfile_has_section(cfg, sec_name)) { + entry = rte_cfgfile_get_entry(cfg, sec_name, + "number of pipes per subport"); + if (entry) + subport_params[i].n_pipes_per_subport_enabled = + (uint32_t)atoi(entry); + + entry = rte_cfgfile_get_entry(cfg, sec_name, "queue sizes"); + if (entry) { + char *next; + + for (j = 0; j < RTE_SCHED_TRAFFIC_CLASS_BE; j++) { + subport_params[i].qsize[j] = + (uint16_t)strtol(entry, &next, 10); + if (subport_params[i].qsize[j] != 0) { + active_queues[n_active_queues] = j; + n_active_queues++; + } + if (next == NULL) + break; + entry = next; + } + + subport_params[i].qsize[RTE_SCHED_TRAFFIC_CLASS_BE] = + (uint16_t)strtol(entry, &next, 10); + + for (j = 0; j < RTE_SCHED_BE_QUEUES_PER_PIPE; j++) { + active_queues[n_active_queues] = + RTE_SCHED_TRAFFIC_CLASS_BE + j; + n_active_queues++; + } + } + entry = rte_cfgfile_get_entry(cfg, sec_name, "tb rate"); if (entry) subport_params[i].tb_rate = (uint32_t)atoi(entry); @@ -362,6 +367,20 @@ cfg_load_subport(struct rte_cfgfile *cfg, struct rte_sched_subport_params *subpo } } } +#ifdef RTE_SCHED_RED + for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { + for (k = 0; k < RTE_COLORS; k++) { + subport_params[i].red_params[j][k].min_th = + red_params[j][k].min_th; + subport_params[i].red_params[j][k].max_th = + red_params[j][k].max_th; + subport_params[i].red_params[j][k].maxp_inv = + red_params[j][k].maxp_inv; + subport_params[i].red_params[j][k].wq_log2 = + red_params[j][k].wq_log2; + } + } +#endif } } diff --git a/examples/qos_sched/init.c b/examples/qos_sched/init.c index 32e6e1ba2..0a17e0d4d 100644 --- a/examples/qos_sched/init.c +++ b/examples/qos_sched/init.c @@ -180,18 +180,6 @@ app_init_port(uint16_t portid, struct rte_mempool *mp) return 0; } -static struct rte_sched_subport_params subport_params[MAX_SCHED_SUBPORTS] = { - { - .tb_rate = 1250000000, - .tb_size = 1000000, - - .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000, - 1250000000, 1250000000, 1250000000, 1250000000, 1250000000, - 1250000000, 1250000000, 1250000000, 1250000000}, - .tc_period = 10, - }, -}; - static struct rte_sched_pipe_params pipe_profiles[MAX_SCHED_PIPE_PROFILES] = { { /* Profile #0 */ .tb_rate = 305175, @@ -208,19 +196,21 @@ static struct rte_sched_pipe_params pipe_profiles[MAX_SCHED_PIPE_PROFILES] = { }, }; -struct rte_sched_port_params port_params = { - .name = "port_scheduler_0", - .socket = 0, /* computed */ - .rate = 0, /* computed */ - .mtu = 6 + 6 + 4 + 4 + 2 + 1500, - .frame_overhead = RTE_SCHED_FRAME_OVERHEAD_DEFAULT, - .n_subports_per_port = 1, - .n_pipes_per_subport = 4096, - .qsize = {64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}, - .pipe_profiles = pipe_profiles, - .n_pipe_profiles = sizeof(pipe_profiles) / sizeof(struct rte_sched_pipe_params), - .n_max_pipe_profiles = MAX_SCHED_PIPE_PROFILES, +struct rte_sched_subport_params subport_params[MAX_SCHED_SUBPORTS] = { + { + .tb_rate = 1250000000, + .tb_size = 1000000, + .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000, + 1250000000, 1250000000, 1250000000, 1250000000, 1250000000, + 1250000000, 1250000000, 1250000000, 1250000000}, + .tc_period = 10, + .n_pipes_per_subport_enabled = 4096, + .qsize = {64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}, + .pipe_profiles = pipe_profiles, + .n_pipe_profiles = sizeof(pipe_profiles) / + sizeof(struct rte_sched_pipe_params), + .n_max_pipe_profiles = MAX_SCHED_PIPE_PROFILES, #ifdef RTE_SCHED_RED .red_params = { /* Traffic Class 0 Colors Green / Yellow / Red */ @@ -289,6 +279,17 @@ struct rte_sched_port_params port_params = { [12][2] = {.min_th = 32, .max_th = 64, .maxp_inv = 10, .wq_log2 = 9}, }, #endif /* RTE_SCHED_RED */ + }, +}; + +struct rte_sched_port_params port_params = { + .name = "port_scheduler_0", + .socket = 0, /* computed */ + .rate = 0, /* computed */ + .mtu = 6 + 6 + 4 + 4 + 2 + 1500, + .frame_overhead = RTE_SCHED_FRAME_OVERHEAD_DEFAULT, + .n_subports_per_port = 1, + .n_pipes_per_subport = MAX_SCHED_PIPES, }; static struct rte_sched_port * @@ -323,7 +324,10 @@ app_init_sched_port(uint32_t portid, uint32_t socketid) subport, err); } - for (pipe = 0; pipe < port_params.n_pipes_per_subport; pipe++) { + uint32_t n_pipes_per_subport = + subport_params[subport].n_pipes_per_subport_enabled; + + for (pipe = 0; pipe < n_pipes_per_subport; pipe++) { if (app_pipe_to_profile[subport][pipe] != -1) { err = rte_sched_pipe_config(port, subport, pipe, app_pipe_to_profile[subport][pipe]); diff --git a/examples/qos_sched/main.h b/examples/qos_sched/main.h index d8f890b64..baa2b3ead 100644 --- a/examples/qos_sched/main.h +++ b/examples/qos_sched/main.h @@ -152,6 +152,7 @@ uint32_t active_queues[RTE_SCHED_QUEUES_PER_PIPE]; uint32_t n_active_queues; extern struct rte_sched_port_params port_params; +extern struct rte_sched_subport_params subport_params[MAX_SCHED_SUBPORTS]; int app_parse_args(int argc, char **argv); int app_init(void); diff --git a/examples/qos_sched/profile.cfg b/examples/qos_sched/profile.cfg index 335561370..61b8b7071 100644 --- a/examples/qos_sched/profile.cfg +++ b/examples/qos_sched/profile.cfg @@ -20,11 +20,12 @@ [port] frame overhead = 24 number of subports per port = 1 -number of pipes per subport = 4096 -queue sizes = 64 64 64 64 64 64 64 64 64 64 64 64 64 ; Subport configuration [subport 0] +number of pipes per subport = 4096 +queue sizes = 64 64 64 64 64 64 64 64 64 64 64 64 64 + tb rate = 1250000000 ; Bytes per second tb size = 1000000 ; Bytes diff --git a/examples/qos_sched/profile_ov.cfg b/examples/qos_sched/profile_ov.cfg index 394987399..ab509d28d 100644 --- a/examples/qos_sched/profile_ov.cfg +++ b/examples/qos_sched/profile_ov.cfg @@ -5,11 +5,12 @@ [port] frame overhead = 24 number of subports per port = 1 -number of pipes per subport = 32 -queue sizes = 64 64 64 64 64 64 64 64 64 64 64 64 64 ; Subport configuration [subport 0] +number of pipes per subport = 32 +queue sizes = 64 64 64 64 64 64 64 64 64 64 64 64 64 + tb rate = 8400000 ; Bytes per second tb size = 100000 ; Bytes diff --git a/examples/qos_sched/stats.c b/examples/qos_sched/stats.c index e62e4a2f6..ce34b6c7c 100644 --- a/examples/qos_sched/stats.c +++ b/examples/qos_sched/stats.c @@ -24,7 +24,7 @@ qavg_q(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id, uint8_t tc, if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || - pipe_id >= port_params.n_pipes_per_subport || + pipe_id >= subport_params[subport_id].n_pipes_per_subport_enabled || tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE || q >= RTE_SCHED_BE_QUEUES_PER_PIPE || (tc < RTE_SCHED_TRAFFIC_CLASS_BE && q > 0)) @@ -32,7 +32,7 @@ qavg_q(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id, uint8_t tc, port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - queue_id += port_params.n_pipes_per_subport * + queue_id += subport_params[i].n_pipes_per_subport_enabled * RTE_SCHED_QUEUES_PER_PIPE; if (tc < RTE_SCHED_TRAFFIC_CLASS_BE) queue_id += pipe_id * RTE_SCHED_QUEUES_PER_PIPE + tc; @@ -69,14 +69,16 @@ qavg_tcpipe(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id, } if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || - pipe_id >= port_params.n_pipes_per_subport || + pipe_id >= subport_params[subport_id].n_pipes_per_subport_enabled || tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE) return -1; port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - queue_id += port_params.n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; + queue_id += + subport_params[i].n_pipes_per_subport_enabled * + RTE_SCHED_QUEUES_PER_PIPE; queue_id += pipe_id * RTE_SCHED_QUEUES_PER_PIPE + tc; @@ -123,13 +125,13 @@ qavg_pipe(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id) if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || - pipe_id >= port_params.n_pipes_per_subport) + pipe_id >= subport_params[subport_id].n_pipes_per_subport_enabled) return -1; port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - queue_id += port_params.n_pipes_per_subport * + queue_id += subport_params[i].n_pipes_per_subport_enabled * RTE_SCHED_QUEUES_PER_PIPE; queue_id += pipe_id * RTE_SCHED_QUEUES_PER_PIPE; @@ -177,13 +179,17 @@ qavg_tcsubport(uint16_t port_id, uint32_t subport_id, uint8_t tc) for (i = 0; i < subport_id; i++) subport_queue_id += - port_params.n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; + subport_params[i].n_pipes_per_subport_enabled * + RTE_SCHED_QUEUES_PER_PIPE; average = 0; for (count = 0; count < qavg_ntimes; count++) { + uint32_t n_pipes_per_subport = + subport_params[subport_id].n_pipes_per_subport_enabled; + part_average = 0; - for (i = 0; i < port_params.n_pipes_per_subport; i++) { + for (i = 0; i < n_pipes_per_subport; i++) { if (tc < RTE_SCHED_TRAFFIC_CLASS_BE) { queue_id = subport_queue_id + i * RTE_SCHED_QUEUES_PER_PIPE + tc; @@ -203,10 +209,11 @@ qavg_tcsubport(uint16_t port_id, uint32_t subport_id, uint8_t tc) } if (tc < RTE_SCHED_TRAFFIC_CLASS_BE) - average += part_average / (port_params.n_pipes_per_subport); + average += part_average / + (subport_params[subport_id].n_pipes_per_subport_enabled); else - average += - part_average / (port_params.n_pipes_per_subport) * + average += part_average / + (subport_params[subport_id].n_pipes_per_subport_enabled) * RTE_SCHED_BE_QUEUES_PER_PIPE; usleep(qavg_period); @@ -240,14 +247,17 @@ qavg_subport(uint16_t port_id, uint32_t subport_id) port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - subport_queue_id += port_params.n_pipes_per_subport * + subport_queue_id += subport_params[i].n_pipes_per_subport_enabled * RTE_SCHED_QUEUES_PER_PIPE; average = 0; for (count = 0; count < qavg_ntimes; count++) { + uint32_t n_pipes_per_subport = + subport_params[subport_id].n_pipes_per_subport_enabled; + part_average = 0; - for (i = 0; i < port_params.n_pipes_per_subport; i++) { + for (i = 0; i < n_pipes_per_subport; i++) { queue_id = subport_queue_id + i * RTE_SCHED_QUEUES_PER_PIPE; for (j = 0; j < RTE_SCHED_QUEUES_PER_PIPE; j++) { @@ -258,7 +268,8 @@ qavg_subport(uint16_t port_id, uint32_t subport_id) } average += part_average / - (port_params.n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE); + (subport_params[subport_id].n_pipes_per_subport_enabled * + RTE_SCHED_QUEUES_PER_PIPE); usleep(qavg_period); } @@ -322,12 +333,13 @@ pipe_stat(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id) if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || - pipe_id >= port_params.n_pipes_per_subport) + pipe_id >= subport_params[subport_id].n_pipes_per_subport_enabled) return -1; port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - queue_id += port_params.n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; + queue_id += subport_params[i].n_pipes_per_subport_enabled * + RTE_SCHED_QUEUES_PER_PIPE; queue_id += pipe_id * RTE_SCHED_QUEUES_PER_PIPE; -- 2.21.0
Remove redundant data structure fields from port level data structures and update the release notes. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- doc/guides/rel_notes/release_19_11.rst | 7 ++++- lib/librte_sched/rte_sched.c | 42 +------------------------- lib/librte_sched/rte_sched.h | 22 -------------- 3 files changed, 7 insertions(+), 64 deletions(-) diff --git a/doc/guides/rel_notes/release_19_11.rst b/doc/guides/rel_notes/release_19_11.rst index f59a28307..524fb338b 100644 --- a/doc/guides/rel_notes/release_19_11.rst +++ b/doc/guides/rel_notes/release_19_11.rst @@ -228,6 +228,11 @@ API Changes has been introduced in this release is used when used when all the packets enqueued in the tx adapter are destined for the same Ethernet port & Tx queue. +* sched: The pipe nodes configuration parameters such as number of pipes, + pipe queue sizes, pipe profiles, etc., are moved from port level structure + to subport level. This allows different subports of the same port to + have different configuration for the pipe nodes. + ABI Changes ----------- @@ -315,7 +320,7 @@ The libraries prepended with a plus sign were incremented in this version. librte_rcu.so.1 librte_reorder.so.1 librte_ring.so.2 - librte_sched.so.3 + + librte_sched.so.4 librte_security.so.2 librte_stack.so.1 librte_table.so.3 diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 1faa580d0..710ecf65a 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -216,13 +216,6 @@ struct rte_sched_port { uint32_t mtu; uint32_t frame_overhead; int socket; - uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - uint32_t n_pipe_profiles; - uint32_t n_max_pipe_profiles; - uint32_t pipe_tc_be_rate_max; -#ifdef RTE_SCHED_RED - struct rte_red_config red_config[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; -#endif /* Timing */ uint64_t time_cpu_cycles; /* Current CPU time measured in CPU cyles */ @@ -230,48 +223,15 @@ struct rte_sched_port { uint64_t time; /* Current NIC TX time measured in bytes */ struct rte_reciprocal inv_cycles_per_byte; /* CPU cycles per byte */ - /* Scheduling loop detection */ - uint32_t pipe_loop; - uint32_t pipe_exhaustion; - - /* Bitmap */ - struct rte_bitmap *bmp; - uint32_t grinder_base_bmp_pos[RTE_SCHED_PORT_N_GRINDERS] __rte_aligned_16; - /* Grinders */ - struct rte_sched_grinder grinder[RTE_SCHED_PORT_N_GRINDERS]; - uint32_t busy_grinders; struct rte_mbuf **pkts_out; uint32_t n_pkts_out; uint32_t subport_id; - /* Queue base calculation */ - uint32_t qsize_add[RTE_SCHED_QUEUES_PER_PIPE]; - uint32_t qsize_sum; - /* Large data structures */ - struct rte_sched_subport *subports[0]; - struct rte_sched_subport *subport; - struct rte_sched_pipe *pipe; - struct rte_sched_queue *queue; - struct rte_sched_queue_extra *queue_extra; - struct rte_sched_pipe_profile *pipe_profiles; - uint8_t *bmp_array; - struct rte_mbuf **queue_array; - uint8_t memory[0] __rte_cache_aligned; + struct rte_sched_subport *subports[0] __rte_cache_aligned; } __rte_cache_aligned; -enum rte_sched_port_array { - e_RTE_SCHED_PORT_ARRAY_SUBPORT = 0, - e_RTE_SCHED_PORT_ARRAY_PIPE, - e_RTE_SCHED_PORT_ARRAY_QUEUE, - e_RTE_SCHED_PORT_ARRAY_QUEUE_EXTRA, - e_RTE_SCHED_PORT_ARRAY_PIPE_PROFILES, - e_RTE_SCHED_PORT_ARRAY_BMP_ARRAY, - e_RTE_SCHED_PORT_ARRAY_QUEUE_ARRAY, - e_RTE_SCHED_PORT_ARRAY_TOTAL, -}; - enum rte_sched_subport_array { e_RTE_SCHED_SUBPORT_ARRAY_PIPE = 0, e_RTE_SCHED_SUBPORT_ARRAY_QUEUE, diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index 40f02f124..c82c23c14 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -260,28 +260,6 @@ struct rte_sched_port_params { * the subports of the same port. */ uint32_t n_pipes_per_subport; - - /** Packet queue size for each traffic class. - * All the pipes within the same subport share the similar - * configuration for the queues. - */ - uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - - /** Pipe profile table. - * Every pipe is configured using one of the profiles from this table. - */ - struct rte_sched_pipe_params *pipe_profiles; - - /** Profiles in the pipe profile table */ - uint32_t n_pipe_profiles; - - /** Max profiles allowed in the pipe profile table */ - uint32_t n_max_pipe_profiles; - -#ifdef RTE_SCHED_RED - /** RED parameters */ - struct rte_red_params red_params[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; -#endif }; /* -- 2.21.0
This patchset refactors the dpdk qos sched library to allow subport level configuration flexibility of the pipe nodes. Currently, all parameters for the pipe nodes (subscribers) configuration are part of the port level structure which forces all groups of subscribers (pipes) in different subports to have similar configurations in terms of their number, queue sizes, traffic-classes, etc. The new implementation moves pipe nodes configuration parameters from port level to subport level structure. This allows different subports of the same port to have different configuration for the pipe nodes, for examples- number of pipes, queue sizes, pipe profiles, etc. In order to keep the implementation complexity under control, all pipes within the same subport share the same configuration for queue sizes. v7: - rebase on latest dpdk master - fix build issue with clang v6: - fix build issue with patchset v5: - remove patches on 64-bit values support, sent separately v4: - remove deprecation note - rebase on current dpdk head - add 64-bit values support v3: - improve doxygen comments v2: - fix qsize parsing in sample application - fix checkpatch warnings Jasvinder Singh (15): sched: add pipe config params to subport struct sched: modify internal structs for config flexibility sched: remove pipe params config from port level sched: add pipe config to subport level sched: modify pipe functions for config flexibility sched: modify pkt enqueue for config flexibility sched: update memory compute to support flexiblity sched: update grinder functions for config flexibility sched: update pkt dequeue for flexible config sched: update queue stats read for config flexibility test/sched: modify tests for subport config flexibility net/softnic: add subport config flexibility to TM ip_pipeline: add subport config flexibility to TM examples/qos_sched: add subport configuration flexibility sched: remove redundant code app/test/test_sched.c | 35 +- doc/guides/rel_notes/release_19_11.rst | 7 +- drivers/net/softnic/rte_eth_softnic_tm.c | 54 +- examples/ip_pipeline/cli.c | 71 +- examples/ip_pipeline/tmgr.c | 25 +- examples/ip_pipeline/tmgr.h | 7 +- examples/qos_sched/app_thread.c | 20 +- examples/qos_sched/cfg_file.c | 229 ++-- examples/qos_sched/init.c | 54 +- examples/qos_sched/main.h | 1 + examples/qos_sched/profile.cfg | 5 +- examples/qos_sched/profile_ov.cfg | 5 +- examples/qos_sched/stats.c | 44 +- lib/librte_sched/Makefile | 2 +- lib/librte_sched/meson.build | 2 +- lib/librte_sched/rte_sched.c | 1394 +++++++++++++--------- lib/librte_sched/rte_sched.h | 129 +- lib/librte_sched/rte_sched_version.map | 2 +- 18 files changed, 1213 insertions(+), 873 deletions(-) -- 2.21.0
Add pipe configuration parameters to subport level structure to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/Makefile | 2 +- lib/librte_sched/meson.build | 2 +- lib/librte_sched/rte_sched.h | 92 ++++++++++++++++++++++++------------ 3 files changed, 65 insertions(+), 31 deletions(-) diff --git a/lib/librte_sched/Makefile b/lib/librte_sched/Makefile index 3d7f410e1..6e4a72d89 100644 --- a/lib/librte_sched/Makefile +++ b/lib/librte_sched/Makefile @@ -18,7 +18,7 @@ LDLIBS += -lrte_timer EXPORT_MAP := rte_sched_version.map -LIBABIVER := 3 +LIBABIVER := 4 # # all source are stored in SRCS-y diff --git a/lib/librte_sched/meson.build b/lib/librte_sched/meson.build index 59d43c6d8..9f40a2368 100644 --- a/lib/librte_sched/meson.build +++ b/lib/librte_sched/meson.build @@ -1,7 +1,7 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright(c) 2017 Intel Corporation -version = 3 +version = 4 sources = files('rte_sched.c', 'rte_red.c', 'rte_approx.c') headers = files('rte_sched.h', 'rte_sched_common.h', 'rte_red.h', 'rte_approx.h') diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index eac6db274..fbb0e23fa 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -111,7 +111,7 @@ extern "C" { #endif /* - * Subport configuration parameters. The period and credits_per_period + * Pipe configuration parameters. The period and credits_per_period * parameters are measured in bytes, with one byte meaning the time * duration associated with the transmission of one byte on the * physical medium of the output port, with pipe or pipe traffic class @@ -119,7 +119,7 @@ extern "C" { * credits_per_period divided by period. One credit represents one * byte. */ -struct rte_sched_subport_params { +struct rte_sched_pipe_params { /** Token bucket rate (measured in bytes per second) */ uint32_t tb_rate; @@ -129,32 +129,18 @@ struct rte_sched_subport_params { /** Traffic class rates (measured in bytes per second) */ uint32_t tc_rate[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - /** Enforcement period for rates (measured in milliseconds) */ + /** Enforcement period (measured in milliseconds) */ uint32_t tc_period; -}; - -/** Subport statistics */ -struct rte_sched_subport_stats { - /** Number of packets successfully written */ - uint32_t n_pkts_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - - /** Number of packets dropped */ - uint32_t n_pkts_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - /** Number of bytes successfully written for each traffic class */ - uint32_t n_bytes_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - - /** Number of bytes dropped for each traffic class */ - uint32_t n_bytes_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + /** Best-effort traffic class oversubscription weight */ + uint8_t tc_ov_weight; -#ifdef RTE_SCHED_RED - /** Number of packets dropped by red */ - uint32_t n_pkts_red_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; -#endif + /** WRR weights of best-effort traffic class queues */ + uint8_t wrr_weights[RTE_SCHED_BE_QUEUES_PER_PIPE]; }; /* - * Pipe configuration parameters. The period and credits_per_period + * Subport configuration parameters. The period and credits_per_period * parameters are measured in bytes, with one byte meaning the time * duration associated with the transmission of one byte on the * physical medium of the output port, with pipe or pipe traffic class @@ -162,7 +148,7 @@ struct rte_sched_subport_stats { * credits_per_period divided by period. One credit represents one * byte. */ -struct rte_sched_pipe_params { +struct rte_sched_subport_params { /** Token bucket rate (measured in bytes per second) */ uint32_t tb_rate; @@ -172,14 +158,58 @@ struct rte_sched_pipe_params { /** Traffic class rates (measured in bytes per second) */ uint32_t tc_rate[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - /** Enforcement period (measured in milliseconds) */ + /** Enforcement period for rates (measured in milliseconds) */ uint32_t tc_period; - /** Best-effort traffic class oversubscription weight */ - uint8_t tc_ov_weight; + /** Number of subport pipes. + * The subport can enable/allocate fewer pipes than the maximum + * number set through struct port_params::n_max_pipes_per_subport, + * as needed, to avoid memory allocation for the queues of the + * pipes that are not really needed. + */ + uint32_t n_pipes_per_subport_enabled; - /** WRR weights of best-effort traffic class queues */ - uint8_t wrr_weights[RTE_SCHED_BE_QUEUES_PER_PIPE]; + /** Packet queue size for each traffic class. + * All the pipes within the same subport share the similar + * configuration for the queues. + */ + uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + + /** Pipe profile table. + * Every pipe is configured using one of the profiles from this table. + */ + struct rte_sched_pipe_params *pipe_profiles; + + /** Profiles in the pipe profile table */ + uint32_t n_pipe_profiles; + + /** Max allowed profiles in the pipe profile table */ + uint32_t n_max_pipe_profiles; + +#ifdef RTE_SCHED_RED + /** RED parameters */ + struct rte_red_params red_params[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; +#endif +}; + +/** Subport statistics */ +struct rte_sched_subport_stats { + /** Number of packets successfully written */ + uint32_t n_pkts_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + + /** Number of packets dropped */ + uint32_t n_pkts_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + + /** Number of bytes successfully written for each traffic class */ + uint32_t n_bytes_tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + + /** Number of bytes dropped for each traffic class */ + uint32_t n_bytes_tc_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + +#ifdef RTE_SCHED_RED + /** Number of packets dropped by red */ + uint32_t n_pkts_red_dropped[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; +#endif }; /** Queue statistics */ @@ -224,7 +254,11 @@ struct rte_sched_port_params { /** Number of subports */ uint32_t n_subports_per_port; - /** Number of subport_pipes */ + /** 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 + * the subports of the same port. + */ uint32_t n_pipes_per_subport; /** Packet queue size for each traffic class. -- 2.21.0
Update internal structures related to port and subport to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 106 ++++++++++++++++++++++++++--------- 1 file changed, 78 insertions(+), 28 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index d8ab21d64..672412b77 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -47,33 +47,6 @@ */ #define RTE_SCHED_TIME_SHIFT 8 -struct rte_sched_subport { - /* Token bucket (TB) */ - uint64_t tb_time; /* time of last update */ - uint32_t tb_period; - uint32_t tb_credits_per_period; - uint32_t tb_size; - uint32_t tb_credits; - - /* Traffic classes (TCs) */ - uint64_t tc_time; /* time of next update */ - uint32_t tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - uint32_t tc_credits[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - uint32_t tc_period; - - /* TC oversubscription */ - uint32_t tc_ov_wm; - uint32_t tc_ov_wm_min; - uint32_t tc_ov_wm_max; - uint8_t tc_ov_period_id; - uint8_t tc_ov; - uint32_t tc_ov_n; - double tc_ov_rate; - - /* Statistics */ - struct rte_sched_subport_stats stats; -}; - struct rte_sched_pipe_profile { /* Token bucket (TB) */ uint32_t tb_period; @@ -107,7 +80,6 @@ struct rte_sched_pipe { /* TC oversubscription */ uint32_t tc_ov_credits; uint8_t tc_ov_period_id; - uint8_t reserved[3]; } __rte_cache_aligned; struct rte_sched_queue { @@ -166,6 +138,72 @@ struct rte_sched_grinder { uint8_t wrr_cost[RTE_SCHED_BE_QUEUES_PER_PIPE]; }; +struct rte_sched_subport { + /* Token bucket (TB) */ + uint64_t tb_time; /* time of last update */ + uint32_t tb_period; + uint32_t tb_credits_per_period; + uint32_t tb_size; + uint32_t tb_credits; + + /* Traffic classes (TCs) */ + uint64_t tc_time; /* time of next update */ + uint32_t tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + uint32_t tc_credits[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + uint32_t tc_period; + + /* TC oversubscription */ + uint32_t tc_ov_wm; + uint32_t tc_ov_wm_min; + uint32_t tc_ov_wm_max; + uint8_t tc_ov_period_id; + uint8_t tc_ov; + uint32_t tc_ov_n; + double tc_ov_rate; + + /* Statistics */ + struct rte_sched_subport_stats stats; + + /* Subport pipes */ + uint32_t n_pipes_per_subport_enabled; + uint32_t n_pipe_profiles; + uint32_t n_max_pipe_profiles; + + /* Pipe best-effort TC rate */ + uint32_t pipe_tc_be_rate_max; + + /* Pipe queues size */ + uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; + +#ifdef RTE_SCHED_RED + struct rte_red_config red_config[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; +#endif + + /* Scheduling loop detection */ + uint32_t pipe_loop; + uint32_t pipe_exhaustion; + + /* Bitmap */ + struct rte_bitmap *bmp; + uint32_t grinder_base_bmp_pos[RTE_SCHED_PORT_N_GRINDERS] __rte_aligned_16; + + /* Grinders */ + struct rte_sched_grinder grinder[RTE_SCHED_PORT_N_GRINDERS]; + uint32_t busy_grinders; + + /* Queue base calculation */ + uint32_t qsize_add[RTE_SCHED_QUEUES_PER_PIPE]; + uint32_t qsize_sum; + + struct rte_sched_pipe *pipe; + struct rte_sched_queue *queue; + struct rte_sched_queue_extra *queue_extra; + struct rte_sched_pipe_profile *pipe_profiles; + uint8_t *bmp_array; + struct rte_mbuf **queue_array; + uint8_t memory[0] __rte_cache_aligned; +} __rte_cache_aligned; + struct rte_sched_port { /* User parameters */ uint32_t n_subports_per_port; @@ -177,6 +215,7 @@ struct rte_sched_port { uint32_t rate; uint32_t mtu; uint32_t frame_overhead; + int socket; uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; uint32_t n_pipe_profiles; uint32_t n_max_pipe_profiles; @@ -210,6 +249,7 @@ struct rte_sched_port { uint32_t qsize_sum; /* Large data structures */ + struct rte_sched_subport *subports[0]; struct rte_sched_subport *subport; struct rte_sched_pipe *pipe; struct rte_sched_queue *queue; @@ -231,6 +271,16 @@ enum rte_sched_port_array { e_RTE_SCHED_PORT_ARRAY_TOTAL, }; +enum rte_sched_subport_array { + e_RTE_SCHED_SUBPORT_ARRAY_PIPE = 0, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_EXTRA, + e_RTE_SCHED_SUBPORT_ARRAY_PIPE_PROFILES, + e_RTE_SCHED_SUBPORT_ARRAY_BMP_ARRAY, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_ARRAY, + e_RTE_SCHED_SUBPORT_ARRAY_TOTAL, +}; + #ifdef RTE_SCHED_COLLECT_STATS static inline uint32_t -- 2.21.0
Remove pipes configuration from the port level to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 254 ++++++++++------------------------- 1 file changed, 71 insertions(+), 183 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 672412b77..952e449f7 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -291,6 +291,31 @@ rte_sched_port_queues_per_subport(struct rte_sched_port *port) #endif +static inline uint32_t +rte_sched_subport_pipe_queues(struct rte_sched_subport *subport) +{ + return RTE_SCHED_QUEUES_PER_PIPE * subport->n_pipes_per_subport_enabled; +} + +static inline struct rte_mbuf ** +rte_sched_subport_pipe_qbase(struct rte_sched_subport *subport, uint32_t qindex) +{ + uint32_t pindex = qindex >> 4; + uint32_t qpos = qindex & (RTE_SCHED_QUEUES_PER_PIPE - 1); + + return (subport->queue_array + pindex * + subport->qsize_sum + subport->qsize_add[qpos]); +} + +static inline uint16_t +rte_sched_subport_pipe_qsize(struct rte_sched_port *port, +struct rte_sched_subport *subport, uint32_t qindex) +{ + uint32_t tc = port->pipe_tc[qindex & (RTE_SCHED_QUEUES_PER_PIPE - 1)]; + + return subport->qsize[tc]; +} + static inline uint32_t rte_sched_port_queues_per_port(struct rte_sched_port *port) { @@ -414,8 +439,6 @@ pipe_profile_check(struct rte_sched_pipe_params *params, 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__); @@ -456,45 +479,10 @@ rte_sched_port_check_params(struct rte_sched_port_params *params) if (params->n_pipes_per_subport == 0 || !rte_is_power_of_2(params->n_pipes_per_subport)) { RTE_LOG(ERR, SCHED, - "%s: Incorrect value for pipes number\n", __func__); - return -EINVAL; - } - - /* qsize: if non-zero, power of 2, - * no bigger than 32K (due to 16-bit read/write pointers) - */ - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - uint16_t qsize = params->qsize[i]; - - if ((qsize != 0 && !rte_is_power_of_2(qsize)) || - ((i == RTE_SCHED_TRAFFIC_CLASS_BE) && (qsize == 0))) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tc rate\n", __func__); - return -EINVAL; - } - } - - /* pipe_profiles and n_pipe_profiles */ - if (params->pipe_profiles == NULL || - params->n_pipe_profiles == 0 || - params->n_pipe_profiles > params->n_max_pipe_profiles) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for number of pipe profiles\n", __func__); + "%s: Incorrect value for maximum pipes number\n", __func__); return -EINVAL; } - for (i = 0; i < params->n_pipe_profiles; i++) { - struct rte_sched_pipe_params *p = params->pipe_profiles + i; - int status; - - status = pipe_profile_check(p, params->rate, ¶ms->qsize[0]); - if (status != 0) { - RTE_LOG(ERR, SCHED, - "%s: Pipe profile check failed(%d)\n", __func__, status); - return -EINVAL; - } - } - return 0; } @@ -582,32 +570,6 @@ rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params) return size0 + size1; } -static void -rte_sched_port_config_qsize(struct rte_sched_port *port) -{ - uint32_t i; - - port->qsize_add[0] = 0; - - /* Strict prority traffic class */ - for (i = 1; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - port->qsize_add[i] = port->qsize_add[i-1] + port->qsize[i-1]; - - /* Best-effort traffic class */ - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 1] = - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE] + - port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 2] = - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 1] + - port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 3] = - port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 2] + - port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; - - port->qsize_sum = port->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 3] + - port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; -} - static void rte_sched_port_log_pipe_profile(struct rte_sched_port *port, uint32_t i) { @@ -717,56 +679,41 @@ rte_sched_pipe_profile_convert(struct rte_sched_port *port, dst->wrr_cost[3] = (uint8_t) wrr_cost[3]; } -static void -rte_sched_port_config_pipe_profile_table(struct rte_sched_port *port, - struct rte_sched_port_params *params) -{ - uint32_t i; - - for (i = 0; i < port->n_pipe_profiles; i++) { - struct rte_sched_pipe_params *src = params->pipe_profiles + i; - struct rte_sched_pipe_profile *dst = port->pipe_profiles + i; - - rte_sched_pipe_profile_convert(port, src, dst, params->rate); - rte_sched_port_log_pipe_profile(port, i); - } - - port->pipe_tc_be_rate_max = 0; - for (i = 0; i < port->n_pipe_profiles; i++) { - struct rte_sched_pipe_params *src = params->pipe_profiles + i; - uint32_t pipe_tc_be_rate = src->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; - - if (port->pipe_tc_be_rate_max < pipe_tc_be_rate) - port->pipe_tc_be_rate_max = pipe_tc_be_rate; - } -} - struct rte_sched_port * rte_sched_port_config(struct rte_sched_port_params *params) { struct rte_sched_port *port = NULL; - uint32_t mem_size, bmp_mem_size, n_queues_per_port, i, j, cycles_per_byte; + uint32_t size0, size1; + uint32_t cycles_per_byte; + uint32_t i, j; + int status; - /* Check user parameters. Determine the amount of memory to allocate */ - mem_size = rte_sched_port_get_memory_footprint(params); - if (mem_size == 0) + status = rte_sched_port_check_params(params); + if (status != 0) { + RTE_LOG(ERR, SCHED, + "%s: Port scheduler params check failed (%d)\n", + __func__, status); return NULL; + } + + size0 = sizeof(struct rte_sched_port); + size1 = params->n_subports_per_port * sizeof(struct rte_sched_subport *); /* Allocate memory to store the data structures */ - port = rte_zmalloc_socket("qos_params", mem_size, RTE_CACHE_LINE_SIZE, + port = rte_zmalloc_socket("qos_params", size0 + size1, RTE_CACHE_LINE_SIZE, params->socket); - if (port == NULL) - return NULL; + if (port == NULL) { + RTE_LOG(ERR, SCHED, "%s: Memory allocation fails\n", __func__); - /* compile time checks */ - RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS == 0); - RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS & (RTE_SCHED_PORT_N_GRINDERS - 1)); + return NULL; + } /* User parameters */ port->n_subports_per_port = params->n_subports_per_port; port->n_pipes_per_subport = params->n_pipes_per_subport; port->n_pipes_per_subport_log2 = __builtin_ctz(params->n_pipes_per_subport); + port->socket = params->socket; for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) port->pipe_queue[i] = i; @@ -787,32 +734,6 @@ rte_sched_port_config(struct rte_sched_port_params *params) port->rate = params->rate; port->mtu = params->mtu + params->frame_overhead; port->frame_overhead = params->frame_overhead; - memcpy(port->qsize, params->qsize, sizeof(params->qsize)); - port->n_pipe_profiles = params->n_pipe_profiles; - port->n_max_pipe_profiles = params->n_max_pipe_profiles; - -#ifdef RTE_SCHED_RED - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - uint32_t j; - - for (j = 0; j < RTE_COLORS; j++) { - /* if min/max are both zero, then RED is disabled */ - if ((params->red_params[i][j].min_th | - params->red_params[i][j].max_th) == 0) { - continue; - } - - if (rte_red_config_init(&port->red_config[i][j], - params->red_params[i][j].wq_log2, - params->red_params[i][j].min_th, - params->red_params[i][j].max_th, - params->red_params[i][j].maxp_inv) != 0) { - rte_free(port); - return NULL; - } - } - } -#endif /* Timing */ port->time_cpu_cycles = rte_get_tsc_cycles(); @@ -823,79 +744,32 @@ rte_sched_port_config(struct rte_sched_port_params *params) / params->rate; port->inv_cycles_per_byte = rte_reciprocal_value(cycles_per_byte); - /* Scheduling loop detection */ - port->pipe_loop = RTE_SCHED_PIPE_INVALID; - port->pipe_exhaustion = 0; - /* Grinders */ - port->busy_grinders = 0; port->pkts_out = NULL; port->n_pkts_out = 0; - /* Queue base calculation */ - rte_sched_port_config_qsize(port); - - /* Large data structures */ - port->subport = (struct rte_sched_subport *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_SUBPORT)); - port->pipe = (struct rte_sched_pipe *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_PIPE)); - port->queue = (struct rte_sched_queue *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_QUEUE)); - port->queue_extra = (struct rte_sched_queue_extra *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_QUEUE_EXTRA)); - port->pipe_profiles = (struct rte_sched_pipe_profile *) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_PIPE_PROFILES)); - port->bmp_array = port->memory - + rte_sched_port_get_array_base(params, e_RTE_SCHED_PORT_ARRAY_BMP_ARRAY); - port->queue_array = (struct rte_mbuf **) - (port->memory + rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_QUEUE_ARRAY)); - - /* Pipe profile table */ - rte_sched_port_config_pipe_profile_table(port, params); - - /* Bitmap */ - n_queues_per_port = rte_sched_port_queues_per_port(port); - bmp_mem_size = rte_bitmap_get_memory_footprint(n_queues_per_port); - port->bmp = rte_bitmap_init(n_queues_per_port, port->bmp_array, - bmp_mem_size); - if (port->bmp == NULL) { - RTE_LOG(ERR, SCHED, "Bitmap init error\n"); - rte_free(port); - return NULL; - } - - for (i = 0; i < RTE_SCHED_PORT_N_GRINDERS; i++) - port->grinder_base_bmp_pos[i] = RTE_SCHED_PIPE_INVALID; - - return port; } -void -rte_sched_port_free(struct rte_sched_port *port) +static inline void +rte_sched_subport_free(struct rte_sched_port *port, + struct rte_sched_subport *subport) { + uint32_t n_subport_pipe_queues; uint32_t qindex; - uint32_t n_queues_per_port; - /* Check user parameters */ - if (port == NULL) + if (subport == NULL) return; - n_queues_per_port = rte_sched_port_queues_per_port(port); + n_subport_pipe_queues = rte_sched_subport_pipe_queues(subport); /* Free enqueued mbufs */ - for (qindex = 0; qindex < n_queues_per_port; qindex++) { - struct rte_mbuf **mbufs = rte_sched_port_qbase(port, qindex); - uint16_t qsize = rte_sched_port_qsize(port, qindex); + for (qindex = 0; qindex < n_subport_pipe_queues; qindex++) { + struct rte_mbuf **mbufs = + rte_sched_subport_pipe_qbase(subport, qindex); + uint16_t qsize = rte_sched_subport_pipe_qsize(port, subport, qindex); if (qsize != 0) { - struct rte_sched_queue *queue = port->queue + qindex; + struct rte_sched_queue *queue = subport->queue + qindex; uint16_t qr = queue->qr & (qsize - 1); uint16_t qw = queue->qw & (qsize - 1); @@ -904,7 +778,21 @@ rte_sched_port_free(struct rte_sched_port *port) } } - rte_bitmap_free(port->bmp); + rte_bitmap_free(subport->bmp); +} + +void +rte_sched_port_free(struct rte_sched_port *port) +{ + uint32_t i; + + /* Check user parameters */ + if (port == NULL) + return; + + for (i = 0; i < port->n_subports_per_port; i++) + rte_sched_subport_free(port, port->subports[i]); + rte_free(port); } -- 2.21.0
Add pipes configuration from the port level to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 388 ++++++++++++++++++++++++++++++----- 1 file changed, 332 insertions(+), 56 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 952e449f7..60dfc6232 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -550,24 +550,91 @@ rte_sched_port_get_array_base(struct rte_sched_port_params *params, enum rte_sch return base; } -uint32_t -rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params) +static uint32_t +rte_sched_subport_get_array_base(struct rte_sched_subport_params *params, + enum rte_sched_subport_array array) { - uint32_t size0, size1; - int status; + uint32_t n_pipes_per_subport = params->n_pipes_per_subport_enabled; + uint32_t n_subport_pipe_queues = + RTE_SCHED_QUEUES_PER_PIPE * n_pipes_per_subport; - status = rte_sched_port_check_params(params); - if (status != 0) { - RTE_LOG(NOTICE, SCHED, - "Port scheduler params check failed (%d)\n", status); + uint32_t size_pipe = n_pipes_per_subport * sizeof(struct rte_sched_pipe); + uint32_t size_queue = + n_subport_pipe_queues * sizeof(struct rte_sched_queue); + uint32_t size_queue_extra + = n_subport_pipe_queues * sizeof(struct rte_sched_queue_extra); + uint32_t size_pipe_profiles = params->n_max_pipe_profiles * + sizeof(struct rte_sched_pipe_profile); + uint32_t size_bmp_array = + rte_bitmap_get_memory_footprint(n_subport_pipe_queues); + uint32_t size_per_pipe_queue_array, size_queue_array; - return 0; + uint32_t base, i; + + size_per_pipe_queue_array = 0; + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + if (i < RTE_SCHED_TRAFFIC_CLASS_BE) + size_per_pipe_queue_array += + params->qsize[i] * sizeof(struct rte_mbuf *); + else + size_per_pipe_queue_array += RTE_SCHED_MAX_QUEUES_PER_TC * + params->qsize[i] * sizeof(struct rte_mbuf *); } + size_queue_array = n_pipes_per_subport * size_per_pipe_queue_array; - size0 = sizeof(struct rte_sched_port); - size1 = rte_sched_port_get_array_base(params, e_RTE_SCHED_PORT_ARRAY_TOTAL); + base = 0; - return size0 + size1; + if (array == e_RTE_SCHED_SUBPORT_ARRAY_PIPE) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_pipe); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_QUEUE) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_queue); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_EXTRA) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_queue_extra); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_PIPE_PROFILES) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_pipe_profiles); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_BMP_ARRAY) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_bmp_array); + + if (array == e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_ARRAY) + return base; + base += RTE_CACHE_LINE_ROUNDUP(size_queue_array); + + return base; +} + +static void +rte_sched_subport_config_qsize(struct rte_sched_subport *subport) +{ + uint32_t i; + + subport->qsize_add[0] = 0; + + /* Strict prority traffic class */ + for (i = 1; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) + subport->qsize_add[i] = subport->qsize_add[i-1] + subport->qsize[i-1]; + + /* Best-effort traffic class */ + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 1] = + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE] + + subport->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 2] = + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 1] + + subport->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 3] = + subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 2] + + subport->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; + + subport->qsize_sum = subport->qsize_add[RTE_SCHED_TRAFFIC_CLASS_BE + 3] + + subport->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]; } static void @@ -679,6 +746,126 @@ rte_sched_pipe_profile_convert(struct rte_sched_port *port, dst->wrr_cost[3] = (uint8_t) wrr_cost[3]; } +static int +rte_sched_subport_check_params(struct rte_sched_subport_params *params, + uint32_t n_max_pipes_per_subport, + uint32_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; + } + + /* qsize: if non-zero, power of 2, + * no bigger than 32K (due to 16-bit read/write pointers) + */ + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + uint16_t qsize = params->qsize[i]; + + if (qsize != 0 && !rte_is_power_of_2(qsize)) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for qsize\n", __func__); + return -EINVAL; + } + } + + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + uint32_t tc_rate = params->tc_rate[i]; + uint16_t qsize = params->qsize[i]; + + if ((qsize == 0 && tc_rate != 0) || + (qsize != 0 && tc_rate == 0) || + (tc_rate > params->tb_rate)) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for tc rate\n", __func__); + return -EINVAL; + } + } + + if (params->qsize[RTE_SCHED_TRAFFIC_CLASS_BE] == 0 || + params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE] == 0) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect qsize or 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; + } + + /* n_pipes_per_subport: non-zero, power of 2 */ + if (params->n_pipes_per_subport_enabled == 0 || + params->n_pipes_per_subport_enabled > n_max_pipes_per_subport || + !rte_is_power_of_2(params->n_pipes_per_subport_enabled)) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for pipes number\n", __func__); + return -EINVAL; + } + + /* pipe_profiles and n_pipe_profiles */ + if (params->pipe_profiles == NULL || + params->n_pipe_profiles == 0 || + params->n_max_pipe_profiles == 0 || + params->n_pipe_profiles > params->n_max_pipe_profiles) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for pipe profiles\n", __func__); + return -EINVAL; + } + + for (i = 0; i < params->n_pipe_profiles; i++) { + struct rte_sched_pipe_params *p = params->pipe_profiles + i; + int status; + + status = pipe_profile_check(p, rate, ¶ms->qsize[0]); + if (status != 0) { + RTE_LOG(ERR, SCHED, + "%s: Pipe profile check failed(%d)\n", __func__, status); + return -EINVAL; + } + } + + return 0; +} + +uint32_t +rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params) +{ + uint32_t size0, size1; + int status; + + status = rte_sched_port_check_params(params); + if (status != 0) { + RTE_LOG(NOTICE, SCHED, + "Port scheduler params check failed (%d)\n", status); + + return 0; + } + + size0 = sizeof(struct rte_sched_port); + size1 = rte_sched_port_get_array_base(params, + e_RTE_SCHED_PORT_ARRAY_TOTAL); + + return size0 + size1; +} + struct rte_sched_port * rte_sched_port_config(struct rte_sched_port_params *params) { @@ -799,7 +986,7 @@ rte_sched_port_free(struct rte_sched_port *port) static void rte_sched_port_log_subport_config(struct rte_sched_port *port, uint32_t i) { - struct rte_sched_subport *s = port->subport + i; + struct rte_sched_subport *s = port->subports[i]; RTE_LOG(DEBUG, SCHED, "Low level config for subport %u:\n" " Token bucket: period = %u, credits per period = %u, size = %u\n" @@ -834,72 +1021,78 @@ rte_sched_port_log_subport_config(struct rte_sched_port *port, uint32_t i) s->tc_ov_wm_max); } +static void +rte_sched_free_memory(struct rte_sched_port *port, uint32_t n_subports) +{ + uint32_t i; + + for (i = 0; i < n_subports; i++) { + struct rte_sched_subport *subport = port->subports[i]; + + rte_sched_subport_free(port, subport); + } + + rte_free(port); +} + int rte_sched_subport_config(struct rte_sched_port *port, uint32_t subport_id, struct rte_sched_subport_params *params) { - struct rte_sched_subport *s; - uint32_t i; + struct rte_sched_subport *s = NULL; + uint32_t n_subports = subport_id; + uint32_t n_subport_pipe_queues, i; + uint32_t size0, size1, bmp_mem_size; + int status; /* Check user parameters */ if (port == NULL) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for parameter port\n", __func__); - return -EINVAL; + return 0; } if (subport_id >= port->n_subports_per_port) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for subport id\n", __func__); - return -EINVAL; - } - if (params == NULL) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for parameter params\n", __func__); + rte_sched_free_memory(port, n_subports); return -EINVAL; } - if (params->tb_rate == 0 || params->tb_rate > port->rate) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tb rate\n", __func__); - return -EINVAL; - } + status = rte_sched_subport_check_params(params, + port->n_pipes_per_subport, + port->rate); + if (status != 0) { + RTE_LOG(NOTICE, SCHED, + "%s: Port scheduler params check failed (%d)\n", + __func__, status); - if (params->tb_size == 0) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tb size\n", __func__); + rte_sched_free_memory(port, n_subports); return -EINVAL; } - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - uint32_t tc_rate = params->tc_rate[i]; - uint16_t qsize = port->qsize[i]; + /* Determine the amount of memory to allocate */ + size0 = sizeof(struct rte_sched_subport); + size1 = rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_TOTAL); - if ((qsize == 0 && tc_rate != 0) || - (qsize != 0 && tc_rate == 0) || - (tc_rate > params->tb_rate)) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tc rate\n", __func__); - return -EINVAL; - } - } - - if (port->qsize[RTE_SCHED_TRAFFIC_CLASS_BE] == 0 || - params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE] == 0) { + /* Allocate memory to store the data structures */ + s = rte_zmalloc_socket("subport_params", size0 + size1, + RTE_CACHE_LINE_SIZE, port->socket); + if (s == NULL) { RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tc rate(best effort)\n", __func__); - return -EINVAL; - } + "%s: Memory allocation fails\n", __func__); - if (params->tc_period == 0) { - RTE_LOG(ERR, SCHED, - "%s: Incorrect value for tc period\n", __func__); - return -EINVAL; + rte_sched_free_memory(port, n_subports); + return -ENOMEM; } - s = port->subport + subport_id; + n_subports++; + + /* Port */ + port->subports[subport_id] = s; /* Token Bucket (TB) */ if (params->tb_rate == port->rate) { @@ -919,26 +1112,109 @@ rte_sched_subport_config(struct rte_sched_port *port, /* Traffic Classes (TCs) */ s->tc_period = rte_sched_time_ms_to_bytes(params->tc_period, port->rate); for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - if (port->qsize[i]) + if (params->qsize[i]) s->tc_credits_per_period[i] = rte_sched_time_ms_to_bytes(params->tc_period, - params->tc_rate[i]); - + params->tc_rate[i]); } s->tc_time = port->time + s->tc_period; for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - if (port->qsize[i]) + if (params->qsize[i]) s->tc_credits[i] = s->tc_credits_per_period[i]; + /* compile time checks */ + RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS == 0); + RTE_BUILD_BUG_ON(RTE_SCHED_PORT_N_GRINDERS & + (RTE_SCHED_PORT_N_GRINDERS - 1)); + + /* User parameters */ + s->n_pipes_per_subport_enabled = params->n_pipes_per_subport_enabled; + memcpy(s->qsize, params->qsize, sizeof(params->qsize)); + s->n_pipe_profiles = params->n_pipe_profiles; + s->n_max_pipe_profiles = params->n_max_pipe_profiles; + +#ifdef RTE_SCHED_RED + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + uint32_t j; + + for (j = 0; j < RTE_COLORS; j++) { + /* if min/max are both zero, then RED is disabled */ + if ((params->red_params[i][j].min_th | + params->red_params[i][j].max_th) == 0) { + continue; + } + + if (rte_red_config_init(&s->red_config[i][j], + params->red_params[i][j].wq_log2, + params->red_params[i][j].min_th, + params->red_params[i][j].max_th, + params->red_params[i][j].maxp_inv) != 0) { + rte_sched_free_memory(port, n_subports); + + RTE_LOG(NOTICE, SCHED, + "%s: RED configuration init fails\n", __func__); + return -EINVAL; + } + } + } +#endif + + /* Scheduling loop detection */ + s->pipe_loop = RTE_SCHED_PIPE_INVALID; + s->pipe_exhaustion = 0; + + /* Grinders */ + s->busy_grinders = 0; + + /* Queue base calculation */ + rte_sched_subport_config_qsize(s); + + /* Large data structures */ + s->pipe = (struct rte_sched_pipe *) + (s->memory + rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_PIPE)); + s->queue = (struct rte_sched_queue *) + (s->memory + rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE)); + s->queue_extra = (struct rte_sched_queue_extra *) + (s->memory + rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_EXTRA)); + s->pipe_profiles = (struct rte_sched_pipe_profile *) + (s->memory + rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_PIPE_PROFILES)); + s->bmp_array = s->memory + rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_BMP_ARRAY); + s->queue_array = (struct rte_mbuf **) + (s->memory + rte_sched_subport_get_array_base(params, + e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_ARRAY)); + + /* Bitmap */ + n_subport_pipe_queues = rte_sched_subport_pipe_queues(s); + bmp_mem_size = rte_bitmap_get_memory_footprint(n_subport_pipe_queues); + s->bmp = rte_bitmap_init(n_subport_pipe_queues, s->bmp_array, + bmp_mem_size); + if (s->bmp == NULL) { + RTE_LOG(ERR, SCHED, + "%s: Subport bitmap init error\n", __func__); + + rte_sched_free_memory(port, n_subports); + return -EINVAL; + } + + for (i = 0; i < RTE_SCHED_PORT_N_GRINDERS; i++) + s->grinder_base_bmp_pos[i] = RTE_SCHED_PIPE_INVALID; + +#ifdef RTE_SCHED_SUBPORT_TC_OV /* TC oversubscription */ s->tc_ov_wm_min = port->mtu; s->tc_ov_wm_max = rte_sched_time_ms_to_bytes(params->tc_period, - port->pipe_tc_be_rate_max); + s->pipe_tc_be_rate_max); s->tc_ov_wm = s->tc_ov_wm_max; s->tc_ov_period_id = 0; s->tc_ov = 0; s->tc_ov_n = 0; s->tc_ov_rate = 0; +#endif rte_sched_port_log_subport_config(port, subport_id); -- 2.21.0
Modify pipe level functions to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 103 +++++++++++++++++-------- lib/librte_sched/rte_sched.h | 7 +- lib/librte_sched/rte_sched_version.map | 2 +- 3 files changed, 76 insertions(+), 36 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 60dfc6232..6b6219e45 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -638,9 +638,9 @@ rte_sched_subport_config_qsize(struct rte_sched_subport *subport) } static void -rte_sched_port_log_pipe_profile(struct rte_sched_port *port, uint32_t i) +rte_sched_port_log_pipe_profile(struct rte_sched_subport *subport, uint32_t i) { - struct rte_sched_pipe_profile *p = port->pipe_profiles + i; + struct rte_sched_pipe_profile *p = subport->pipe_profiles + i; RTE_LOG(DEBUG, SCHED, "Low level config for pipe profile %u:\n" " Token bucket: period = %u, credits per period = %u, size = %u\n" @@ -689,7 +689,7 @@ rte_sched_time_ms_to_bytes(uint32_t time_ms, uint32_t rate) } static void -rte_sched_pipe_profile_convert(struct rte_sched_port *port, +rte_sched_pipe_profile_convert(struct rte_sched_subport *subport, struct rte_sched_pipe_params *src, struct rte_sched_pipe_profile *dst, uint32_t rate) @@ -718,7 +718,7 @@ rte_sched_pipe_profile_convert(struct rte_sched_port *port, rate); for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - if (port->qsize[i]) + if (subport->qsize[i]) dst->tc_credits_per_period[i] = rte_sched_time_ms_to_bytes(src->tc_period, src->tc_rate[i]); @@ -746,6 +746,30 @@ rte_sched_pipe_profile_convert(struct rte_sched_port *port, dst->wrr_cost[3] = (uint8_t) wrr_cost[3]; } +static void +rte_sched_subport_config_pipe_profile_table(struct rte_sched_subport *subport, + struct rte_sched_subport_params *params, uint32_t rate) +{ + uint32_t i; + + for (i = 0; i < subport->n_pipe_profiles; i++) { + struct rte_sched_pipe_params *src = params->pipe_profiles + i; + struct rte_sched_pipe_profile *dst = subport->pipe_profiles + i; + + rte_sched_pipe_profile_convert(subport, src, dst, rate); + rte_sched_port_log_pipe_profile(subport, i); + } + + subport->pipe_tc_be_rate_max = 0; + for (i = 0; i < subport->n_pipe_profiles; i++) { + struct rte_sched_pipe_params *src = params->pipe_profiles + i; + uint32_t pipe_tc_be_rate = src->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; + + if (subport->pipe_tc_be_rate_max < pipe_tc_be_rate) + subport->pipe_tc_be_rate_max = pipe_tc_be_rate; + } +} + static int rte_sched_subport_check_params(struct rte_sched_subport_params *params, uint32_t n_max_pipes_per_subport, @@ -1188,6 +1212,9 @@ rte_sched_subport_config(struct rte_sched_port *port, (s->memory + rte_sched_subport_get_array_base(params, e_RTE_SCHED_SUBPORT_ARRAY_QUEUE_ARRAY)); + /* Pipe profile table */ + rte_sched_subport_config_pipe_profile_table(s, params, port->rate); + /* Bitmap */ n_subport_pipe_queues = rte_sched_subport_pipe_queues(s); bmp_mem_size = rte_bitmap_get_memory_footprint(n_subport_pipe_queues); @@ -1230,6 +1257,7 @@ rte_sched_pipe_config(struct rte_sched_port *port, struct rte_sched_subport *s; struct rte_sched_pipe *p; struct rte_sched_pipe_profile *params; + uint32_t n_subports = subport_id + 1; uint32_t deactivate, profile, i; /* Check user parameters */ @@ -1245,34 +1273,32 @@ rte_sched_pipe_config(struct rte_sched_port *port, if (subport_id >= port->n_subports_per_port) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for parameter subport id\n", __func__); + + rte_sched_free_memory(port, n_subports); return -EINVAL; } - if (pipe_id >= port->n_pipes_per_subport) { + s = port->subports[subport_id]; + if (pipe_id >= s->n_pipes_per_subport_enabled) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for parameter pipe id\n", __func__); + + rte_sched_free_memory(port, n_subports); return -EINVAL; } - if (!deactivate && profile >= port->n_pipe_profiles) { + if (!deactivate && profile >= s->n_pipe_profiles) { RTE_LOG(ERR, SCHED, "%s: Incorrect value for parameter pipe profile\n", __func__); - return -EINVAL; - } - /* Check that subport configuration is valid */ - s = port->subport + subport_id; - if (s->tb_period == 0) { - RTE_LOG(ERR, SCHED, - "%s: Subport configuration invalid\n", __func__); + rte_sched_free_memory(port, n_subports); return -EINVAL; } - p = port->pipe + (subport_id * port->n_pipes_per_subport + pipe_id); - /* Handle the case when pipe already has a valid configuration */ + p = s->pipe + pipe_id; if (p->tb_time) { - params = port->pipe_profiles + p->profile; + params = s->pipe_profiles + p->profile; double subport_tc_be_rate = (double) s->tc_credits_per_period[RTE_SCHED_TRAFFIC_CLASS_BE] @@ -1302,7 +1328,7 @@ rte_sched_pipe_config(struct rte_sched_port *port, /* Apply the new pipe configuration */ p->profile = profile; - params = port->pipe_profiles + p->profile; + params = s->pipe_profiles + p->profile; /* Token Bucket (TB) */ p->tb_time = port->time; @@ -1312,7 +1338,7 @@ rte_sched_pipe_config(struct rte_sched_port *port, p->tc_time = port->time + params->tc_period; for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - if (port->qsize[i]) + if (s->qsize[i]) p->tc_credits[i] = params->tc_credits_per_period[i]; { @@ -1342,10 +1368,12 @@ rte_sched_pipe_config(struct rte_sched_port *port, } int -rte_sched_port_pipe_profile_add(struct rte_sched_port *port, +rte_sched_subport_pipe_profile_add(struct rte_sched_port *port, + uint32_t subport_id, struct rte_sched_pipe_params *params, uint32_t *pipe_profile_id) { + struct rte_sched_subport *s; struct rte_sched_pipe_profile *pp; uint32_t i; int status; @@ -1357,40 +1385,49 @@ rte_sched_port_pipe_profile_add(struct rte_sched_port *port, return -EINVAL; } - /* Pipe profiles not exceeds the max limit */ - if (port->n_pipe_profiles >= port->n_max_pipe_profiles) { + /* Subport id not exceeds the max limit */ + if (subport_id > port->n_subports_per_port) { + RTE_LOG(ERR, SCHED, + "%s: Incorrect value for subport id\n", __func__); + return -EINVAL; + } + + s = port->subports[subport_id]; + + /* Pipe profiles exceeds the max limit */ + if (s->n_pipe_profiles >= s->n_max_pipe_profiles) { RTE_LOG(ERR, SCHED, "%s: Number of pipe profiles exceeds the max limit\n", __func__); return -EINVAL; } /* Pipe params */ - status = pipe_profile_check(params, port->rate, &port->qsize[0]); + status = pipe_profile_check(params, port->rate, &s->qsize[0]); if (status != 0) { RTE_LOG(ERR, SCHED, "%s: Pipe profile check failed(%d)\n", __func__, status); return -EINVAL; } - pp = &port->pipe_profiles[port->n_pipe_profiles]; - rte_sched_pipe_profile_convert(port, params, pp, port->rate); + pp = &s->pipe_profiles[s->n_pipe_profiles]; + rte_sched_pipe_profile_convert(s, params, pp, port->rate); - /* Pipe profile not exists */ - for (i = 0; i < port->n_pipe_profiles; i++) - if (memcmp(port->pipe_profiles + i, pp, sizeof(*pp)) == 0) { + /* Pipe profile should not exists */ + for (i = 0; i < s->n_pipe_profiles; i++) + if (memcmp(s->pipe_profiles + i, pp, sizeof(*pp)) == 0) { RTE_LOG(ERR, SCHED, - "%s: Pipe profile doesn't exist\n", __func__); + "%s: Pipe profile exists\n", __func__); return -EINVAL; } /* Pipe profile commit */ - *pipe_profile_id = port->n_pipe_profiles; - port->n_pipe_profiles++; + *pipe_profile_id = s->n_pipe_profiles; + s->n_pipe_profiles++; - if (port->pipe_tc_be_rate_max < params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]) - port->pipe_tc_be_rate_max = params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; + if (s->pipe_tc_be_rate_max < params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]) + s->pipe_tc_be_rate_max = params->tc_rate[RTE_SCHED_TRAFFIC_CLASS_BE]; - rte_sched_port_log_pipe_profile(port, *pipe_profile_id); + rte_sched_port_log_pipe_profile(s, *pipe_profile_id); return 0; } diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index fbb0e23fa..5001f09ed 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -317,6 +317,8 @@ rte_sched_port_free(struct rte_sched_port *port); * * @param port * Handle to port scheduler instance + * @param subport_id + * Subport ID * @param params * Pipe profile parameters * @param pipe_profile_id @@ -326,7 +328,8 @@ rte_sched_port_free(struct rte_sched_port *port); */ __rte_experimental int -rte_sched_port_pipe_profile_add(struct rte_sched_port *port, +rte_sched_subport_pipe_profile_add(struct rte_sched_port *port, + uint32_t subport_id, struct rte_sched_pipe_params *params, uint32_t *pipe_profile_id); @@ -357,7 +360,7 @@ rte_sched_subport_config(struct rte_sched_port *port, * @param pipe_id * Pipe ID within subport * @param pipe_profile - * ID of port-level pre-configured pipe profile + * ID of subport-level pre-configured pipe profile * @return * 0 upon success, error code otherwise */ diff --git a/lib/librte_sched/rte_sched_version.map b/lib/librte_sched/rte_sched_version.map index 729588794..f33761e63 100644 --- a/lib/librte_sched/rte_sched_version.map +++ b/lib/librte_sched/rte_sched_version.map @@ -33,5 +33,5 @@ DPDK_2.1 { EXPERIMENTAL { global: - rte_sched_port_pipe_profile_add; + rte_sched_subport_pipe_profile_add; }; -- 2.21.0
Modify scheduler packet enqueue operation of the scheduler to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 287 ++++++++++++++++++++++------------- 1 file changed, 178 insertions(+), 109 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 6b6219e45..f59519b00 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -281,16 +281,6 @@ enum rte_sched_subport_array { e_RTE_SCHED_SUBPORT_ARRAY_TOTAL, }; -#ifdef RTE_SCHED_COLLECT_STATS - -static inline uint32_t -rte_sched_port_queues_per_subport(struct rte_sched_port *port) -{ - return RTE_SCHED_QUEUES_PER_PIPE * port->n_pipes_per_subport; -} - -#endif - static inline uint32_t rte_sched_subport_pipe_queues(struct rte_sched_subport *subport) { @@ -1440,10 +1430,11 @@ rte_sched_port_qindex(struct rte_sched_port *port, 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) | - ((rte_sched_port_pipe_queue(port, traffic_class) + queue) & - (RTE_SCHED_QUEUES_PER_PIPE - 1)); + (port->n_pipes_per_subport_log2 + 4)) | + ((pipe & + (port->subports[subport]->n_pipes_per_subport_enabled - 1)) << 4) | + ((rte_sched_port_pipe_queue(port, traffic_class) + queue) & + (RTE_SCHED_QUEUES_PER_PIPE - 1)); } void @@ -1468,7 +1459,8 @@ rte_sched_port_pkt_read_tree_path(struct rte_sched_port *port, uint32_t queue_id = rte_mbuf_sched_queue_get(pkt); *subport = queue_id >> (port->n_pipes_per_subport_log2 + 4); - *pipe = (queue_id >> 4) & (port->n_pipes_per_subport - 1); + *pipe = (queue_id >> 4) & + (port->subports[*subport]->n_pipes_per_subport_enabled - 1); *traffic_class = rte_sched_port_pipe_tc(port, queue_id); *queue = rte_sched_port_tc_queue(port, queue_id); } @@ -1512,7 +1504,7 @@ rte_sched_subport_read_stats(struct rte_sched_port *port, return -EINVAL; } - s = port->subport + subport_id; + s = port->subports[subport_id]; /* Copy subport stats and clear */ memcpy(stats, &s->stats, sizeof(struct rte_sched_subport_stats)); @@ -1585,43 +1577,50 @@ rte_sched_port_queue_is_empty(struct rte_sched_port *port, uint32_t qindex) #ifdef RTE_SCHED_COLLECT_STATS static inline void -rte_sched_port_update_subport_stats(struct rte_sched_port *port, uint32_t qindex, struct rte_mbuf *pkt) +rte_sched_port_update_subport_stats(struct rte_sched_port *port, + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt) { - struct rte_sched_subport *s = port->subport + (qindex / rte_sched_port_queues_per_subport(port)); uint32_t tc_index = rte_sched_port_pipe_tc(port, qindex); uint32_t pkt_len = pkt->pkt_len; - s->stats.n_pkts_tc[tc_index] += 1; - s->stats.n_bytes_tc[tc_index] += pkt_len; + subport->stats.n_pkts_tc[tc_index] += 1; + subport->stats.n_bytes_tc[tc_index] += pkt_len; } #ifdef RTE_SCHED_RED static inline void rte_sched_port_update_subport_stats_on_drop(struct rte_sched_port *port, - uint32_t qindex, - struct rte_mbuf *pkt, uint32_t red) + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt, + uint32_t red) #else static inline void rte_sched_port_update_subport_stats_on_drop(struct rte_sched_port *port, - uint32_t qindex, - struct rte_mbuf *pkt, __rte_unused uint32_t red) + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt, + __rte_unused uint32_t red) #endif { - struct rte_sched_subport *s = port->subport + (qindex / rte_sched_port_queues_per_subport(port)); uint32_t tc_index = rte_sched_port_pipe_tc(port, qindex); uint32_t pkt_len = pkt->pkt_len; - s->stats.n_pkts_tc_dropped[tc_index] += 1; - s->stats.n_bytes_tc_dropped[tc_index] += pkt_len; + subport->stats.n_pkts_tc_dropped[tc_index] += 1; + subport->stats.n_bytes_tc_dropped[tc_index] += pkt_len; #ifdef RTE_SCHED_RED - s->stats.n_pkts_red_dropped[tc_index] += red; + subport->stats.n_pkts_red_dropped[tc_index] += red; #endif } static inline void -rte_sched_port_update_queue_stats(struct rte_sched_port *port, uint32_t qindex, struct rte_mbuf *pkt) +rte_sched_port_update_queue_stats(struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt) { - struct rte_sched_queue_extra *qe = port->queue_extra + qindex; + struct rte_sched_queue_extra *qe = subport->queue_extra + qindex; uint32_t pkt_len = pkt->pkt_len; qe->stats.n_pkts += 1; @@ -1630,17 +1629,19 @@ rte_sched_port_update_queue_stats(struct rte_sched_port *port, uint32_t qindex, #ifdef RTE_SCHED_RED static inline void -rte_sched_port_update_queue_stats_on_drop(struct rte_sched_port *port, - uint32_t qindex, - struct rte_mbuf *pkt, uint32_t red) +rte_sched_port_update_queue_stats_on_drop(struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt, + uint32_t red) #else static inline void -rte_sched_port_update_queue_stats_on_drop(struct rte_sched_port *port, - uint32_t qindex, - struct rte_mbuf *pkt, __rte_unused uint32_t red) +rte_sched_port_update_queue_stats_on_drop(struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf *pkt, + __rte_unused uint32_t red) #endif { - struct rte_sched_queue_extra *qe = port->queue_extra + qindex; + struct rte_sched_queue_extra *qe = subport->queue_extra + qindex; uint32_t pkt_len = pkt->pkt_len; qe->stats.n_pkts_dropped += 1; @@ -1655,7 +1656,11 @@ rte_sched_port_update_queue_stats_on_drop(struct rte_sched_port *port, #ifdef RTE_SCHED_RED static inline int -rte_sched_port_red_drop(struct rte_sched_port *port, struct rte_mbuf *pkt, uint32_t qindex, uint16_t qlen) +rte_sched_port_red_drop(struct rte_sched_port *port, + struct rte_sched_subport *subport, + struct rte_mbuf *pkt, + uint32_t qindex, + uint16_t qlen) { struct rte_sched_queue_extra *qe; struct rte_red_config *red_cfg; @@ -1665,12 +1670,12 @@ rte_sched_port_red_drop(struct rte_sched_port *port, struct rte_mbuf *pkt, uint3 tc_index = rte_sched_port_pipe_tc(port, qindex); color = rte_sched_port_pkt_read_color(pkt); - red_cfg = &port->red_config[tc_index][color]; + red_cfg = &subport->red_config[tc_index][color]; if ((red_cfg->min_th | red_cfg->max_th) == 0) return 0; - qe = port->queue_extra + qindex; + qe = subport->queue_extra + qindex; red = &qe->red; return rte_red_enqueue(red_cfg, red, qlen, port->time); @@ -1687,7 +1692,14 @@ rte_sched_port_set_queue_empty_timestamp(struct rte_sched_port *port, uint32_t q #else -#define rte_sched_port_red_drop(port, pkt, qindex, qlen) 0 +static inline int rte_sched_port_red_drop(struct rte_sched_port *port __rte_unused, + struct rte_sched_subport *subport __rte_unused, + struct rte_mbuf *pkt __rte_unused, + uint32_t qindex __rte_unused, + uint16_t qlen __rte_unused) +{ + return 0; +} #define rte_sched_port_set_queue_empty_timestamp(port, qindex) @@ -1722,63 +1734,79 @@ debug_check_queue_slab(struct rte_sched_port *port, uint32_t bmp_pos, #endif /* RTE_SCHED_DEBUG */ +static inline struct rte_sched_subport * +rte_sched_port_subport(struct rte_sched_port *port, + struct rte_mbuf *pkt) +{ + uint32_t queue_id = rte_mbuf_sched_queue_get(pkt); + uint32_t subport_id = queue_id >> (port->n_pipes_per_subport_log2 + 4); + + return port->subports[subport_id]; +} + static inline uint32_t -rte_sched_port_enqueue_qptrs_prefetch0(struct rte_sched_port *port, - struct rte_mbuf *pkt) +rte_sched_port_enqueue_qptrs_prefetch0(struct rte_sched_subport *subport, + struct rte_mbuf *pkt, uint32_t subport_qmask) { struct rte_sched_queue *q; #ifdef RTE_SCHED_COLLECT_STATS struct rte_sched_queue_extra *qe; #endif uint32_t qindex = rte_mbuf_sched_queue_get(pkt); + uint32_t subport_queue_id = subport_qmask & qindex; - q = port->queue + qindex; + q = subport->queue + subport_queue_id; rte_prefetch0(q); #ifdef RTE_SCHED_COLLECT_STATS - qe = port->queue_extra + qindex; + qe = subport->queue_extra + subport_queue_id; rte_prefetch0(qe); #endif - return qindex; + return subport_queue_id; } static inline void rte_sched_port_enqueue_qwa_prefetch0(struct rte_sched_port *port, - uint32_t qindex, struct rte_mbuf **qbase) + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf **qbase) { struct rte_sched_queue *q; struct rte_mbuf **q_qw; uint16_t qsize; - q = port->queue + qindex; - qsize = rte_sched_port_qsize(port, qindex); + q = subport->queue + qindex; + qsize = rte_sched_subport_pipe_qsize(port, subport, qindex); q_qw = qbase + (q->qw & (qsize - 1)); rte_prefetch0(q_qw); - rte_bitmap_prefetch0(port->bmp, qindex); + rte_bitmap_prefetch0(subport->bmp, qindex); } static inline int -rte_sched_port_enqueue_qwa(struct rte_sched_port *port, uint32_t qindex, - struct rte_mbuf **qbase, struct rte_mbuf *pkt) +rte_sched_port_enqueue_qwa(struct rte_sched_port *port, + struct rte_sched_subport *subport, + uint32_t qindex, + struct rte_mbuf **qbase, + struct rte_mbuf *pkt) { struct rte_sched_queue *q; uint16_t qsize; uint16_t qlen; - q = port->queue + qindex; - qsize = rte_sched_port_qsize(port, qindex); + q = subport->queue + qindex; + qsize = rte_sched_subport_pipe_qsize(port, subport, qindex); qlen = q->qw - q->qr; /* Drop the packet (and update drop stats) when queue is full */ - if (unlikely(rte_sched_port_red_drop(port, pkt, qindex, qlen) || + if (unlikely(rte_sched_port_red_drop(port, subport, pkt, qindex, qlen) || (qlen >= qsize))) { rte_pktmbuf_free(pkt); #ifdef RTE_SCHED_COLLECT_STATS - rte_sched_port_update_subport_stats_on_drop(port, qindex, pkt, - qlen < qsize); - rte_sched_port_update_queue_stats_on_drop(port, qindex, pkt, - qlen < qsize); + rte_sched_port_update_subport_stats_on_drop(port, subport, + qindex, pkt, qlen < qsize); + rte_sched_port_update_queue_stats_on_drop(subport, qindex, pkt, + qlen < qsize); #endif return 0; } @@ -1787,13 +1815,13 @@ rte_sched_port_enqueue_qwa(struct rte_sched_port *port, uint32_t qindex, qbase[q->qw & (qsize - 1)] = pkt; q->qw++; - /* Activate queue in the port bitmap */ - rte_bitmap_set(port->bmp, qindex); + /* Activate queue in the subport bitmap */ + rte_bitmap_set(subport->bmp, qindex); /* Statistics */ #ifdef RTE_SCHED_COLLECT_STATS - rte_sched_port_update_subport_stats(port, qindex, pkt); - rte_sched_port_update_queue_stats(port, qindex, pkt); + rte_sched_port_update_subport_stats(port, subport, qindex, pkt); + rte_sched_port_update_queue_stats(subport, qindex, pkt); #endif return 1; @@ -1821,17 +1849,22 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, *pkt30, *pkt31, *pkt_last; struct rte_mbuf **q00_base, **q01_base, **q10_base, **q11_base, **q20_base, **q21_base, **q30_base, **q31_base, **q_last_base; + struct rte_sched_subport *subport00, *subport01, *subport10, *subport11, + *subport20, *subport21, *subport30, *subport31, *subport_last; uint32_t q00, q01, q10, q11, q20, q21, q30, q31, q_last; uint32_t r00, r01, r10, r11, r20, r21, r30, r31, r_last; + uint32_t subport_qmask; uint32_t result, i; result = 0; + subport_qmask = (1 << (port->n_pipes_per_subport_log2 + 4)) - 1; /* * Less then 6 input packets available, which is not enough to * feed the pipeline */ if (unlikely(n_pkts < 6)) { + struct rte_sched_subport *subports[5]; struct rte_mbuf **q_base[5]; uint32_t q[5]; @@ -1839,22 +1872,26 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, for (i = 0; i < n_pkts; i++) rte_prefetch0(pkts[i]); + /* Prefetch the subport structure for each packet */ + for (i = 0; i < n_pkts; i++) + subports[i] = rte_sched_port_subport(port, pkts[i]); + /* Prefetch the queue structure for each queue */ for (i = 0; i < n_pkts; i++) - q[i] = rte_sched_port_enqueue_qptrs_prefetch0(port, - pkts[i]); + q[i] = rte_sched_port_enqueue_qptrs_prefetch0(subports[i], + pkts[i], subport_qmask); /* Prefetch the write pointer location of each queue */ for (i = 0; i < n_pkts; i++) { - q_base[i] = rte_sched_port_qbase(port, q[i]); - rte_sched_port_enqueue_qwa_prefetch0(port, q[i], - q_base[i]); + q_base[i] = rte_sched_subport_pipe_qbase(subports[i], q[i]); + rte_sched_port_enqueue_qwa_prefetch0(port, subports[i], + q[i], q_base[i]); } /* Write each packet to its queue */ for (i = 0; i < n_pkts; i++) - result += rte_sched_port_enqueue_qwa(port, q[i], - q_base[i], pkts[i]); + result += rte_sched_port_enqueue_qwa(port, subports[i], + q[i], q_base[i], pkts[i]); return result; } @@ -1870,21 +1907,29 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, rte_prefetch0(pkt10); rte_prefetch0(pkt11); - q20 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt20); - q21 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt21); + subport20 = rte_sched_port_subport(port, pkt20); + subport21 = rte_sched_port_subport(port, pkt21); + q20 = rte_sched_port_enqueue_qptrs_prefetch0(subport20, + pkt20, subport_qmask); + q21 = rte_sched_port_enqueue_qptrs_prefetch0(subport21, + pkt21, subport_qmask); pkt00 = pkts[4]; pkt01 = pkts[5]; rte_prefetch0(pkt00); rte_prefetch0(pkt01); - q10 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt10); - q11 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt11); + subport10 = rte_sched_port_subport(port, pkt10); + subport11 = rte_sched_port_subport(port, pkt11); + q10 = rte_sched_port_enqueue_qptrs_prefetch0(subport10, + pkt10, subport_qmask); + q11 = rte_sched_port_enqueue_qptrs_prefetch0(subport11, + pkt11, subport_qmask); - q20_base = rte_sched_port_qbase(port, q20); - q21_base = rte_sched_port_qbase(port, q21); - rte_sched_port_enqueue_qwa_prefetch0(port, q20, q20_base); - rte_sched_port_enqueue_qwa_prefetch0(port, q21, q21_base); + q20_base = rte_sched_subport_pipe_qbase(subport20, q20); + q21_base = rte_sched_subport_pipe_qbase(subport21, q21); + rte_sched_port_enqueue_qwa_prefetch0(port, subport20, q20, q20_base); + rte_sched_port_enqueue_qwa_prefetch0(port, subport21, q21, q21_base); /* Run the pipeline */ for (i = 6; i < (n_pkts & (~1)); i += 2) { @@ -1899,6 +1944,10 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, q31 = q21; q20 = q10; q21 = q11; + subport30 = subport20; + subport31 = subport21; + subport20 = subport10; + subport21 = subport11; q30_base = q20_base; q31_base = q21_base; @@ -1908,19 +1957,25 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, rte_prefetch0(pkt00); rte_prefetch0(pkt01); - /* Stage 1: Prefetch queue structure storing queue pointers */ - q10 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt10); - q11 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt11); + /* Stage 1: Prefetch subport and queue structure storing queue pointers */ + subport10 = rte_sched_port_subport(port, pkt10); + subport11 = rte_sched_port_subport(port, pkt11); + q10 = rte_sched_port_enqueue_qptrs_prefetch0(subport10, + pkt10, subport_qmask); + q11 = rte_sched_port_enqueue_qptrs_prefetch0(subport11, + pkt11, subport_qmask); /* Stage 2: Prefetch queue write location */ - q20_base = rte_sched_port_qbase(port, q20); - q21_base = rte_sched_port_qbase(port, q21); - rte_sched_port_enqueue_qwa_prefetch0(port, q20, q20_base); - rte_sched_port_enqueue_qwa_prefetch0(port, q21, q21_base); + q20_base = rte_sched_subport_pipe_qbase(subport20, q20); + q21_base = rte_sched_subport_pipe_qbase(subport21, q21); + rte_sched_port_enqueue_qwa_prefetch0(port, subport20, q20, q20_base); + rte_sched_port_enqueue_qwa_prefetch0(port, subport21, q21, q21_base); /* Stage 3: Write packet to queue and activate queue */ - r30 = rte_sched_port_enqueue_qwa(port, q30, q30_base, pkt30); - r31 = rte_sched_port_enqueue_qwa(port, q31, q31_base, pkt31); + r30 = rte_sched_port_enqueue_qwa(port, subport30, + q30, q30_base, pkt30); + r31 = rte_sched_port_enqueue_qwa(port, subport31, + q31, q31_base, pkt31); result += r30 + r31; } @@ -1932,38 +1987,52 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, pkt_last = pkts[n_pkts - 1]; rte_prefetch0(pkt_last); - q00 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt00); - q01 = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt01); - - q10_base = rte_sched_port_qbase(port, q10); - q11_base = rte_sched_port_qbase(port, q11); - rte_sched_port_enqueue_qwa_prefetch0(port, q10, q10_base); - rte_sched_port_enqueue_qwa_prefetch0(port, q11, q11_base); - - r20 = rte_sched_port_enqueue_qwa(port, q20, q20_base, pkt20); - r21 = rte_sched_port_enqueue_qwa(port, q21, q21_base, pkt21); + subport00 = rte_sched_port_subport(port, pkt00); + subport01 = rte_sched_port_subport(port, pkt01); + q00 = rte_sched_port_enqueue_qptrs_prefetch0(subport00, + pkt00, subport_qmask); + q01 = rte_sched_port_enqueue_qptrs_prefetch0(subport01, + pkt01, subport_qmask); + + q10_base = rte_sched_subport_pipe_qbase(subport10, q10); + q11_base = rte_sched_subport_pipe_qbase(subport11, q11); + rte_sched_port_enqueue_qwa_prefetch0(port, subport10, q10, q10_base); + rte_sched_port_enqueue_qwa_prefetch0(port, subport11, q11, q11_base); + + r20 = rte_sched_port_enqueue_qwa(port, subport20, + q20, q20_base, pkt20); + r21 = rte_sched_port_enqueue_qwa(port, subport21, + q21, q21_base, pkt21); result += r20 + r21; - q_last = rte_sched_port_enqueue_qptrs_prefetch0(port, pkt_last); + subport_last = rte_sched_port_subport(port, pkt_last); + q_last = rte_sched_port_enqueue_qptrs_prefetch0(subport_last, + pkt_last, subport_qmask); - q00_base = rte_sched_port_qbase(port, q00); - q01_base = rte_sched_port_qbase(port, q01); - rte_sched_port_enqueue_qwa_prefetch0(port, q00, q00_base); - rte_sched_port_enqueue_qwa_prefetch0(port, q01, q01_base); + q00_base = rte_sched_subport_pipe_qbase(subport00, q00); + q01_base = rte_sched_subport_pipe_qbase(subport01, q01); + rte_sched_port_enqueue_qwa_prefetch0(port, subport00, q00, q00_base); + rte_sched_port_enqueue_qwa_prefetch0(port, subport01, q01, q01_base); - r10 = rte_sched_port_enqueue_qwa(port, q10, q10_base, pkt10); - r11 = rte_sched_port_enqueue_qwa(port, q11, q11_base, pkt11); + r10 = rte_sched_port_enqueue_qwa(port, subport10, q10, + q10_base, pkt10); + r11 = rte_sched_port_enqueue_qwa(port, subport11, q11, + q11_base, pkt11); result += r10 + r11; - q_last_base = rte_sched_port_qbase(port, q_last); - rte_sched_port_enqueue_qwa_prefetch0(port, q_last, q_last_base); + q_last_base = rte_sched_subport_pipe_qbase(subport_last, q_last); + rte_sched_port_enqueue_qwa_prefetch0(port, subport_last, + q_last, q_last_base); - r00 = rte_sched_port_enqueue_qwa(port, q00, q00_base, pkt00); - r01 = rte_sched_port_enqueue_qwa(port, q01, q01_base, pkt01); + r00 = rte_sched_port_enqueue_qwa(port, subport00, q00, + q00_base, pkt00); + r01 = rte_sched_port_enqueue_qwa(port, subport01, q01, + q01_base, pkt01); result += r00 + r01; if (n_pkts & 1) { - r_last = rte_sched_port_enqueue_qwa(port, q_last, q_last_base, pkt_last); + r_last = rte_sched_port_enqueue_qwa(port, subport_last, + q_last, q_last_base, pkt_last); result += r_last; } -- 2.21.0
Update memory footprint compute function for allowing subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 100 ++++++++++------------------------- lib/librte_sched/rte_sched.h | 8 +-- 2 files changed, 34 insertions(+), 74 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index f59519b00..fdcbb214e 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -476,70 +476,6 @@ rte_sched_port_check_params(struct rte_sched_port_params *params) return 0; } -static uint32_t -rte_sched_port_get_array_base(struct rte_sched_port_params *params, enum rte_sched_port_array array) -{ - uint32_t n_subports_per_port = params->n_subports_per_port; - uint32_t n_pipes_per_subport = params->n_pipes_per_subport; - uint32_t n_pipes_per_port = n_pipes_per_subport * n_subports_per_port; - uint32_t n_queues_per_port = RTE_SCHED_QUEUES_PER_PIPE * n_pipes_per_subport * n_subports_per_port; - - uint32_t size_subport = n_subports_per_port * sizeof(struct rte_sched_subport); - uint32_t size_pipe = n_pipes_per_port * sizeof(struct rte_sched_pipe); - uint32_t size_queue = n_queues_per_port * sizeof(struct rte_sched_queue); - uint32_t size_queue_extra - = n_queues_per_port * sizeof(struct rte_sched_queue_extra); - uint32_t size_pipe_profiles - = params->n_max_pipe_profiles * sizeof(struct rte_sched_pipe_profile); - uint32_t size_bmp_array = rte_bitmap_get_memory_footprint(n_queues_per_port); - uint32_t size_per_pipe_queue_array, size_queue_array; - - uint32_t base, i; - - size_per_pipe_queue_array = 0; - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { - if (i < RTE_SCHED_TRAFFIC_CLASS_BE) - size_per_pipe_queue_array += - params->qsize[i] * sizeof(struct rte_mbuf *); - else - size_per_pipe_queue_array += RTE_SCHED_MAX_QUEUES_PER_TC * - params->qsize[i] * sizeof(struct rte_mbuf *); - } - size_queue_array = n_pipes_per_port * size_per_pipe_queue_array; - - base = 0; - - if (array == e_RTE_SCHED_PORT_ARRAY_SUBPORT) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_subport); - - if (array == e_RTE_SCHED_PORT_ARRAY_PIPE) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_pipe); - - if (array == e_RTE_SCHED_PORT_ARRAY_QUEUE) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_queue); - - if (array == e_RTE_SCHED_PORT_ARRAY_QUEUE_EXTRA) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_queue_extra); - - if (array == e_RTE_SCHED_PORT_ARRAY_PIPE_PROFILES) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_pipe_profiles); - - if (array == e_RTE_SCHED_PORT_ARRAY_BMP_ARRAY) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_bmp_array); - - if (array == e_RTE_SCHED_PORT_ARRAY_QUEUE_ARRAY) - return base; - base += RTE_CACHE_LINE_ROUNDUP(size_queue_array); - - return base; -} - static uint32_t rte_sched_subport_get_array_base(struct rte_sched_subport_params *params, enum rte_sched_subport_array array) @@ -860,22 +796,44 @@ rte_sched_subport_check_params(struct rte_sched_subport_params *params, } uint32_t -rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params) +rte_sched_port_get_memory_footprint(struct rte_sched_port_params *port_params, + struct rte_sched_subport_params **subport_params) { - uint32_t size0, size1; + uint32_t size0 = 0, size1 = 0, i; int status; - status = rte_sched_port_check_params(params); + status = rte_sched_port_check_params(port_params); if (status != 0) { - RTE_LOG(NOTICE, SCHED, - "Port scheduler params check failed (%d)\n", status); + RTE_LOG(ERR, SCHED, + "%s: Port scheduler port params check failed (%d)\n", + __func__, status); return 0; } + for (i = 0; i < port_params->n_subports_per_port; i++) { + struct rte_sched_subport_params *sp = subport_params[i]; + + status = rte_sched_subport_check_params(sp, + port_params->n_pipes_per_subport, + port_params->rate); + if (status != 0) { + RTE_LOG(ERR, SCHED, + "%s: Port scheduler subport params check failed (%d)\n", + __func__, status); + + return 0; + } + } + size0 = sizeof(struct rte_sched_port); - size1 = rte_sched_port_get_array_base(params, - e_RTE_SCHED_PORT_ARRAY_TOTAL); + + for (i = 0; i < port_params->n_subports_per_port; i++) { + struct rte_sched_subport_params *sp = subport_params[i]; + + size1 += rte_sched_subport_get_array_base(sp, + e_RTE_SCHED_SUBPORT_ARRAY_TOTAL); + } return size0 + size1; } diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index 5001f09ed..40f02f124 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -373,14 +373,16 @@ rte_sched_pipe_config(struct rte_sched_port *port, /** * Hierarchical scheduler memory footprint size per port * - * @param params + * @param port_params * Port scheduler configuration parameter structure + * @param subport_params + * Array of subport parameter structures * @return * Memory footprint size in bytes upon success, 0 otherwise */ uint32_t -rte_sched_port_get_memory_footprint(struct rte_sched_port_params *params); - +rte_sched_port_get_memory_footprint(struct rte_sched_port_params *port_params, + struct rte_sched_subport_params **subport_params); /* * Statistics * -- 2.21.0
Modify packet grinder functions of the schedule to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 223 +++++++++++++++++------------------ 1 file changed, 106 insertions(+), 117 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index fdcbb214e..6eba69d99 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -312,24 +312,6 @@ rte_sched_port_queues_per_port(struct rte_sched_port *port) return RTE_SCHED_QUEUES_PER_PIPE * port->n_pipes_per_subport * port->n_subports_per_port; } -static inline struct rte_mbuf ** -rte_sched_port_qbase(struct rte_sched_port *port, uint32_t qindex) -{ - uint32_t pindex = qindex >> 4; - uint32_t qpos = qindex & 0xF; - - return (port->queue_array + pindex * - port->qsize_sum + port->qsize_add[qpos]); -} - -static inline uint16_t -rte_sched_port_qsize(struct rte_sched_port *port, uint32_t qindex) -{ - uint32_t tc = port->pipe_tc[qindex & (RTE_SCHED_QUEUES_PER_PIPE - 1)]; - - return port->qsize[tc]; -} - static inline uint16_t rte_sched_port_pipe_queue(struct rte_sched_port *port, uint32_t traffic_class) { @@ -1523,9 +1505,10 @@ rte_sched_queue_read_stats(struct rte_sched_port *port, #ifdef RTE_SCHED_DEBUG static inline int -rte_sched_port_queue_is_empty(struct rte_sched_port *port, uint32_t qindex) +rte_sched_port_queue_is_empty(struct rte_sched_subport *subport, + uint32_t qindex) { - struct rte_sched_queue *queue = port->queue + qindex; + struct rte_sched_queue *queue = subport->queue + qindex; return queue->qr == queue->qw; } @@ -1640,9 +1623,10 @@ rte_sched_port_red_drop(struct rte_sched_port *port, } static inline void -rte_sched_port_set_queue_empty_timestamp(struct rte_sched_port *port, uint32_t qindex) +rte_sched_port_set_queue_empty_timestamp(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t qindex) { - struct rte_sched_queue_extra *qe = port->queue_extra + qindex; + struct rte_sched_queue_extra *qe = subport->queue_extra + qindex; struct rte_red *red = &qe->red; rte_red_mark_queue_empty(red, port->time); @@ -1659,14 +1643,14 @@ static inline int rte_sched_port_red_drop(struct rte_sched_port *port __rte_unus return 0; } -#define rte_sched_port_set_queue_empty_timestamp(port, qindex) +#define rte_sched_port_set_queue_empty_timestamp(port, subport, qindex) #endif /* RTE_SCHED_RED */ #ifdef RTE_SCHED_DEBUG static inline void -debug_check_queue_slab(struct rte_sched_port *port, uint32_t bmp_pos, +debug_check_queue_slab(struct rte_sched_subport *subport, uint32_t bmp_pos, uint64_t bmp_slab) { uint64_t mask; @@ -1678,7 +1662,7 @@ debug_check_queue_slab(struct rte_sched_port *port, uint32_t bmp_pos, panic = 0; for (i = 0, mask = 1; i < 64; i++, mask <<= 1) { if (mask & bmp_slab) { - if (rte_sched_port_queue_is_empty(port, bmp_pos + i)) { + if (rte_sched_port_queue_is_empty(subport, bmp_pos + i)) { printf("Queue %u (slab offset %u) is empty\n", bmp_pos + i, i); panic = 1; } @@ -2000,10 +1984,10 @@ rte_sched_port_enqueue(struct rte_sched_port *port, struct rte_mbuf **pkts, #ifndef RTE_SCHED_SUBPORT_TC_OV static inline void -grinder_credits_update(struct rte_sched_port *port, uint32_t pos) +grinder_credits_update(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; struct rte_sched_pipe_profile *params = grinder->pipe_params; uint64_t n_periods; @@ -2041,10 +2025,9 @@ grinder_credits_update(struct rte_sched_port *port, uint32_t pos) #else static inline uint32_t -grinder_tc_ov_credits_update(struct rte_sched_port *port, uint32_t pos) +grinder_tc_ov_credits_update(struct rte_sched_port *port, + struct rte_sched_subport *subport) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; uint32_t tc_ov_consumption[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; uint32_t tc_consumption = 0, tc_ov_consumption_max; uint32_t tc_ov_wm = subport->tc_ov_wm; @@ -2084,10 +2067,10 @@ grinder_tc_ov_credits_update(struct rte_sched_port *port, uint32_t pos) } static inline void -grinder_credits_update(struct rte_sched_port *port, uint32_t pos) +grinder_credits_update(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; struct rte_sched_pipe_profile *params = grinder->pipe_params; uint64_t n_periods; @@ -2107,7 +2090,7 @@ grinder_credits_update(struct rte_sched_port *port, uint32_t pos) /* Subport TCs */ if (unlikely(port->time >= subport->tc_time)) { - subport->tc_ov_wm = grinder_tc_ov_credits_update(port, pos); + subport->tc_ov_wm = grinder_tc_ov_credits_update(port, subport); for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) subport->tc_credits[i] = subport->tc_credits_per_period[i]; @@ -2137,10 +2120,10 @@ grinder_credits_update(struct rte_sched_port *port, uint32_t pos) #ifndef RTE_SCHED_SUBPORT_TC_OV static inline int -grinder_credits_check(struct rte_sched_port *port, uint32_t pos) +grinder_credits_check(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; + 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; @@ -2172,10 +2155,10 @@ grinder_credits_check(struct rte_sched_port *port, uint32_t pos) #else static inline int -grinder_credits_check(struct rte_sched_port *port, uint32_t pos) +grinder_credits_check(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; - struct rte_sched_subport *subport = grinder->subport; + 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; @@ -2220,15 +2203,16 @@ grinder_credits_check(struct rte_sched_port *port, uint32_t pos) static inline int -grinder_schedule(struct rte_sched_port *port, uint32_t pos) +grinder_schedule(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_queue *queue = grinder->queue[grinder->qpos]; struct rte_mbuf *pkt = grinder->pkt; uint32_t pkt_len = pkt->pkt_len + port->frame_overhead; uint32_t be_tc_active; - if (!grinder_credits_check(port, pos)) + if (!grinder_credits_check(port, subport, pos)) return 0; /* Advance port time */ @@ -2245,15 +2229,15 @@ grinder_schedule(struct rte_sched_port *port, uint32_t pos) if (queue->qr == queue->qw) { uint32_t qindex = grinder->qindex[grinder->qpos]; - rte_bitmap_clear(port->bmp, qindex); + rte_bitmap_clear(subport->bmp, qindex); grinder->qmask &= ~(1 << grinder->qpos); if (be_tc_active) grinder->wrr_mask[grinder->qpos] = 0; - rte_sched_port_set_queue_empty_timestamp(port, qindex); + rte_sched_port_set_queue_empty_timestamp(port, subport, qindex); } /* Reset pipe loop detection */ - port->pipe_loop = RTE_SCHED_PIPE_INVALID; + subport->pipe_loop = RTE_SCHED_PIPE_INVALID; grinder->productive = 1; return 1; @@ -2262,13 +2246,13 @@ grinder_schedule(struct rte_sched_port *port, uint32_t pos) #ifdef SCHED_VECTOR_SSE4 static inline int -grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) +grinder_pipe_exists(struct rte_sched_subport *subport, uint32_t base_pipe) { __m128i index = _mm_set1_epi32(base_pipe); - __m128i pipes = _mm_load_si128((__m128i *)port->grinder_base_bmp_pos); + __m128i pipes = _mm_load_si128((__m128i *)subport->grinder_base_bmp_pos); __m128i res = _mm_cmpeq_epi32(pipes, index); - pipes = _mm_load_si128((__m128i *)(port->grinder_base_bmp_pos + 4)); + pipes = _mm_load_si128((__m128i *)(subport->grinder_base_bmp_pos + 4)); pipes = _mm_cmpeq_epi32(pipes, index); res = _mm_or_si128(res, pipes); @@ -2281,10 +2265,10 @@ grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) #elif defined(SCHED_VECTOR_NEON) static inline int -grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) +grinder_pipe_exists(struct rte_sched_subport *subport, uint32_t base_pipe) { uint32x4_t index, pipes; - uint32_t *pos = (uint32_t *)port->grinder_base_bmp_pos; + uint32_t *pos = (uint32_t *)subport->grinder_base_bmp_pos; index = vmovq_n_u32(base_pipe); pipes = vld1q_u32(pos); @@ -2301,12 +2285,12 @@ grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) #else static inline int -grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) +grinder_pipe_exists(struct rte_sched_subport *subport, uint32_t base_pipe) { uint32_t i; for (i = 0; i < RTE_SCHED_PORT_N_GRINDERS; i++) { - if (port->grinder_base_bmp_pos[i] == base_pipe) + if (subport->grinder_base_bmp_pos[i] == base_pipe) return 1; } @@ -2316,9 +2300,10 @@ grinder_pipe_exists(struct rte_sched_port *port, uint32_t base_pipe) #endif /* RTE_SCHED_OPTIMIZATIONS */ static inline void -grinder_pcache_populate(struct rte_sched_port *port, uint32_t pos, uint32_t bmp_pos, uint64_t bmp_slab) +grinder_pcache_populate(struct rte_sched_subport *subport, + uint32_t pos, uint32_t bmp_pos, uint64_t bmp_slab) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint16_t w[4]; grinder->pcache_w = 0; @@ -2347,9 +2332,10 @@ grinder_pcache_populate(struct rte_sched_port *port, uint32_t pos, uint32_t bmp_ } static inline void -grinder_tccache_populate(struct rte_sched_port *port, uint32_t pos, uint32_t qindex, uint16_t qmask) +grinder_tccache_populate(struct rte_sched_subport *subport, + uint32_t pos, uint32_t qindex, uint16_t qmask) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint8_t b, i; grinder->tccache_w = 0; @@ -2370,9 +2356,10 @@ grinder_tccache_populate(struct rte_sched_port *port, uint32_t pos, uint32_t qin } static inline int -grinder_next_tc(struct rte_sched_port *port, uint32_t pos) +grinder_next_tc(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_mbuf **qbase; uint32_t qindex; uint16_t qsize; @@ -2381,15 +2368,15 @@ grinder_next_tc(struct rte_sched_port *port, uint32_t pos) return 0; qindex = grinder->tccache_qindex[grinder->tccache_r]; - qbase = rte_sched_port_qbase(port, qindex); - qsize = rte_sched_port_qsize(port, qindex); + qbase = rte_sched_subport_pipe_qbase(subport, qindex); + qsize = rte_sched_subport_pipe_qsize(port, subport, qindex); grinder->tc_index = rte_sched_port_pipe_tc(port, qindex); grinder->qmask = grinder->tccache_qmask[grinder->tccache_r]; grinder->qsize = qsize; if (grinder->tc_index < RTE_SCHED_TRAFFIC_CLASS_BE) { - grinder->queue[0] = port->queue + qindex; + grinder->queue[0] = subport->queue + qindex; grinder->qbase[0] = qbase; grinder->qindex[0] = qindex; grinder->tccache_r++; @@ -2397,10 +2384,10 @@ grinder_next_tc(struct rte_sched_port *port, uint32_t pos) return 1; } - grinder->queue[0] = port->queue + qindex; - grinder->queue[1] = port->queue + qindex + 1; - grinder->queue[2] = port->queue + qindex + 2; - grinder->queue[3] = port->queue + qindex + 3; + grinder->queue[0] = subport->queue + qindex; + grinder->queue[1] = subport->queue + qindex + 1; + grinder->queue[2] = subport->queue + qindex + 2; + grinder->queue[3] = subport->queue + qindex + 3; grinder->qbase[0] = qbase; grinder->qbase[1] = qbase + qsize; @@ -2417,9 +2404,10 @@ grinder_next_tc(struct rte_sched_port *port, uint32_t pos) } static inline int -grinder_next_pipe(struct rte_sched_port *port, uint32_t pos) +grinder_next_pipe(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint32_t pipe_qindex; uint16_t pipe_qmask; @@ -2432,22 +2420,22 @@ grinder_next_pipe(struct rte_sched_port *port, uint32_t pos) uint32_t bmp_pos = 0; /* Get another non-empty pipe group */ - if (unlikely(rte_bitmap_scan(port->bmp, &bmp_pos, &bmp_slab) <= 0)) + if (unlikely(rte_bitmap_scan(subport->bmp, &bmp_pos, &bmp_slab) <= 0)) return 0; #ifdef RTE_SCHED_DEBUG - debug_check_queue_slab(port, bmp_pos, bmp_slab); + debug_check_queue_slab(subport, bmp_pos, bmp_slab); #endif /* Return if pipe group already in one of the other grinders */ - port->grinder_base_bmp_pos[pos] = RTE_SCHED_BMP_POS_INVALID; - if (unlikely(grinder_pipe_exists(port, bmp_pos))) + subport->grinder_base_bmp_pos[pos] = RTE_SCHED_BMP_POS_INVALID; + if (unlikely(grinder_pipe_exists(subport, bmp_pos))) return 0; - port->grinder_base_bmp_pos[pos] = bmp_pos; + subport->grinder_base_bmp_pos[pos] = bmp_pos; /* Install new pipe group into grinder's pipe cache */ - grinder_pcache_populate(port, pos, bmp_pos, bmp_slab); + grinder_pcache_populate(subport, pos, bmp_pos, bmp_slab); pipe_qmask = grinder->pcache_qmask[0]; pipe_qindex = grinder->pcache_qindex[0]; @@ -2456,18 +2444,18 @@ grinder_next_pipe(struct rte_sched_port *port, uint32_t pos) /* Install new pipe in the grinder */ grinder->pindex = pipe_qindex >> 4; - grinder->subport = port->subport + (grinder->pindex / port->n_pipes_per_subport); - grinder->pipe = port->pipe + grinder->pindex; + grinder->subport = subport; + grinder->pipe = subport->pipe + grinder->pindex; grinder->pipe_params = NULL; /* to be set after the pipe structure is prefetched */ grinder->productive = 0; - grinder_tccache_populate(port, pos, pipe_qindex, pipe_qmask); - grinder_next_tc(port, pos); + grinder_tccache_populate(subport, pos, pipe_qindex, pipe_qmask); + grinder_next_tc(port, subport, pos); /* Check for pipe exhaustion */ - if (grinder->pindex == port->pipe_loop) { - port->pipe_exhaustion = 1; - port->pipe_loop = RTE_SCHED_PIPE_INVALID; + if (grinder->pindex == subport->pipe_loop) { + subport->pipe_exhaustion = 1; + subport->pipe_loop = RTE_SCHED_PIPE_INVALID; } return 1; @@ -2475,9 +2463,9 @@ grinder_next_pipe(struct rte_sched_port *port, uint32_t pos) static inline void -grinder_wrr_load(struct rte_sched_port *port, uint32_t pos) +grinder_wrr_load(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; struct rte_sched_pipe_profile *pipe_params = grinder->pipe_params; uint32_t qmask = grinder->qmask; @@ -2503,9 +2491,9 @@ grinder_wrr_load(struct rte_sched_port *port, uint32_t pos) } static inline void -grinder_wrr_store(struct rte_sched_port *port, uint32_t pos) +grinder_wrr_store(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; struct rte_sched_pipe *pipe = grinder->pipe; pipe->wrr_tokens[0] = @@ -2523,9 +2511,9 @@ grinder_wrr_store(struct rte_sched_port *port, uint32_t pos) } static inline void -grinder_wrr(struct rte_sched_port *port, uint32_t pos) +grinder_wrr(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint16_t wrr_tokens_min; grinder->wrr_tokens[0] |= ~grinder->wrr_mask[0]; @@ -2543,21 +2531,21 @@ grinder_wrr(struct rte_sched_port *port, uint32_t pos) } -#define grinder_evict(port, pos) +#define grinder_evict(subport, pos) static inline void -grinder_prefetch_pipe(struct rte_sched_port *port, uint32_t pos) +grinder_prefetch_pipe(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; rte_prefetch0(grinder->pipe); rte_prefetch0(grinder->queue[0]); } static inline void -grinder_prefetch_tc_queue_arrays(struct rte_sched_port *port, uint32_t pos) +grinder_prefetch_tc_queue_arrays(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint16_t qsize, qr[RTE_SCHED_MAX_QUEUES_PER_TC]; qsize = grinder->qsize; @@ -2578,17 +2566,17 @@ grinder_prefetch_tc_queue_arrays(struct rte_sched_port *port, uint32_t pos) rte_prefetch0(grinder->qbase[0] + qr[0]); rte_prefetch0(grinder->qbase[1] + qr[1]); - grinder_wrr_load(port, pos); - grinder_wrr(port, pos); + grinder_wrr_load(subport, pos); + grinder_wrr(subport, pos); rte_prefetch0(grinder->qbase[2] + qr[2]); rte_prefetch0(grinder->qbase[3] + qr[3]); } static inline void -grinder_prefetch_mbuf(struct rte_sched_port *port, uint32_t pos) +grinder_prefetch_mbuf(struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_grinder *grinder = subport->grinder + pos; uint32_t qpos = grinder->qpos; struct rte_mbuf **qbase = grinder->qbase[qpos]; uint16_t qsize = grinder->qsize; @@ -2607,14 +2595,15 @@ grinder_prefetch_mbuf(struct rte_sched_port *port, uint32_t pos) static inline uint32_t grinder_handle(struct rte_sched_port *port, uint32_t pos) { - struct rte_sched_grinder *grinder = port->grinder + pos; + struct rte_sched_subport *subport = port->subport; + struct rte_sched_grinder *grinder = subport->grinder + pos; switch (grinder->state) { case e_GRINDER_PREFETCH_PIPE: { - if (grinder_next_pipe(port, pos)) { - grinder_prefetch_pipe(port, pos); - port->busy_grinders++; + if (grinder_next_pipe(port, subport, pos)) { + grinder_prefetch_pipe(subport, pos); + subport->busy_grinders++; grinder->state = e_GRINDER_PREFETCH_TC_QUEUE_ARRAYS; return 0; @@ -2627,9 +2616,9 @@ grinder_handle(struct rte_sched_port *port, uint32_t pos) { struct rte_sched_pipe *pipe = grinder->pipe; - grinder->pipe_params = port->pipe_profiles + pipe->profile; - grinder_prefetch_tc_queue_arrays(port, pos); - grinder_credits_update(port, pos); + grinder->pipe_params = subport->pipe_profiles + pipe->profile; + grinder_prefetch_tc_queue_arrays(subport, pos); + grinder_credits_update(port, subport, pos); grinder->state = e_GRINDER_PREFETCH_MBUF; return 0; @@ -2637,7 +2626,7 @@ grinder_handle(struct rte_sched_port *port, uint32_t pos) case e_GRINDER_PREFETCH_MBUF: { - grinder_prefetch_mbuf(port, pos); + grinder_prefetch_mbuf(subport, pos); grinder->state = e_GRINDER_READ_MBUF; return 0; @@ -2647,47 +2636,47 @@ grinder_handle(struct rte_sched_port *port, uint32_t pos) { uint32_t wrr_active, result = 0; - result = grinder_schedule(port, pos); + result = grinder_schedule(port, subport, pos); wrr_active = (grinder->tc_index == RTE_SCHED_TRAFFIC_CLASS_BE); /* Look for next packet within the same TC */ if (result && grinder->qmask) { if (wrr_active) - grinder_wrr(port, pos); + grinder_wrr(subport, pos); - grinder_prefetch_mbuf(port, pos); + grinder_prefetch_mbuf(subport, pos); return 1; } if (wrr_active) - grinder_wrr_store(port, pos); + grinder_wrr_store(subport, pos); /* Look for another active TC within same pipe */ - if (grinder_next_tc(port, pos)) { - grinder_prefetch_tc_queue_arrays(port, pos); + if (grinder_next_tc(port, subport, pos)) { + grinder_prefetch_tc_queue_arrays(subport, pos); grinder->state = e_GRINDER_PREFETCH_MBUF; return result; } if (grinder->productive == 0 && - port->pipe_loop == RTE_SCHED_PIPE_INVALID) - port->pipe_loop = grinder->pindex; + subport->pipe_loop == RTE_SCHED_PIPE_INVALID) + subport->pipe_loop = grinder->pindex; - grinder_evict(port, pos); + grinder_evict(subport, pos); /* Look for another active pipe */ - if (grinder_next_pipe(port, pos)) { - grinder_prefetch_pipe(port, pos); + if (grinder_next_pipe(port, subport, pos)) { + grinder_prefetch_pipe(subport, pos); grinder->state = e_GRINDER_PREFETCH_TC_QUEUE_ARRAYS; return result; } /* No active pipe found */ - port->busy_grinders--; + subport->busy_grinders--; grinder->state = e_GRINDER_PREFETCH_PIPE; return result; -- 2.21.0
Modify scheduler packet dequeue operation to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 51 ++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 6eba69d99..28df34447 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -243,6 +243,7 @@ struct rte_sched_port { uint32_t busy_grinders; struct rte_mbuf **pkts_out; uint32_t n_pkts_out; + uint32_t subport_id; /* Queue base calculation */ uint32_t qsize_add[RTE_SCHED_QUEUES_PER_PIPE]; @@ -888,6 +889,7 @@ rte_sched_port_config(struct rte_sched_port_params *params) /* Grinders */ port->pkts_out = NULL; port->n_pkts_out = 0; + port->subport_id = 0; return port; } @@ -2593,9 +2595,9 @@ grinder_prefetch_mbuf(struct rte_sched_subport *subport, uint32_t pos) } static inline uint32_t -grinder_handle(struct rte_sched_port *port, uint32_t pos) +grinder_handle(struct rte_sched_port *port, + struct rte_sched_subport *subport, uint32_t pos) { - struct rte_sched_subport *subport = port->subport; struct rte_sched_grinder *grinder = subport->grinder + pos; switch (grinder->state) { @@ -2694,6 +2696,7 @@ rte_sched_port_time_resync(struct rte_sched_port *port) uint64_t cycles = rte_get_tsc_cycles(); uint64_t cycles_diff = cycles - port->time_cpu_cycles; uint64_t bytes_diff; + uint32_t i; /* Compute elapsed time in bytes */ bytes_diff = rte_reciprocal_divide(cycles_diff << RTE_SCHED_TIME_SHIFT, @@ -2706,20 +2709,21 @@ rte_sched_port_time_resync(struct rte_sched_port *port) port->time = port->time_cpu_bytes; /* Reset pipe loop detection */ - port->pipe_loop = RTE_SCHED_PIPE_INVALID; + for (i = 0; i < port->n_subports_per_port; i++) + port->subports[i]->pipe_loop = RTE_SCHED_PIPE_INVALID; } static inline int -rte_sched_port_exceptions(struct rte_sched_port *port, int second_pass) +rte_sched_port_exceptions(struct rte_sched_subport *subport, int second_pass) { int exceptions; /* Check if any exception flag is set */ - exceptions = (second_pass && port->busy_grinders == 0) || - (port->pipe_exhaustion == 1); + exceptions = (second_pass && subport->busy_grinders == 0) || + (subport->pipe_exhaustion == 1); /* Clear exception flags */ - port->pipe_exhaustion = 0; + subport->pipe_exhaustion = 0; return exceptions; } @@ -2727,7 +2731,9 @@ rte_sched_port_exceptions(struct rte_sched_port *port, int second_pass) int rte_sched_port_dequeue(struct rte_sched_port *port, struct rte_mbuf **pkts, uint32_t n_pkts) { - uint32_t i, count; + struct rte_sched_subport *subport; + uint32_t subport_id = port->subport_id; + uint32_t i, n_subports = 0, count; port->pkts_out = pkts; port->n_pkts_out = 0; @@ -2736,9 +2742,32 @@ rte_sched_port_dequeue(struct rte_sched_port *port, struct rte_mbuf **pkts, uint /* Take each queue in the grinder one step further */ for (i = 0, count = 0; ; i++) { - count += grinder_handle(port, i & (RTE_SCHED_PORT_N_GRINDERS - 1)); - if ((count == n_pkts) || - rte_sched_port_exceptions(port, i >= RTE_SCHED_PORT_N_GRINDERS)) { + subport = port->subports[subport_id]; + + count += grinder_handle(port, subport, + i & (RTE_SCHED_PORT_N_GRINDERS - 1)); + + if (count == n_pkts) { + subport_id++; + + if (subport_id == port->n_subports_per_port) + subport_id = 0; + + port->subport_id = subport_id; + break; + } + + if (rte_sched_port_exceptions(subport, i >= RTE_SCHED_PORT_N_GRINDERS)) { + i = 0; + subport_id++; + n_subports++; + } + + if (subport_id == port->n_subports_per_port) + subport_id = 0; + + if (n_subports == port->n_subports_per_port) { + port->subport_id = subport_id; break; } } -- 2.21.0
Modify pipe queue stats read function to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- lib/librte_sched/rte_sched.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 28df34447..1faa580d0 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -310,7 +310,12 @@ struct rte_sched_subport *subport, uint32_t qindex) static inline uint32_t rte_sched_port_queues_per_port(struct rte_sched_port *port) { - return RTE_SCHED_QUEUES_PER_PIPE * port->n_pipes_per_subport * port->n_subports_per_port; + uint32_t n_queues = 0, i; + + for (i = 0; i < port->n_subports_per_port; i++) + n_queues += rte_sched_subport_pipe_queues(port->subports[i]); + + return n_queues; } static inline uint16_t @@ -1464,8 +1469,10 @@ rte_sched_queue_read_stats(struct rte_sched_port *port, struct rte_sched_queue_stats *stats, uint16_t *qlen) { + struct rte_sched_subport *s; struct rte_sched_queue *q; struct rte_sched_queue_extra *qe; + uint32_t subport_id, subport_qmask, subport_qindex; /* Check user parameters */ if (port == NULL) { @@ -1491,8 +1498,13 @@ rte_sched_queue_read_stats(struct rte_sched_port *port, "%s: Incorrect value for parameter qlen\n", __func__); return -EINVAL; } - q = port->queue + queue_id; - qe = port->queue_extra + queue_id; + subport_qmask = port->n_pipes_per_subport_log2 + 4; + subport_id = (queue_id >> subport_qmask) & (port->n_subports_per_port - 1); + + s = port->subports[subport_id]; + subport_qindex = ((1 << subport_qmask) - 1) & queue_id; + q = s->queue + subport_qindex; + qe = s->queue_extra + subport_qindex; /* Copy queue stats and clear */ memcpy(stats, &qe->stats, sizeof(struct rte_sched_queue_stats)); -- 2.21.0
Modify tests function to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- app/test/test_sched.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/app/test/test_sched.c b/app/test/test_sched.c index afe0b0765..fc31080ef 100644 --- a/app/test/test_sched.c +++ b/app/test/test_sched.c @@ -22,18 +22,6 @@ #define TC 2 #define QUEUE 0 -static struct rte_sched_subport_params subport_param[] = { - { - .tb_rate = 1250000000, - .tb_size = 1000000, - - .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000, - 1250000000, 1250000000, 1250000000, 1250000000, 1250000000, - 1250000000, 1250000000, 1250000000, 1250000000}, - .tc_period = 10, - }, -}; - static struct rte_sched_pipe_params pipe_profile[] = { { /* Profile #0 */ .tb_rate = 305175, @@ -48,6 +36,23 @@ static struct rte_sched_pipe_params pipe_profile[] = { }, }; +static struct rte_sched_subport_params subport_param[] = { + { + .tb_rate = 1250000000, + .tb_size = 1000000, + + .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000, + 1250000000, 1250000000, 1250000000, 1250000000, 1250000000, + 1250000000, 1250000000, 1250000000, 1250000000}, + .tc_period = 10, + .n_pipes_per_subport_enabled = 1024, + .qsize = {32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}, + .pipe_profiles = pipe_profile, + .n_pipe_profiles = 1, + .n_max_pipe_profiles = 1, + }, +}; + static struct rte_sched_port_params port_param = { .socket = 0, /* computed */ .rate = 0, /* computed */ @@ -55,10 +60,6 @@ static struct rte_sched_port_params port_param = { .frame_overhead = RTE_SCHED_FRAME_OVERHEAD_DEFAULT, .n_subports_per_port = 1, .n_pipes_per_subport = 1024, - .qsize = {32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}, - .pipe_profiles = pipe_profile, - .n_pipe_profiles = 1, - .n_max_pipe_profiles = 1, }; #define NB_MBUF 32 @@ -140,7 +141,7 @@ test_sched(void) err = rte_sched_subport_config(port, SUBPORT, subport_param); TEST_ASSERT_SUCCESS(err, "Error config sched, err=%d\n", err); - for (pipe = 0; pipe < port_param.n_pipes_per_subport; pipe ++) { + for (pipe = 0; pipe < subport_param[0].n_pipes_per_subport_enabled; pipe++) { err = rte_sched_pipe_config(port, SUBPORT, pipe, 0); TEST_ASSERT_SUCCESS(err, "Error config sched pipe %u, err=%d\n", pipe, err); } -- 2.21.0
Modify softnic traffic management function to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- drivers/net/softnic/rte_eth_softnic_tm.c | 54 ++++++++++++------------ 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/drivers/net/softnic/rte_eth_softnic_tm.c b/drivers/net/softnic/rte_eth_softnic_tm.c index 61c3adc82..80a470c9e 100644 --- a/drivers/net/softnic/rte_eth_softnic_tm.c +++ b/drivers/net/softnic/rte_eth_softnic_tm.c @@ -85,7 +85,8 @@ softnic_tmgr_port_create(struct pmd_internals *p, /* Subport */ n_subports = t->port_params.n_subports_per_port; for (subport_id = 0; subport_id < n_subports; subport_id++) { - uint32_t n_pipes_per_subport = t->port_params.n_pipes_per_subport; + uint32_t n_pipes_per_subport = + t->subport_params[subport_id].n_pipes_per_subport_enabled; uint32_t pipe_id; int status; @@ -2211,10 +2212,11 @@ tm_tc_wred_profile_get(struct rte_eth_dev *dev, uint32_t tc_id) #ifdef RTE_SCHED_RED static void -wred_profiles_set(struct rte_eth_dev *dev) +wred_profiles_set(struct rte_eth_dev *dev, uint32_t subport_id) { struct pmd_internals *p = dev->data->dev_private; - struct rte_sched_port_params *pp = &p->soft.tm.params.port_params; + struct rte_sched_subport_params *pp = + &p->soft.tm.params.subport_params[subport_id]; uint32_t tc_id; enum rte_color color; @@ -2234,7 +2236,7 @@ wred_profiles_set(struct rte_eth_dev *dev) #else -#define wred_profiles_set(dev) +#define wred_profiles_set(dev, subport_id) #endif @@ -2526,29 +2528,9 @@ hierarchy_blueprints_create(struct rte_eth_dev *dev) .frame_overhead = root->shaper_profile->params.pkt_length_adjust, .n_subports_per_port = root->n_children, - .n_pipes_per_subport = h->n_tm_nodes[TM_NODE_LEVEL_PIPE] / - h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT], - .qsize = {p->params.tm.qsize[0], - p->params.tm.qsize[1], - p->params.tm.qsize[2], - p->params.tm.qsize[3], - p->params.tm.qsize[4], - p->params.tm.qsize[5], - p->params.tm.qsize[6], - p->params.tm.qsize[7], - p->params.tm.qsize[8], - p->params.tm.qsize[9], - p->params.tm.qsize[10], - p->params.tm.qsize[11], - p->params.tm.qsize[12], - }, - .pipe_profiles = t->pipe_profiles, - .n_pipe_profiles = t->n_pipe_profiles, - .n_max_pipe_profiles = TM_MAX_PIPE_PROFILE, + .n_pipes_per_subport = TM_MAX_PIPES_PER_SUBPORT, }; - wred_profiles_set(dev); - subport_id = 0; TAILQ_FOREACH(n, nl, node) { uint64_t tc_rate[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; @@ -2588,8 +2570,28 @@ hierarchy_blueprints_create(struct rte_eth_dev *dev) tc_rate[12], }, .tc_period = SUBPORT_TC_PERIOD, + .n_pipes_per_subport_enabled = + h->n_tm_nodes[TM_NODE_LEVEL_PIPE] / + h->n_tm_nodes[TM_NODE_LEVEL_SUBPORT], + .qsize = {p->params.tm.qsize[0], + p->params.tm.qsize[1], + p->params.tm.qsize[2], + p->params.tm.qsize[3], + p->params.tm.qsize[4], + p->params.tm.qsize[5], + p->params.tm.qsize[6], + p->params.tm.qsize[7], + p->params.tm.qsize[8], + p->params.tm.qsize[9], + p->params.tm.qsize[10], + p->params.tm.qsize[11], + p->params.tm.qsize[12], + }, + .pipe_profiles = t->pipe_profiles, + .n_pipe_profiles = t->n_pipe_profiles, + .n_max_pipe_profiles = TM_MAX_PIPE_PROFILE, }; - + wred_profiles_set(dev, subport_id); subport_id++; } } -- 2.21.0
Modify ip pipeline traffic management function to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- examples/ip_pipeline/cli.c | 71 ++++++++++++++++++------------------- examples/ip_pipeline/tmgr.c | 25 +++++++------ examples/ip_pipeline/tmgr.h | 7 ++-- 3 files changed, 51 insertions(+), 52 deletions(-) diff --git a/examples/ip_pipeline/cli.c b/examples/ip_pipeline/cli.c index 02dc11495..c72030682 100644 --- a/examples/ip_pipeline/cli.c +++ b/examples/ip_pipeline/cli.c @@ -393,7 +393,12 @@ static const char cmd_tmgr_subport_profile_help[] = " <tc0_rate> <tc1_rate> <tc2_rate> <tc3_rate> <tc4_rate>" " <tc5_rate> <tc6_rate> <tc7_rate> <tc8_rate>" " <tc9_rate> <tc10_rate> <tc11_rate> <tc12_rate>\n" -" <tc_period>\n"; +" <tc_period>\n" +" pps <n_pipes_per_subport>\n" +" qsize <qsize_tc0> <qsize_tc1> <qsize_tc2>" +" <qsize_tc3> <qsize_tc4> <qsize_tc5> <qsize_tc6>" +" <qsize_tc7> <qsize_tc8> <qsize_tc9> <qsize_tc10>" +" <qsize_tc11> <qsize_tc12>"; static void cmd_tmgr_subport_profile(char **tokens, @@ -404,7 +409,7 @@ cmd_tmgr_subport_profile(char **tokens, struct rte_sched_subport_params p; int status, i; - if (n_tokens != 19) { + if (n_tokens != 35) { snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); return; } @@ -430,6 +435,27 @@ cmd_tmgr_subport_profile(char **tokens, return; } + if (strcmp(tokens[19], "pps") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps"); + return; + } + + if (parser_read_uint32(&p.n_pipes_per_subport_enabled, tokens[20]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "n_pipes_per_subport"); + return; + } + + if (strcmp(tokens[21], "qsize") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "qsize"); + return; + } + + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) + if (parser_read_uint16(&p.qsize[i], tokens[22 + i]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "qsize"); + return; + } + status = tmgr_subport_profile_add(&p); if (status != 0) { snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); @@ -504,11 +530,6 @@ static const char cmd_tmgr_help[] = "tmgr <tmgr_name>\n" " rate <rate>\n" " spp <n_subports_per_port>\n" -" pps <n_pipes_per_subport>\n" -" qsize <qsize_tc0> <qsize_tc1> <qsize_tc2>" -" <qsize_tc3> <qsize_tc4> <qsize_tc5> <qsize_tc6>" -" <qsize_tc7> <qsize_tc8> <qsize_tc9> <qsize_tc10>" -" <qsize_tc11> <qsize_tc12>\n" " fo <frame_overhead>\n" " mtu <mtu>\n" " cpu <cpu_id>\n"; @@ -522,9 +543,8 @@ cmd_tmgr(char **tokens, struct tmgr_port_params p; char *name; struct tmgr_port *tmgr_port; - int i; - if (n_tokens != 28) { + if (n_tokens != 12) { snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); return; } @@ -551,53 +571,32 @@ cmd_tmgr(char **tokens, return; } - if (strcmp(tokens[6], "pps") != 0) { - snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps"); - return; - } - - if (parser_read_uint32(&p.n_pipes_per_subport, tokens[7]) != 0) { - snprintf(out, out_size, MSG_ARG_INVALID, "n_pipes_per_subport"); - return; - } - - if (strcmp(tokens[8], "qsize") != 0) { - snprintf(out, out_size, MSG_ARG_NOT_FOUND, "qsize"); - return; - } - - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - if (parser_read_uint16(&p.qsize[i], tokens[9 + i]) != 0) { - snprintf(out, out_size, MSG_ARG_INVALID, "qsize"); - return; - } - - if (strcmp(tokens[22], "fo") != 0) { + if (strcmp(tokens[6], "fo") != 0) { snprintf(out, out_size, MSG_ARG_NOT_FOUND, "fo"); return; } - if (parser_read_uint32(&p.frame_overhead, tokens[23]) != 0) { + if (parser_read_uint32(&p.frame_overhead, tokens[7]) != 0) { snprintf(out, out_size, MSG_ARG_INVALID, "frame_overhead"); return; } - if (strcmp(tokens[24], "mtu") != 0) { + if (strcmp(tokens[8], "mtu") != 0) { snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mtu"); return; } - if (parser_read_uint32(&p.mtu, tokens[25]) != 0) { + if (parser_read_uint32(&p.mtu, tokens[9]) != 0) { snprintf(out, out_size, MSG_ARG_INVALID, "mtu"); return; } - if (strcmp(tokens[26], "cpu") != 0) { + if (strcmp(tokens[10], "cpu") != 0) { snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu"); return; } - if (parser_read_uint32(&p.cpu_id, tokens[27]) != 0) { + if (parser_read_uint32(&p.cpu_id, tokens[11]) != 0) { snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id"); return; } diff --git a/examples/ip_pipeline/tmgr.c b/examples/ip_pipeline/tmgr.c index 40cbf1d0a..91ccbf60f 100644 --- a/examples/ip_pipeline/tmgr.c +++ b/examples/ip_pipeline/tmgr.c @@ -47,7 +47,8 @@ int tmgr_subport_profile_add(struct rte_sched_subport_params *p) { /* Check input params */ - if (p == NULL) + if (p == NULL || + p->n_pipes_per_subport_enabled == 0) return -1; /* Save profile */ @@ -90,7 +91,6 @@ tmgr_port_create(const char *name, struct tmgr_port_params *params) tmgr_port_find(name) || (params == NULL) || (params->n_subports_per_port == 0) || - (params->n_pipes_per_subport == 0) || (params->cpu_id >= RTE_MAX_NUMA_NODES) || (n_subport_profiles == 0) || (n_pipe_profiles == 0)) @@ -103,18 +103,16 @@ tmgr_port_create(const char *name, struct tmgr_port_params *params) p.mtu = params->mtu; p.frame_overhead = params->frame_overhead; p.n_subports_per_port = params->n_subports_per_port; - p.n_pipes_per_subport = params->n_pipes_per_subport; - - for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) - p.qsize[i] = params->qsize[i]; - - p.pipe_profiles = pipe_profile; - p.n_pipe_profiles = n_pipe_profiles; + p.n_pipes_per_subport = TMGR_PIPE_SUBPORT_MAX; s = rte_sched_port_config(&p); if (s == NULL) return NULL; + subport_profile[0].pipe_profiles = pipe_profile; + subport_profile[0].n_pipe_profiles = n_pipe_profiles; + subport_profile[0].n_max_pipe_profiles = TMGR_PIPE_PROFILE_MAX; + for (i = 0; i < params->n_subports_per_port; i++) { int status; @@ -128,7 +126,7 @@ tmgr_port_create(const char *name, struct tmgr_port_params *params) return NULL; } - for (j = 0; j < params->n_pipes_per_subport; j++) { + for (j = 0; j < subport_profile[0].n_pipes_per_subport_enabled; j++) { status = rte_sched_pipe_config( s, i, @@ -153,7 +151,6 @@ tmgr_port_create(const char *name, struct tmgr_port_params *params) strlcpy(tmgr_port->name, name, sizeof(tmgr_port->name)); tmgr_port->s = s; tmgr_port->n_subports_per_port = params->n_subports_per_port; - tmgr_port->n_pipes_per_subport = params->n_pipes_per_subport; /* Node add to list */ TAILQ_INSERT_TAIL(&tmgr_port_list, tmgr_port, node); @@ -205,8 +202,10 @@ tmgr_pipe_config(const char *port_name, port = tmgr_port_find(port_name); if ((port == NULL) || (subport_id >= port->n_subports_per_port) || - (pipe_id_first >= port->n_pipes_per_subport) || - (pipe_id_last >= port->n_pipes_per_subport) || + (pipe_id_first >= + subport_profile[subport_id].n_pipes_per_subport_enabled) || + (pipe_id_last >= + subport_profile[subport_id].n_pipes_per_subport_enabled) || (pipe_id_first > pipe_id_last) || (pipe_profile_id >= n_pipe_profiles)) return -1; diff --git a/examples/ip_pipeline/tmgr.h b/examples/ip_pipeline/tmgr.h index 8703a2e00..1fcf66ee1 100644 --- a/examples/ip_pipeline/tmgr.h +++ b/examples/ip_pipeline/tmgr.h @@ -12,6 +12,10 @@ #include "common.h" +#ifndef TMGR_PIPE_SUBPORT_MAX +#define TMGR_PIPE_SUBPORT_MAX 4096 +#endif + #ifndef TMGR_SUBPORT_PROFILE_MAX #define TMGR_SUBPORT_PROFILE_MAX 256 #endif @@ -25,7 +29,6 @@ struct tmgr_port { char name[NAME_SIZE]; struct rte_sched_port *s; uint32_t n_subports_per_port; - uint32_t n_pipes_per_subport; }; TAILQ_HEAD(tmgr_port_list, tmgr_port); @@ -42,8 +45,6 @@ struct tmgr_port_params { uint32_t frame_overhead; uint32_t mtu; uint32_t cpu_id; - uint32_t n_pipes_per_subport; - uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; }; int -- 2.21.0
Modify qos sample app to allow different subports of the same port to have different configuration in terms of number of pipes, pipe queue sizes, etc. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- examples/qos_sched/app_thread.c | 20 ++- examples/qos_sched/cfg_file.c | 229 ++++++++++++++++-------------- examples/qos_sched/init.c | 54 +++---- examples/qos_sched/main.h | 1 + examples/qos_sched/profile.cfg | 5 +- examples/qos_sched/profile_ov.cfg | 5 +- examples/qos_sched/stats.c | 44 +++--- 7 files changed, 203 insertions(+), 155 deletions(-) diff --git a/examples/qos_sched/app_thread.c b/examples/qos_sched/app_thread.c index 18b734a14..dbc878b55 100644 --- a/examples/qos_sched/app_thread.c +++ b/examples/qos_sched/app_thread.c @@ -35,15 +35,25 @@ get_pkt_sched(struct rte_mbuf *m, uint32_t *subport, uint32_t *pipe, uint16_t *pdata = rte_pktmbuf_mtod(m, uint16_t *); uint16_t pipe_queue; + /* Outer VLAN ID*/ *subport = (rte_be_to_cpu_16(pdata[SUBPORT_OFFSET]) & 0x0FFF) & - (port_params.n_subports_per_port - 1); /* Outer VLAN ID*/ + (port_params.n_subports_per_port - 1); + + /* Inner VLAN ID */ *pipe = (rte_be_to_cpu_16(pdata[PIPE_OFFSET]) & 0x0FFF) & - (port_params.n_pipes_per_subport - 1); /* Inner VLAN ID */ + (subport_params[*subport].n_pipes_per_subport_enabled - 1); + pipe_queue = active_queues[(pdata[QUEUE_OFFSET] >> 8) % n_active_queues]; + + /* Traffic class (Destination IP) */ *traffic_class = pipe_queue > RTE_SCHED_TRAFFIC_CLASS_BE ? - RTE_SCHED_TRAFFIC_CLASS_BE : pipe_queue; /* Destination IP */ - *queue = pipe_queue - *traffic_class; /* Destination IP */ - *color = pdata[COLOR_OFFSET] & 0x03; /* Destination IP */ + RTE_SCHED_TRAFFIC_CLASS_BE : pipe_queue; + + /* Traffic class queue (Destination IP) */ + *queue = pipe_queue - *traffic_class; + + /* Color (Destination IP) */ + *color = pdata[COLOR_OFFSET] & 0x03; return 0; } diff --git a/examples/qos_sched/cfg_file.c b/examples/qos_sched/cfg_file.c index 45bf599e4..c6d3f5ab6 100644 --- a/examples/qos_sched/cfg_file.c +++ b/examples/qos_sched/cfg_file.c @@ -24,14 +24,10 @@ int cfg_load_port(struct rte_cfgfile *cfg, struct rte_sched_port_params *port_params) { const char *entry; - int j; if (!cfg || !port_params) return -1; - memset(active_queues, 0, sizeof(active_queues)); - n_active_queues = 0; - entry = rte_cfgfile_get_entry(cfg, "port", "frame overhead"); if (entry) port_params->frame_overhead = (uint32_t)atoi(entry); @@ -40,106 +36,6 @@ cfg_load_port(struct rte_cfgfile *cfg, struct rte_sched_port_params *port_params if (entry) port_params->n_subports_per_port = (uint32_t)atoi(entry); - entry = rte_cfgfile_get_entry(cfg, "port", "number of pipes per subport"); - if (entry) - port_params->n_pipes_per_subport = (uint32_t)atoi(entry); - - entry = rte_cfgfile_get_entry(cfg, "port", "queue sizes"); - if (entry) { - char *next; - - for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { - port_params->qsize[j] = (uint16_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - - for (j = 0; j < RTE_SCHED_TRAFFIC_CLASS_BE; j++) - if (port_params->qsize[j]) { - active_queues[n_active_queues] = j; - n_active_queues++; - } - - if (port_params->qsize[RTE_SCHED_TRAFFIC_CLASS_BE]) - for (j = 0; j < RTE_SCHED_BE_QUEUES_PER_PIPE; j++) { - active_queues[n_active_queues] = - RTE_SCHED_TRAFFIC_CLASS_BE + j; - n_active_queues++; - } - } - -#ifdef RTE_SCHED_RED - for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { - char str[32]; - - /* Parse WRED min thresholds */ - snprintf(str, sizeof(str), "tc %d wred min", j); - entry = rte_cfgfile_get_entry(cfg, "red", str); - if (entry) { - char *next; - int k; - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < RTE_COLORS; k++) { - port_params->red_params[j][k].min_th - = (uint16_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - } - - /* Parse WRED max thresholds */ - snprintf(str, sizeof(str), "tc %d wred max", j); - entry = rte_cfgfile_get_entry(cfg, "red", str); - if (entry) { - char *next; - int k; - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < RTE_COLORS; k++) { - port_params->red_params[j][k].max_th - = (uint16_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - } - - /* Parse WRED inverse mark probabilities */ - snprintf(str, sizeof(str), "tc %d wred inv prob", j); - entry = rte_cfgfile_get_entry(cfg, "red", str); - if (entry) { - char *next; - int k; - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < RTE_COLORS; k++) { - port_params->red_params[j][k].maxp_inv - = (uint8_t)strtol(entry, &next, 10); - - if (next == NULL) - break; - entry = next; - } - } - - /* Parse WRED EWMA filter weights */ - snprintf(str, sizeof(str), "tc %d wred weight", j); - entry = rte_cfgfile_get_entry(cfg, "red", str); - if (entry) { - char *next; - int k; - /* for each packet colour (green, yellow, red) */ - for (k = 0; k < RTE_COLORS; k++) { - port_params->red_params[j][k].wq_log2 - = (uint8_t)strtol(entry, &next, 10); - if (next == NULL) - break; - entry = next; - } - } - } -#endif /* RTE_SCHED_RED */ - return 0; } @@ -155,7 +51,7 @@ cfg_load_pipe(struct rte_cfgfile *cfg, struct rte_sched_pipe_params *pipe_params return -1; profiles = rte_cfgfile_num_sections(cfg, "pipe profile", sizeof("pipe profile") - 1); - port_params.n_pipe_profiles = profiles; + subport_params[0].n_pipe_profiles = profiles; for (j = 0; j < profiles; j++) { char pipe_name[32]; @@ -253,12 +149,121 @@ cfg_load_subport(struct rte_cfgfile *cfg, struct rte_sched_subport_params *subpo return -1; memset(app_pipe_to_profile, -1, sizeof(app_pipe_to_profile)); + memset(active_queues, 0, sizeof(active_queues)); + n_active_queues = 0; + +#ifdef RTE_SCHED_RED + char sec_name[CFG_NAME_LEN]; + struct rte_red_params red_params[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; + + snprintf(sec_name, sizeof(sec_name), "red"); + + if (rte_cfgfile_has_section(cfg, sec_name)) { + + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + char str[32]; + + /* Parse WRED min thresholds */ + snprintf(str, sizeof(str), "tc %d wred min", i); + entry = rte_cfgfile_get_entry(cfg, sec_name, str); + if (entry) { + char *next; + /* for each packet colour (green, yellow, red) */ + for (j = 0; j < RTE_COLORS; j++) { + red_params[i][j].min_th + = (uint16_t)strtol(entry, &next, 10); + if (next == NULL) + break; + entry = next; + } + } + + /* Parse WRED max thresholds */ + snprintf(str, sizeof(str), "tc %d wred max", i); + entry = rte_cfgfile_get_entry(cfg, "red", str); + if (entry) { + char *next; + /* for each packet colour (green, yellow, red) */ + for (j = 0; j < RTE_COLORS; j++) { + red_params[i][j].max_th + = (uint16_t)strtol(entry, &next, 10); + if (next == NULL) + break; + entry = next; + } + } + + /* Parse WRED inverse mark probabilities */ + snprintf(str, sizeof(str), "tc %d wred inv prob", i); + entry = rte_cfgfile_get_entry(cfg, "red", str); + if (entry) { + char *next; + /* for each packet colour (green, yellow, red) */ + for (j = 0; j < RTE_COLORS; j++) { + red_params[i][j].maxp_inv + = (uint8_t)strtol(entry, &next, 10); + + if (next == NULL) + break; + entry = next; + } + } + + /* Parse WRED EWMA filter weights */ + snprintf(str, sizeof(str), "tc %d wred weight", i); + entry = rte_cfgfile_get_entry(cfg, "red", str); + if (entry) { + char *next; + /* for each packet colour (green, yellow, red) */ + for (j = 0; j < RTE_COLORS; j++) { + red_params[i][j].wq_log2 + = (uint8_t)strtol(entry, &next, 10); + if (next == NULL) + break; + entry = next; + } + } + } + } +#endif /* RTE_SCHED_RED */ for (i = 0; i < MAX_SCHED_SUBPORTS; i++) { char sec_name[CFG_NAME_LEN]; snprintf(sec_name, sizeof(sec_name), "subport %d", i); if (rte_cfgfile_has_section(cfg, sec_name)) { + entry = rte_cfgfile_get_entry(cfg, sec_name, + "number of pipes per subport"); + if (entry) + subport_params[i].n_pipes_per_subport_enabled = + (uint32_t)atoi(entry); + + entry = rte_cfgfile_get_entry(cfg, sec_name, "queue sizes"); + if (entry) { + char *next; + + for (j = 0; j < RTE_SCHED_TRAFFIC_CLASS_BE; j++) { + subport_params[i].qsize[j] = + (uint16_t)strtol(entry, &next, 10); + if (subport_params[i].qsize[j] != 0) { + active_queues[n_active_queues] = j; + n_active_queues++; + } + if (next == NULL) + break; + entry = next; + } + + subport_params[i].qsize[RTE_SCHED_TRAFFIC_CLASS_BE] = + (uint16_t)strtol(entry, &next, 10); + + for (j = 0; j < RTE_SCHED_BE_QUEUES_PER_PIPE; j++) { + active_queues[n_active_queues] = + RTE_SCHED_TRAFFIC_CLASS_BE + j; + n_active_queues++; + } + } + entry = rte_cfgfile_get_entry(cfg, sec_name, "tb rate"); if (entry) subport_params[i].tb_rate = (uint32_t)atoi(entry); @@ -362,6 +367,20 @@ cfg_load_subport(struct rte_cfgfile *cfg, struct rte_sched_subport_params *subpo } } } +#ifdef RTE_SCHED_RED + for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { + for (k = 0; k < RTE_COLORS; k++) { + subport_params[i].red_params[j][k].min_th = + red_params[j][k].min_th; + subport_params[i].red_params[j][k].max_th = + red_params[j][k].max_th; + subport_params[i].red_params[j][k].maxp_inv = + red_params[j][k].maxp_inv; + subport_params[i].red_params[j][k].wq_log2 = + red_params[j][k].wq_log2; + } + } +#endif } } diff --git a/examples/qos_sched/init.c b/examples/qos_sched/init.c index 32e6e1ba2..0a17e0d4d 100644 --- a/examples/qos_sched/init.c +++ b/examples/qos_sched/init.c @@ -180,18 +180,6 @@ app_init_port(uint16_t portid, struct rte_mempool *mp) return 0; } -static struct rte_sched_subport_params subport_params[MAX_SCHED_SUBPORTS] = { - { - .tb_rate = 1250000000, - .tb_size = 1000000, - - .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000, - 1250000000, 1250000000, 1250000000, 1250000000, 1250000000, - 1250000000, 1250000000, 1250000000, 1250000000}, - .tc_period = 10, - }, -}; - static struct rte_sched_pipe_params pipe_profiles[MAX_SCHED_PIPE_PROFILES] = { { /* Profile #0 */ .tb_rate = 305175, @@ -208,19 +196,21 @@ static struct rte_sched_pipe_params pipe_profiles[MAX_SCHED_PIPE_PROFILES] = { }, }; -struct rte_sched_port_params port_params = { - .name = "port_scheduler_0", - .socket = 0, /* computed */ - .rate = 0, /* computed */ - .mtu = 6 + 6 + 4 + 4 + 2 + 1500, - .frame_overhead = RTE_SCHED_FRAME_OVERHEAD_DEFAULT, - .n_subports_per_port = 1, - .n_pipes_per_subport = 4096, - .qsize = {64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}, - .pipe_profiles = pipe_profiles, - .n_pipe_profiles = sizeof(pipe_profiles) / sizeof(struct rte_sched_pipe_params), - .n_max_pipe_profiles = MAX_SCHED_PIPE_PROFILES, +struct rte_sched_subport_params subport_params[MAX_SCHED_SUBPORTS] = { + { + .tb_rate = 1250000000, + .tb_size = 1000000, + .tc_rate = {1250000000, 1250000000, 1250000000, 1250000000, + 1250000000, 1250000000, 1250000000, 1250000000, 1250000000, + 1250000000, 1250000000, 1250000000, 1250000000}, + .tc_period = 10, + .n_pipes_per_subport_enabled = 4096, + .qsize = {64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}, + .pipe_profiles = pipe_profiles, + .n_pipe_profiles = sizeof(pipe_profiles) / + sizeof(struct rte_sched_pipe_params), + .n_max_pipe_profiles = MAX_SCHED_PIPE_PROFILES, #ifdef RTE_SCHED_RED .red_params = { /* Traffic Class 0 Colors Green / Yellow / Red */ @@ -289,6 +279,17 @@ struct rte_sched_port_params port_params = { [12][2] = {.min_th = 32, .max_th = 64, .maxp_inv = 10, .wq_log2 = 9}, }, #endif /* RTE_SCHED_RED */ + }, +}; + +struct rte_sched_port_params port_params = { + .name = "port_scheduler_0", + .socket = 0, /* computed */ + .rate = 0, /* computed */ + .mtu = 6 + 6 + 4 + 4 + 2 + 1500, + .frame_overhead = RTE_SCHED_FRAME_OVERHEAD_DEFAULT, + .n_subports_per_port = 1, + .n_pipes_per_subport = MAX_SCHED_PIPES, }; static struct rte_sched_port * @@ -323,7 +324,10 @@ app_init_sched_port(uint32_t portid, uint32_t socketid) subport, err); } - for (pipe = 0; pipe < port_params.n_pipes_per_subport; pipe++) { + uint32_t n_pipes_per_subport = + subport_params[subport].n_pipes_per_subport_enabled; + + for (pipe = 0; pipe < n_pipes_per_subport; pipe++) { if (app_pipe_to_profile[subport][pipe] != -1) { err = rte_sched_pipe_config(port, subport, pipe, app_pipe_to_profile[subport][pipe]); diff --git a/examples/qos_sched/main.h b/examples/qos_sched/main.h index d8f890b64..baa2b3ead 100644 --- a/examples/qos_sched/main.h +++ b/examples/qos_sched/main.h @@ -152,6 +152,7 @@ uint32_t active_queues[RTE_SCHED_QUEUES_PER_PIPE]; uint32_t n_active_queues; extern struct rte_sched_port_params port_params; +extern struct rte_sched_subport_params subport_params[MAX_SCHED_SUBPORTS]; int app_parse_args(int argc, char **argv); int app_init(void); diff --git a/examples/qos_sched/profile.cfg b/examples/qos_sched/profile.cfg index 335561370..61b8b7071 100644 --- a/examples/qos_sched/profile.cfg +++ b/examples/qos_sched/profile.cfg @@ -20,11 +20,12 @@ [port] frame overhead = 24 number of subports per port = 1 -number of pipes per subport = 4096 -queue sizes = 64 64 64 64 64 64 64 64 64 64 64 64 64 ; Subport configuration [subport 0] +number of pipes per subport = 4096 +queue sizes = 64 64 64 64 64 64 64 64 64 64 64 64 64 + tb rate = 1250000000 ; Bytes per second tb size = 1000000 ; Bytes diff --git a/examples/qos_sched/profile_ov.cfg b/examples/qos_sched/profile_ov.cfg index 394987399..ab509d28d 100644 --- a/examples/qos_sched/profile_ov.cfg +++ b/examples/qos_sched/profile_ov.cfg @@ -5,11 +5,12 @@ [port] frame overhead = 24 number of subports per port = 1 -number of pipes per subport = 32 -queue sizes = 64 64 64 64 64 64 64 64 64 64 64 64 64 ; Subport configuration [subport 0] +number of pipes per subport = 32 +queue sizes = 64 64 64 64 64 64 64 64 64 64 64 64 64 + tb rate = 8400000 ; Bytes per second tb size = 100000 ; Bytes diff --git a/examples/qos_sched/stats.c b/examples/qos_sched/stats.c index e62e4a2f6..ce34b6c7c 100644 --- a/examples/qos_sched/stats.c +++ b/examples/qos_sched/stats.c @@ -24,7 +24,7 @@ qavg_q(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id, uint8_t tc, if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || - pipe_id >= port_params.n_pipes_per_subport || + pipe_id >= subport_params[subport_id].n_pipes_per_subport_enabled || tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE || q >= RTE_SCHED_BE_QUEUES_PER_PIPE || (tc < RTE_SCHED_TRAFFIC_CLASS_BE && q > 0)) @@ -32,7 +32,7 @@ qavg_q(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id, uint8_t tc, port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - queue_id += port_params.n_pipes_per_subport * + queue_id += subport_params[i].n_pipes_per_subport_enabled * RTE_SCHED_QUEUES_PER_PIPE; if (tc < RTE_SCHED_TRAFFIC_CLASS_BE) queue_id += pipe_id * RTE_SCHED_QUEUES_PER_PIPE + tc; @@ -69,14 +69,16 @@ qavg_tcpipe(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id, } if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || - pipe_id >= port_params.n_pipes_per_subport || + pipe_id >= subport_params[subport_id].n_pipes_per_subport_enabled || tc >= RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE) return -1; port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - queue_id += port_params.n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; + queue_id += + subport_params[i].n_pipes_per_subport_enabled * + RTE_SCHED_QUEUES_PER_PIPE; queue_id += pipe_id * RTE_SCHED_QUEUES_PER_PIPE + tc; @@ -123,13 +125,13 @@ qavg_pipe(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id) if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || - pipe_id >= port_params.n_pipes_per_subport) + pipe_id >= subport_params[subport_id].n_pipes_per_subport_enabled) return -1; port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - queue_id += port_params.n_pipes_per_subport * + queue_id += subport_params[i].n_pipes_per_subport_enabled * RTE_SCHED_QUEUES_PER_PIPE; queue_id += pipe_id * RTE_SCHED_QUEUES_PER_PIPE; @@ -177,13 +179,17 @@ qavg_tcsubport(uint16_t port_id, uint32_t subport_id, uint8_t tc) for (i = 0; i < subport_id; i++) subport_queue_id += - port_params.n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; + subport_params[i].n_pipes_per_subport_enabled * + RTE_SCHED_QUEUES_PER_PIPE; average = 0; for (count = 0; count < qavg_ntimes; count++) { + uint32_t n_pipes_per_subport = + subport_params[subport_id].n_pipes_per_subport_enabled; + part_average = 0; - for (i = 0; i < port_params.n_pipes_per_subport; i++) { + for (i = 0; i < n_pipes_per_subport; i++) { if (tc < RTE_SCHED_TRAFFIC_CLASS_BE) { queue_id = subport_queue_id + i * RTE_SCHED_QUEUES_PER_PIPE + tc; @@ -203,10 +209,11 @@ qavg_tcsubport(uint16_t port_id, uint32_t subport_id, uint8_t tc) } if (tc < RTE_SCHED_TRAFFIC_CLASS_BE) - average += part_average / (port_params.n_pipes_per_subport); + average += part_average / + (subport_params[subport_id].n_pipes_per_subport_enabled); else - average += - part_average / (port_params.n_pipes_per_subport) * + average += part_average / + (subport_params[subport_id].n_pipes_per_subport_enabled) * RTE_SCHED_BE_QUEUES_PER_PIPE; usleep(qavg_period); @@ -240,14 +247,17 @@ qavg_subport(uint16_t port_id, uint32_t subport_id) port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - subport_queue_id += port_params.n_pipes_per_subport * + subport_queue_id += subport_params[i].n_pipes_per_subport_enabled * RTE_SCHED_QUEUES_PER_PIPE; average = 0; for (count = 0; count < qavg_ntimes; count++) { + uint32_t n_pipes_per_subport = + subport_params[subport_id].n_pipes_per_subport_enabled; + part_average = 0; - for (i = 0; i < port_params.n_pipes_per_subport; i++) { + for (i = 0; i < n_pipes_per_subport; i++) { queue_id = subport_queue_id + i * RTE_SCHED_QUEUES_PER_PIPE; for (j = 0; j < RTE_SCHED_QUEUES_PER_PIPE; j++) { @@ -258,7 +268,8 @@ qavg_subport(uint16_t port_id, uint32_t subport_id) } average += part_average / - (port_params.n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE); + (subport_params[subport_id].n_pipes_per_subport_enabled * + RTE_SCHED_QUEUES_PER_PIPE); usleep(qavg_period); } @@ -322,12 +333,13 @@ pipe_stat(uint16_t port_id, uint32_t subport_id, uint32_t pipe_id) if (i == nb_pfc || subport_id >= port_params.n_subports_per_port || - pipe_id >= port_params.n_pipes_per_subport) + pipe_id >= subport_params[subport_id].n_pipes_per_subport_enabled) return -1; port = qos_conf[i].sched_port; for (i = 0; i < subport_id; i++) - queue_id += port_params.n_pipes_per_subport * RTE_SCHED_QUEUES_PER_PIPE; + queue_id += subport_params[i].n_pipes_per_subport_enabled * + RTE_SCHED_QUEUES_PER_PIPE; queue_id += pipe_id * RTE_SCHED_QUEUES_PER_PIPE; -- 2.21.0
Remove redundant data structure fields from port level data structures and update the release notes. Signed-off-by: Jasvinder Singh <jasvinder.singh@intel.com> Signed-off-by: Lukasz Krakowiak <lukaszx.krakowiak@intel.com> --- doc/guides/rel_notes/release_19_11.rst | 7 ++++- lib/librte_sched/rte_sched.c | 42 +------------------------- lib/librte_sched/rte_sched.h | 22 -------------- 3 files changed, 7 insertions(+), 64 deletions(-) diff --git a/doc/guides/rel_notes/release_19_11.rst b/doc/guides/rel_notes/release_19_11.rst index f59a28307..524fb338b 100644 --- a/doc/guides/rel_notes/release_19_11.rst +++ b/doc/guides/rel_notes/release_19_11.rst @@ -228,6 +228,11 @@ API Changes has been introduced in this release is used when used when all the packets enqueued in the tx adapter are destined for the same Ethernet port & Tx queue. +* sched: The pipe nodes configuration parameters such as number of pipes, + pipe queue sizes, pipe profiles, etc., are moved from port level structure + to subport level. This allows different subports of the same port to + have different configuration for the pipe nodes. + ABI Changes ----------- @@ -315,7 +320,7 @@ The libraries prepended with a plus sign were incremented in this version. librte_rcu.so.1 librte_reorder.so.1 librte_ring.so.2 - librte_sched.so.3 + + librte_sched.so.4 librte_security.so.2 librte_stack.so.1 librte_table.so.3 diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 1faa580d0..710ecf65a 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -216,13 +216,6 @@ struct rte_sched_port { uint32_t mtu; uint32_t frame_overhead; int socket; - uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - uint32_t n_pipe_profiles; - uint32_t n_max_pipe_profiles; - uint32_t pipe_tc_be_rate_max; -#ifdef RTE_SCHED_RED - struct rte_red_config red_config[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; -#endif /* Timing */ uint64_t time_cpu_cycles; /* Current CPU time measured in CPU cyles */ @@ -230,48 +223,15 @@ struct rte_sched_port { uint64_t time; /* Current NIC TX time measured in bytes */ struct rte_reciprocal inv_cycles_per_byte; /* CPU cycles per byte */ - /* Scheduling loop detection */ - uint32_t pipe_loop; - uint32_t pipe_exhaustion; - - /* Bitmap */ - struct rte_bitmap *bmp; - uint32_t grinder_base_bmp_pos[RTE_SCHED_PORT_N_GRINDERS] __rte_aligned_16; - /* Grinders */ - struct rte_sched_grinder grinder[RTE_SCHED_PORT_N_GRINDERS]; - uint32_t busy_grinders; struct rte_mbuf **pkts_out; uint32_t n_pkts_out; uint32_t subport_id; - /* Queue base calculation */ - uint32_t qsize_add[RTE_SCHED_QUEUES_PER_PIPE]; - uint32_t qsize_sum; - /* Large data structures */ - struct rte_sched_subport *subports[0]; - struct rte_sched_subport *subport; - struct rte_sched_pipe *pipe; - struct rte_sched_queue *queue; - struct rte_sched_queue_extra *queue_extra; - struct rte_sched_pipe_profile *pipe_profiles; - uint8_t *bmp_array; - struct rte_mbuf **queue_array; - uint8_t memory[0] __rte_cache_aligned; + struct rte_sched_subport *subports[0] __rte_cache_aligned; } __rte_cache_aligned; -enum rte_sched_port_array { - e_RTE_SCHED_PORT_ARRAY_SUBPORT = 0, - e_RTE_SCHED_PORT_ARRAY_PIPE, - e_RTE_SCHED_PORT_ARRAY_QUEUE, - e_RTE_SCHED_PORT_ARRAY_QUEUE_EXTRA, - e_RTE_SCHED_PORT_ARRAY_PIPE_PROFILES, - e_RTE_SCHED_PORT_ARRAY_BMP_ARRAY, - e_RTE_SCHED_PORT_ARRAY_QUEUE_ARRAY, - e_RTE_SCHED_PORT_ARRAY_TOTAL, -}; - enum rte_sched_subport_array { e_RTE_SCHED_SUBPORT_ARRAY_PIPE = 0, e_RTE_SCHED_SUBPORT_ARRAY_QUEUE, diff --git a/lib/librte_sched/rte_sched.h b/lib/librte_sched/rte_sched.h index 40f02f124..c82c23c14 100644 --- a/lib/librte_sched/rte_sched.h +++ b/lib/librte_sched/rte_sched.h @@ -260,28 +260,6 @@ struct rte_sched_port_params { * the subports of the same port. */ uint32_t n_pipes_per_subport; - - /** Packet queue size for each traffic class. - * All the pipes within the same subport share the similar - * configuration for the queues. - */ - uint16_t qsize[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; - - /** Pipe profile table. - * Every pipe is configured using one of the profiles from this table. - */ - struct rte_sched_pipe_params *pipe_profiles; - - /** Profiles in the pipe profile table */ - uint32_t n_pipe_profiles; - - /** Max profiles allowed in the pipe profile table */ - uint32_t n_max_pipe_profiles; - -#ifdef RTE_SCHED_RED - /** RED parameters */ - struct rte_red_params red_params[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; -#endif }; /* -- 2.21.0
25/10/2019 12:51, Jasvinder Singh:
> This patchset refactors the dpdk qos sched library to allow subport
> level configuration flexibility of the pipe nodes.
>
> Currently, all parameters for the pipe nodes (subscribers)
> configuration are part of the port level structure which forces
> all groups of subscribers (pipes) in different subports to
> have similar configurations in terms of their number, queue sizes,
> traffic-classes, etc.
>
> The new implementation moves pipe nodes configuration parameters
> from port level to subport level structure. This allows different
> subports of the same port to have different configuration for the
> pipe nodes, for examples- number of pipes, queue sizes, pipe
> profiles, etc.
>
> In order to keep the implementation complexity under control, all
> pipes within the same subport share the same configuration for queue
> sizes.
>
> v7:
> - rebase on latest dpdk master
> - fix build issue with clang
>
> v6:
> - fix build issue with patchset
Now it compiles fine :)
Applied, thanks