To reduce flow migration overhead, replace the array-based representation of which set of ports are bound to a particular queue by a multi-word bitset.
Signed-off-by: Mattias Rönnblom <mattias.ronnb...@ericsson.com> --- drivers/event/dsw/dsw_evdev.c | 34 +++++++++++++++++++--------------- drivers/event/dsw/dsw_evdev.h | 3 ++- drivers/event/dsw/dsw_event.c | 11 ++++------- 3 files changed, 25 insertions(+), 23 deletions(-) diff --git a/drivers/event/dsw/dsw_evdev.c b/drivers/event/dsw/dsw_evdev.c index 1209e73a9d..a0781e4141 100644 --- a/drivers/event/dsw/dsw_evdev.c +++ b/drivers/event/dsw/dsw_evdev.c @@ -118,6 +118,7 @@ dsw_queue_setup(struct rte_eventdev *dev, uint8_t queue_id, queue->schedule_type = conf->schedule_type; } + rte_bitset_init(queue->serving_ports, DSW_MAX_PORTS); queue->num_serving_ports = 0; return 0; @@ -144,24 +145,19 @@ dsw_queue_release(struct rte_eventdev *dev __rte_unused, static void queue_add_port(struct dsw_queue *queue, uint16_t port_id) { - queue->serving_ports[queue->num_serving_ports] = port_id; + rte_bitset_set(queue->serving_ports, port_id); queue->num_serving_ports++; } static bool queue_remove_port(struct dsw_queue *queue, uint16_t port_id) { - uint16_t i; + if (rte_bitset_test(queue->serving_ports, port_id)) { + queue->num_serving_ports--; + rte_bitset_clear(queue->serving_ports, port_id); + return true; + } - for (i = 0; i < queue->num_serving_ports; i++) - if (queue->serving_ports[i] == port_id) { - uint16_t last_idx = queue->num_serving_ports - 1; - if (i != last_idx) - queue->serving_ports[i] = - queue->serving_ports[last_idx]; - queue->num_serving_ports--; - return true; - } return false; } @@ -256,10 +252,18 @@ initial_flow_to_port_assignment(struct dsw_evdev *dsw) struct dsw_queue *queue = &dsw->queues[queue_id]; uint16_t flow_hash; for (flow_hash = 0; flow_hash < DSW_MAX_FLOWS; flow_hash++) { - uint8_t port_idx = - rte_rand() % queue->num_serving_ports; - uint8_t port_id = - queue->serving_ports[port_idx]; + uint8_t skip = rte_rand_max(queue->num_serving_ports); + uint8_t port_id; + + for (port_id = 0;; port_id++) { + if (rte_bitset_test(queue->serving_ports, + port_id)) { + if (skip == 0) + break; + skip--; + } + } + dsw->queues[queue_id].flow_to_port_map[flow_hash] = port_id; } diff --git a/drivers/event/dsw/dsw_evdev.h b/drivers/event/dsw/dsw_evdev.h index 6416a8a898..503a63cbb2 100644 --- a/drivers/event/dsw/dsw_evdev.h +++ b/drivers/event/dsw/dsw_evdev.h @@ -7,6 +7,7 @@ #include <eventdev_pmd.h> +#include <rte_bitset.h> #include <rte_event_ring.h> #include <rte_eventdev.h> @@ -234,7 +235,7 @@ struct dsw_port { struct dsw_queue { uint8_t schedule_type; - uint8_t serving_ports[DSW_MAX_PORTS]; + RTE_BITSET_DECLARE(serving_ports, DSW_MAX_PORTS); uint16_t num_serving_ports; uint8_t flow_to_port_map[DSW_MAX_FLOWS] __rte_cache_aligned; diff --git a/drivers/event/dsw/dsw_event.c b/drivers/event/dsw/dsw_event.c index 93bbeead2e..b855f9ecf1 100644 --- a/drivers/event/dsw/dsw_event.c +++ b/drivers/event/dsw/dsw_event.c @@ -447,13 +447,8 @@ static bool dsw_is_serving_port(struct dsw_evdev *dsw, uint8_t port_id, uint8_t queue_id) { struct dsw_queue *queue = &dsw->queues[queue_id]; - uint16_t i; - - for (i = 0; i < queue->num_serving_ports; i++) - if (queue->serving_ports[i] == port_id) - return true; - return false; + return rte_bitset_test(queue->serving_ports, port_id); } static bool @@ -575,7 +570,9 @@ dsw_schedule(struct dsw_evdev *dsw, uint8_t queue_id, uint16_t flow_hash) /* A single-link queue, or atomic/ordered/parallel but * with just a single serving port. */ - port_id = queue->serving_ports[0]; + port_id = (uint8_t)rte_bitset_find_first_set( + queue->serving_ports, DSW_MAX_PORTS + ); DSW_LOG_DP(DEBUG, "Event with queue_id %d flow_hash %d is scheduled " "to port %d.\n", queue_id, flow_hash, port_id); -- 2.34.1