X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Flibrte_sched%2Frte_sched.c;h=a60ddf97eb3990ad53539e251330f4f6e04672f4;hb=4c773788e05a3d5e2a55e134f015bea09350807b;hp=634486c80acb0277cb3caa85e82e7d9e4e6ed58c;hpb=0b037e8b02b7ced8c18a650b708f2fd6e3364d83;p=dpdk.git diff --git a/lib/librte_sched/rte_sched.c b/lib/librte_sched/rte_sched.c index 634486c80a..a60ddf97eb 100644 --- a/lib/librte_sched/rte_sched.c +++ b/lib/librte_sched/rte_sched.c @@ -128,22 +128,6 @@ enum grinder_state { e_GRINDER_READ_MBUF }; -/* - * Path through the scheduler hierarchy used by the scheduler enqueue - * operation to identify the destination queue for the current - * packet. Stored in the field pkt.hash.sched of struct rte_mbuf of - * each packet, typically written by the classification stage and read - * by scheduler enqueue. - */ -struct rte_sched_port_hierarchy { - uint16_t queue:2; /**< Queue ID (0 .. 3) */ - uint16_t traffic_class:2; /**< Traffic class ID (0 .. 3)*/ - uint32_t color:2; /**< Color */ - uint16_t unused:10; - uint16_t subport; /**< Subport ID */ - uint32_t pipe; /**< Pipe ID */ -}; - struct rte_sched_grinder { /* Pipe cache */ uint16_t pcache_qmask[RTE_SCHED_GRINDER_PCACHE_SIZE]; @@ -185,6 +169,7 @@ struct rte_sched_port { /* User parameters */ uint32_t n_subports_per_port; uint32_t n_pipes_per_subport; + uint32_t n_pipes_per_subport_log2; uint32_t rate; uint32_t mtu; uint32_t frame_overhead; @@ -192,7 +177,7 @@ struct rte_sched_port { uint32_t n_pipe_profiles; uint32_t pipe_tc3_rate_max; #ifdef RTE_SCHED_RED - struct rte_red_config red_config[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][e_RTE_METER_COLORS]; + struct rte_red_config red_config[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE][RTE_COLORS]; #endif /* Timing */ @@ -275,16 +260,61 @@ rte_sched_port_qsize(struct rte_sched_port *port, uint32_t qindex) return port->qsize[tc]; } +static int +pipe_profile_check(struct rte_sched_pipe_params *params, + uint32_t rate) +{ + uint32_t i; + + /* Pipe parameters */ + if (params == NULL) + return -10; + + /* TB rate: non-zero, not greater than port rate */ + if (params->tb_rate == 0 || + params->tb_rate > rate) + return -11; + + /* TB size: non-zero */ + if (params->tb_size == 0) + return -12; + + /* TC rate: non-zero, less than pipe rate */ + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + if (params->tc_rate[i] == 0 || + params->tc_rate[i] > params->tb_rate) + return -13; + } + + /* TC period: non-zero */ + if (params->tc_period == 0) + return -14; + +#ifdef RTE_SCHED_SUBPORT_TC_OV + /* TC3 oversubscription weight: non-zero */ + if (params->tc_ov_weight == 0) + return -15; +#endif + + /* Queue WRR weights: non-zero */ + for (i = 0; i < RTE_SCHED_QUEUES_PER_PIPE; i++) { + if (params->wrr_weights[i] == 0) + return -16; + } + + return 0; +} + static int rte_sched_port_check_params(struct rte_sched_port_params *params) { - uint32_t i, j; + uint32_t i; if (params == NULL) return -1; /* socket */ - if ((params->socket < 0) || (params->socket >= RTE_MAX_NUMA_NODES)) + if (params->socket < 0) return -3; /* rate */ @@ -324,36 +354,11 @@ rte_sched_port_check_params(struct rte_sched_port_params *params) for (i = 0; i < params->n_pipe_profiles; i++) { struct rte_sched_pipe_params *p = params->pipe_profiles + i; + int status; - /* TB rate: non-zero, not greater than port rate */ - if (p->tb_rate == 0 || p->tb_rate > params->rate) - return -10; - - /* TB size: non-zero */ - if (p->tb_size == 0) - return -11; - - /* TC rate: non-zero, less than pipe rate */ - for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { - if (p->tc_rate[j] == 0 || p->tc_rate[j] > p->tb_rate) - return -12; - } - - /* TC period: non-zero */ - if (p->tc_period == 0) - return -13; - -#ifdef RTE_SCHED_SUBPORT_TC_OV - /* TC3 oversubscription weight: non-zero */ - if (p->tc_ov_weight == 0) - return -14; -#endif - - /* Queue WRR weights: non-zero */ - for (j = 0; j < RTE_SCHED_QUEUES_PER_PIPE; j++) { - if (p->wrr_weights[j] == 0) - return -15; - } + status = pipe_profile_check(p, params->rate); + if (status != 0) + return status; } return 0; @@ -514,69 +519,80 @@ rte_sched_time_ms_to_bytes(uint32_t time_ms, uint32_t rate) } static void -rte_sched_port_config_pipe_profile_table(struct rte_sched_port *port, struct rte_sched_port_params *params) +rte_sched_pipe_profile_convert(struct rte_sched_pipe_params *src, + struct rte_sched_pipe_profile *dst, + uint32_t rate) { - uint32_t i, j; + 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; + /* Token Bucket */ + if (src->tb_rate == rate) { + dst->tb_credits_per_period = 1; + dst->tb_period = 1; + } else { + double tb_rate = (double) src->tb_rate + / (double) rate; + double d = RTE_SCHED_TB_RATE_CONFIG_ERR; - /* Token Bucket */ - if (src->tb_rate == params->rate) { - dst->tb_credits_per_period = 1; - dst->tb_period = 1; - } else { - double tb_rate = (double) src->tb_rate - / (double) params->rate; - double d = RTE_SCHED_TB_RATE_CONFIG_ERR; - - rte_approx(tb_rate, d, - &dst->tb_credits_per_period, &dst->tb_period); - } - dst->tb_size = src->tb_size; + rte_approx(tb_rate, d, + &dst->tb_credits_per_period, &dst->tb_period); + } - /* Traffic Classes */ - dst->tc_period = rte_sched_time_ms_to_bytes(src->tc_period, - params->rate); + dst->tb_size = src->tb_size; - for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) - dst->tc_credits_per_period[j] - = rte_sched_time_ms_to_bytes(src->tc_period, - src->tc_rate[j]); + /* Traffic Classes */ + dst->tc_period = rte_sched_time_ms_to_bytes(src->tc_period, + rate); + + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) + dst->tc_credits_per_period[i] + = rte_sched_time_ms_to_bytes(src->tc_period, + src->tc_rate[i]); #ifdef RTE_SCHED_SUBPORT_TC_OV - dst->tc_ov_weight = src->tc_ov_weight; + dst->tc_ov_weight = src->tc_ov_weight; #endif - /* WRR */ - for (j = 0; j < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; j++) { - uint32_t wrr_cost[RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS]; - uint32_t lcd, lcd1, lcd2; - uint32_t qindex; - - qindex = j * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; - - wrr_cost[0] = src->wrr_weights[qindex]; - wrr_cost[1] = src->wrr_weights[qindex + 1]; - wrr_cost[2] = src->wrr_weights[qindex + 2]; - wrr_cost[3] = src->wrr_weights[qindex + 3]; - - lcd1 = rte_get_lcd(wrr_cost[0], wrr_cost[1]); - lcd2 = rte_get_lcd(wrr_cost[2], wrr_cost[3]); - lcd = rte_get_lcd(lcd1, lcd2); - - wrr_cost[0] = lcd / wrr_cost[0]; - wrr_cost[1] = lcd / wrr_cost[1]; - wrr_cost[2] = lcd / wrr_cost[2]; - wrr_cost[3] = lcd / wrr_cost[3]; - - dst->wrr_cost[qindex] = (uint8_t) wrr_cost[0]; - dst->wrr_cost[qindex + 1] = (uint8_t) wrr_cost[1]; - dst->wrr_cost[qindex + 2] = (uint8_t) wrr_cost[2]; - dst->wrr_cost[qindex + 3] = (uint8_t) wrr_cost[3]; - } + /* WRR */ + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { + uint32_t wrr_cost[RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS]; + uint32_t lcd, lcd1, lcd2; + uint32_t qindex; + + qindex = i * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS; + + wrr_cost[0] = src->wrr_weights[qindex]; + wrr_cost[1] = src->wrr_weights[qindex + 1]; + wrr_cost[2] = src->wrr_weights[qindex + 2]; + wrr_cost[3] = src->wrr_weights[qindex + 3]; + + lcd1 = rte_get_lcd(wrr_cost[0], wrr_cost[1]); + lcd2 = rte_get_lcd(wrr_cost[2], wrr_cost[3]); + lcd = rte_get_lcd(lcd1, lcd2); + + wrr_cost[0] = lcd / wrr_cost[0]; + wrr_cost[1] = lcd / wrr_cost[1]; + wrr_cost[2] = lcd / wrr_cost[2]; + wrr_cost[3] = lcd / wrr_cost[3]; + + dst->wrr_cost[qindex] = (uint8_t) wrr_cost[0]; + dst->wrr_cost[qindex + 1] = (uint8_t) wrr_cost[1]; + dst->wrr_cost[qindex + 2] = (uint8_t) wrr_cost[2]; + dst->wrr_cost[qindex + 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(src, dst, params->rate); rte_sched_port_log_pipe_profile(port, i); } @@ -602,7 +618,8 @@ rte_sched_port_config(struct rte_sched_port_params *params) return NULL; /* Allocate memory to store the data structures */ - port = rte_zmalloc("qos_params", mem_size, RTE_CACHE_LINE_SIZE); + port = rte_zmalloc_socket("qos_params", mem_size, RTE_CACHE_LINE_SIZE, + params->socket); if (port == NULL) return NULL; @@ -613,6 +630,8 @@ rte_sched_port_config(struct rte_sched_port_params *params) /* User parameters */ port->n_subports_per_port = params->n_subports_per_port; port->n_pipes_per_subport = params->n_pipes_per_subport; + port->n_pipes_per_subport_log2 = + __builtin_ctz(params->n_pipes_per_subport); port->rate = params->rate; port->mtu = params->mtu + params->frame_overhead; port->frame_overhead = params->frame_overhead; @@ -623,7 +642,7 @@ rte_sched_port_config(struct rte_sched_port_params *params) for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) { uint32_t j; - for (j = 0; j < e_RTE_METER_COLORS; 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) { @@ -635,6 +654,7 @@ rte_sched_port_config(struct rte_sched_port_params *params) 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; } } @@ -694,6 +714,7 @@ rte_sched_port_config(struct rte_sched_port_params *params) bmp_mem_size); if (port->bmp == NULL) { RTE_LOG(ERR, SCHED, "Bitmap init error\n"); + rte_free(port); return NULL; } @@ -932,44 +953,94 @@ rte_sched_pipe_config(struct rte_sched_port *port, return 0; } -void -rte_sched_port_pkt_write(struct rte_mbuf *pkt, - uint32_t subport, uint32_t pipe, uint32_t traffic_class, - uint32_t queue, enum rte_meter_color color) +int __rte_experimental +rte_sched_port_pipe_profile_add(struct rte_sched_port *port, + struct rte_sched_pipe_params *params, + uint32_t *pipe_profile_id) { - struct rte_sched_port_hierarchy *sched - = (struct rte_sched_port_hierarchy *) &pkt->hash.sched; + struct rte_sched_pipe_profile *pp; + uint32_t i; + int status; + + /* Port */ + if (port == NULL) + return -1; + + /* Pipe profiles not exceeds the max limit */ + if (port->n_pipe_profiles >= RTE_SCHED_PIPE_PROFILES_PER_PORT) + return -2; - RTE_BUILD_BUG_ON(sizeof(*sched) > sizeof(pkt->hash.sched)); + /* Pipe params */ + status = pipe_profile_check(params, port->rate); + if (status != 0) + return status; - sched->color = (uint32_t) color; - sched->subport = subport; - sched->pipe = pipe; - sched->traffic_class = traffic_class; - sched->queue = queue; + pp = &port->pipe_profiles[port->n_pipe_profiles]; + rte_sched_pipe_profile_convert(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) + return -3; + + /* Pipe profile commit */ + *pipe_profile_id = port->n_pipe_profiles; + port->n_pipe_profiles++; + + if (port->pipe_tc3_rate_max < params->tc_rate[3]) + port->pipe_tc3_rate_max = params->tc_rate[3]; + + rte_sched_port_log_pipe_profile(port, *pipe_profile_id); + + return 0; +} + +static inline uint32_t +rte_sched_port_qindex(struct rte_sched_port *port, + uint32_t subport, + uint32_t pipe, + uint32_t traffic_class, + uint32_t queue) +{ + return ((subport & (port->n_subports_per_port - 1)) << + (port->n_pipes_per_subport_log2 + 4)) | + ((pipe & (port->n_pipes_per_subport - 1)) << 4) | + ((traffic_class & + (RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE - 1)) << 2) | + (queue & (RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS - 1)); } void -rte_sched_port_pkt_read_tree_path(const struct rte_mbuf *pkt, +rte_sched_port_pkt_write(struct rte_sched_port *port, + struct rte_mbuf *pkt, + uint32_t subport, uint32_t pipe, + uint32_t traffic_class, + uint32_t queue, enum rte_color color) +{ + uint32_t queue_id = rte_sched_port_qindex(port, subport, pipe, + traffic_class, queue); + rte_mbuf_sched_set(pkt, queue_id, traffic_class, (uint8_t)color); +} + +void +rte_sched_port_pkt_read_tree_path(struct rte_sched_port *port, + const struct rte_mbuf *pkt, uint32_t *subport, uint32_t *pipe, uint32_t *traffic_class, uint32_t *queue) { - const struct rte_sched_port_hierarchy *sched - = (const struct rte_sched_port_hierarchy *) &pkt->hash.sched; + uint32_t queue_id = rte_mbuf_sched_queue_get(pkt); - *subport = sched->subport; - *pipe = sched->pipe; - *traffic_class = sched->traffic_class; - *queue = sched->queue; + *subport = queue_id >> (port->n_pipes_per_subport_log2 + 4); + *pipe = (queue_id >> 4) & (port->n_pipes_per_subport - 1); + *traffic_class = (queue_id >> 2) & + (RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE - 1); + *queue = queue_id & (RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS - 1); } -enum rte_meter_color +enum rte_color rte_sched_port_pkt_read_color(const struct rte_mbuf *pkt) { - const struct rte_sched_port_hierarchy *sched - = (const struct rte_sched_port_hierarchy *) &pkt->hash.sched; - - return (enum rte_meter_color) sched->color; + return (enum rte_color)rte_mbuf_sched_color_get(pkt); } int @@ -1026,18 +1097,6 @@ rte_sched_queue_read_stats(struct rte_sched_port *port, return 0; } -static inline uint32_t -rte_sched_port_qindex(struct rte_sched_port *port, uint32_t subport, uint32_t pipe, uint32_t traffic_class, uint32_t queue) -{ - uint32_t result; - - result = subport * port->n_pipes_per_subport + pipe; - result = result * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE + traffic_class; - result = result * RTE_SCHED_QUEUES_PER_TRAFFIC_CLASS + queue; - - return result; -} - #ifdef RTE_SCHED_DEBUG static inline int @@ -1129,7 +1188,7 @@ rte_sched_port_red_drop(struct rte_sched_port *port, struct rte_mbuf *pkt, uint3 struct rte_red_config *red_cfg; struct rte_red *red; uint32_t tc_index; - enum rte_meter_color color; + enum rte_color color; tc_index = (qindex >> 2) & 0x3; color = rte_sched_port_pkt_read_color(pkt); @@ -1198,11 +1257,8 @@ rte_sched_port_enqueue_qptrs_prefetch0(struct rte_sched_port *port, #ifdef RTE_SCHED_COLLECT_STATS struct rte_sched_queue_extra *qe; #endif - uint32_t subport, pipe, traffic_class, queue, qindex; - - rte_sched_port_pkt_read_tree_path(pkt, &subport, &pipe, &traffic_class, &queue); + uint32_t qindex = rte_mbuf_sched_queue_get(pkt); - qindex = rte_sched_port_qindex(port, subport, pipe, traffic_class, queue); q = port->queue + qindex; rte_prefetch0(q); #ifdef RTE_SCHED_COLLECT_STATS