DPDK-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Pravin Pathak <pravinpathakdev@gmail.com>
To: dev@dpdk.org
Cc: jerinj@marvell.com, mike.ximing.chen@intel.com,
	bruce.richardson@intel.com, thomas@monjalon.net,
	david.marchand@redhat.com, nipun.gupta@amd.com,
	chenbox@nvidia.com, tirthendu.sarkar@intel.com,
	Pravin Pathak <pravin.pathak.dev@gmail.com>
Subject: [PATCH v1 7/8] event/slb: update resets and credit defaults
Date: Fri,  6 Nov 2026 20:30:09 -0500	[thread overview]
Message-ID: <20261107013011.2443138-8-pravinpathakdev@gmail.com> (raw)
In-Reply-To: <20261107013011.2443138-1-pravinpathakdev@gmail.com>

From: Pravin Pathak <pravin.pathak.dev@gmail.com>

- Force RTE_SCHED_TYPE_ATOMIC on events dequeued from single-link queues
  and skip atomic/ordered state allocations for single-link queues.
- Remove RTE_EVENT_DEV_CAP_RUNTIME_PORT_LINK advertisement from driver
  info, feature matrix, and release notes.
- Reset atomic queue flow-to-port mappings, hold buffers, migration
  state, per-port stats, ordered reorder buffers, and port history when
  the device is stopped in slb_stop().
- Default port new_event_threshold in slb_port_def_conf() to 1/4 of
  SLB_IN_RING_SIZE (clamped to nb_events_limit when configured) and
  lower SLB_MIN_CREDIT_LOAN from 512 to 256 so more ports can borrow
  credits concurrently.

Signed-off-by: Pravin Pathak <pravin.pathak.dev@gmail.com>
---
 doc/guides/eventdevs/features/slb.ini |  1 -
 doc/guides/eventdevs/slb.rst          | 31 ++++------
 drivers/event/slb/slb_evdev.c         | 81 +++++++++++++++++++++------
 drivers/event/slb/slb_evdev.h         |  5 +-
 drivers/event/slb/slb_event.c         | 23 ++++++--
 drivers/event/slb/slb_selftest.c      | 12 ++++
 6 files changed, 110 insertions(+), 43 deletions(-)

diff --git a/doc/guides/eventdevs/features/slb.ini b/doc/guides/eventdevs/features/slb.ini
index 0364840bc9..33036301a8 100644
--- a/doc/guides/eventdevs/features/slb.ini
+++ b/doc/guides/eventdevs/features/slb.ini
@@ -11,7 +11,6 @@ distributed_sched          = Y
 burst_mode                 = Y
 implicit_release_disable   = Y
 nonseq_mode                = Y
-runtime_port_link          = Y
 multiple_queue_port        = Y
 carry_flow_id              = Y
 maintenance_free           = Y
diff --git a/doc/guides/eventdevs/slb.rst b/doc/guides/eventdevs/slb.rst
index d319b94920..b109a1e2ca 100644
--- a/doc/guides/eventdevs/slb.rst
+++ b/doc/guides/eventdevs/slb.rst
@@ -4,9 +4,10 @@
 Software Load Balancer (SLB) Eventdev Driver
 ============================================
 
-The Software Load Balancer (SLB) event device is a poll-mode eventdev driver
-which distributes events among multiple worker ports and cores without requiring
-dedicated scheduling service cores or hardware coprocessors.
+The Software Load Balancer (SLB) is a software event device and a poll-mode Eventdev driver.
+It uses a distributed scheduler, allowing it to scale well. SLB does not require dedicated
+cores for scheduling. It supports Atomic, Parallel, and Ordered queues with dynamic atomic
+flow load balancing. SLB also requires no internal core communication and is maintenance-free.
 
 Features
 --------
@@ -19,25 +20,17 @@ Queues
 * **Atomic**: Flow-pinned scheduling guaranteeing strict per-flow packet ordering.
   Includes dynamic load tracking and automatic flow migration to rebalance overloaded
   ports while preserving in-flight sequence integrity.
-* **Ordered**: Ticket-based sequence tracking and reorder buffer providing end-to-end
-  packet order restoration across parallel processing workers.
-* **Single-Link**: Dedicated direct queue mapping from a producer port to a single
-  consumer port using optimized single-consumer rings.
+* **Ordered**: Sequence number-based tracking and reordering.
+* **Single-Link**: Implemented using optimized multi-producer single-consumer rings.
 
 Ports & Scheduling Capabilities
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-* **Distributed Scheduling**: No dedicated service core required; scheduling work is
-  performed inline during enqueue and dequeue operations.
-* **Prefix Sum Burst Enqueue**: Interleaved multi-queue bursts are grouped and scattered
-  via prefix-sum offsets, dispatching single batched bursts to queue rings to eliminate
-  atomic Compare-And-Swap contention on multi-producer rings.
+* **Distributed Scheduling**: No dedicated service core required.
 * **Dynamic Flow Migration**: Atomic queues monitor port dequeue loads and migrate
-  eligible victim flows from overloaded ports to underloaded ports with cooling cycles.
+  Eligible flows from overloaded ports to underloaded ports with cooling cycles.
 * **Credit Pool Management**: Centralized event credit pool with per-port credit caching
   to enforce device-wide in-flight event limits (``max_num_events``).
-* **Runtime Port Linking**: Supports dynamic linking and unlinking of ports and queues
-  both when stopped and at runtime.
 * **Maintenance Free**: Operates without requiring periodic maintenance calls
   (``RTE_EVENT_DEV_CAP_MAINTENANCE_FREE``).
 
@@ -62,7 +55,7 @@ application code or from the EAL command line:
 Limitations
 -----------
 
-* **Flow Hash Table Size**: Atomic queues use an internal flow mapping table
-  dimensioned to 2048 concurrent active flows per queue (``SLB_ATOMIC_FLOWS``).
-* **Maximum Ports and Queues**: Configured for up to 64 ports (``SLB_MAX_PORTS``)
-  and 64 queues (``SLB_MAX_QUEUES``).
+* **Maximum Ports and Queues**: Supports up to 64 ports and 64 queues.
+* **Priorities and linking**: Supports two levels of service priority to link up to
+  eight queues per port at each priority. SLB currently does not support event priority.
+* **Queues Types**: Does not support all-type queues.
diff --git a/drivers/event/slb/slb_evdev.c b/drivers/event/slb/slb_evdev.c
index c86b934b03..16bfefaa68 100644
--- a/drivers/event/slb/slb_evdev.c
+++ b/drivers/event/slb/slb_evdev.c
@@ -26,6 +26,7 @@ slb_port_reset_history(struct slb_port *port)
 {
 	port->history[0].active = false;
 	port->history[0].next_free = SLB_PORT_HISTORY_FREE_END;
+	/* 1 -> 2 -> 3 ..... 255 -> END */
 	for (int i = 1; i < SLB_PORT_HISTORY_SIZE; i++) {
 		port->history[i].active = false;
 		port->history[i].next_free = i + 1;
@@ -36,7 +37,7 @@ slb_port_reset_history(struct slb_port *port)
 	port->history_avail = SLB_PORT_HISTORY_MAX_TOKENS;
 }
 
-/* Setup Eventdev port. Reset all mapped queues */
+/* Setup Eventdev port. Reset all mapped queues and history tracking */
 static int
 slb_port_setup(struct rte_eventdev *dev, uint8_t port_id,
 	       const struct rte_event_port_conf *conf)
@@ -103,12 +104,18 @@ slb_port_setup(struct rte_eventdev *dev, uint8_t port_id,
 
 /* Default Eventdev port configuration for SLB */
 static void
-slb_port_def_conf(struct rte_eventdev *dev __rte_unused,
+slb_port_def_conf(struct rte_eventdev *dev,
 		  uint8_t port_id __rte_unused,
 		  struct rte_event_port_conf *port_conf)
 {
+	int32_t threshold = SLB_IN_RING_SIZE / 4;
+
+	if (dev->data->dev_conf.nb_events_limit > 0 &&
+	    threshold > dev->data->dev_conf.nb_events_limit)
+		threshold = dev->data->dev_conf.nb_events_limit;
+
 	*port_conf = (struct rte_event_port_conf) {
-		.new_event_threshold = 1024,
+		.new_event_threshold = threshold,
 		.dequeue_depth = SLB_MAX_PORT_DEQUEUE_DEPTH / 4,
 		.enqueue_depth = SLB_MAX_PORT_ENQUEUE_DEPTH / 4
 	};
@@ -146,7 +153,9 @@ slb_queue_release(struct rte_eventdev *dev, uint8_t queue_id)
 	}
 }
 
-/* Setup Eventdev queue. Eventdev queues are implemented as DPDK rings */
+/* Setup Eventdev queue. Eventdev queues are implemented as DPDK rings.
+ *  SLB Supports single-link, atomic, parallel, and ordered queues.
+ */
 static int
 slb_queue_setup(struct rte_eventdev *dev, uint8_t queue_id,
 		const struct rte_event_queue_conf *conf)
@@ -190,12 +199,15 @@ slb_queue_setup(struct rte_eventdev *dev, uint8_t queue_id,
 		return -ENOMEM;
 
 	queue->q_ring = ring;
-	queue->schedule_type = conf->schedule_type;
+	/* Single-link queue uses atomic schedule type */
+	queue->schedule_type = queue->is_single_link ?
+			       RTE_SCHED_TYPE_ATOMIC : conf->schedule_type;
 	queue->serving_ports_mask = 0;
 	queue->num_serving_ports = 0;
 
-	/* Atomic queue allocation */
-	if (conf->schedule_type == RTE_SCHED_TYPE_ATOMIC) {
+	/* Atomic queue state allocation */
+	if (!queue->is_single_link &&
+	    conf->schedule_type == RTE_SCHED_TYPE_ATOMIC) {
 		for (int i = 0; i < SLB_MAX_PORTS; i++)
 			queue->per_port_rings[i] = NULL;
 
@@ -224,7 +236,8 @@ slb_queue_setup(struct rte_eventdev *dev, uint8_t queue_id,
 	}
 
 	/* Ordered queue reorder buffer allocation */
-	if (conf->schedule_type == RTE_SCHED_TYPE_ORDERED) {
+	if (!queue->is_single_link &&
+	    conf->schedule_type == RTE_SCHED_TYPE_ORDERED) {
 		queue->reorder_buffer = rte_zmalloc_socket("slb_reorder_buf",
 			sizeof(struct slb_reorder_entry) * ring->r.size,
 			RTE_CACHE_LINE_SIZE, dev->data->socket_id);
@@ -293,7 +306,8 @@ slb_port_link_one(struct slb_port *port, struct slb_queue *queue,
 		port->single_linked_q = queue;
 		port->single_linked_ring = queue->q_ring;
 	} else {
-		if (queue->schedule_type == RTE_SCHED_TYPE_ATOMIC &&
+		if (!queue->is_single_link &&
+		    queue->schedule_type == RTE_SCHED_TYPE_ATOMIC &&
 		    queue->per_port_rings[port->id] == NULL) {
 			char ring_name[RTE_RING_NAMESIZE];
 			struct rte_event_ring *ring;
@@ -332,7 +346,8 @@ slb_port_link_one(struct slb_port *port, struct slb_queue *queue,
 		if (!found) {
 			uint16_t slot = port->num_q[prio];
 			struct rte_event_ring *dq_ring =
-				(queue->schedule_type == RTE_SCHED_TYPE_ATOMIC) ?
+				(!queue->is_single_link &&
+				 queue->schedule_type == RTE_SCHED_TYPE_ATOMIC) ?
 				queue->per_port_rings[port->id] : queue->q_ring;
 
 			if (slot >= SLB_PORT_MAX_Q_MAP_PER_PRIO) {
@@ -344,6 +359,8 @@ slb_port_link_one(struct slb_port *port, struct slb_queue *queue,
 			port->q_entries[prio][slot].queue_id = qid;
 			port->q_entries[prio][slot].schedule_type =
 				queue->schedule_type;
+			port->q_entries[prio][slot].is_single_link =
+				queue->is_single_link;
 			port->num_q[prio]++;
 		}
 
@@ -464,7 +481,6 @@ slb_info_get(struct rte_eventdev *dev __rte_unused,
 		RTE_EVENT_DEV_CAP_IMPLICIT_RELEASE_DISABLE |
 		RTE_EVENT_DEV_CAP_NONSEQ_MODE |
 		RTE_EVENT_DEV_CAP_MULTIPLE_QUEUE_PORT |
-		RTE_EVENT_DEV_CAP_RUNTIME_PORT_LINK |
 		RTE_EVENT_DEV_CAP_CARRY_FLOW_ID |
 		RTE_EVENT_DEV_CAP_MAINTENANCE_FREE |
 		RTE_EVENT_DEV_CAP_INDEPENDENT_ENQ
@@ -555,22 +571,52 @@ slb_stop(struct rte_eventdev *dev)
 	for (uint8_t qid = 0; qid < slb->num_queues; qid++) {
 		struct slb_queue *q = &slb->queues[qid];
 
-		if (q->schedule_type == RTE_SCHED_TYPE_ATOMIC && q->atomic_state != NULL) {
+		if (q->schedule_type == RTE_SCHED_TYPE_ATOMIC &&
+		    q->atomic_state != NULL) {
+			struct slb_atomic_state *astate = q->atomic_state;
+
+			for (uint16_t h = 0; h < astate->hold_count; h++) {
+				if (flush != NULL)
+					flush(dev_id, astate->hold_buffer[h],
+					      flush_arg);
+			}
+			astate->hold_count = 0;
+			astate->next_port_rr = 0;
+			astate->migration.in_progress = false;
+
 			for (int f = 0; f < SLB_ATOMIC_FLOWS; f++) {
 				rte_atomic_store_explicit(
-					&q->atomic_state->flow_map.flows[f].port_id,
+					&astate->flow_map.flows[f].port_id,
 					-1, rte_memory_order_relaxed);
-				q->atomic_state->flow_last_migrated[f] = 0;
+				astate->flow_last_migrated[f] = 0;
 			}
-			q->atomic_state->migration.in_progress = false;
+
+			memset(astate->port_stats, 0,
+			       sizeof(astate->port_stats));
 
 			for (uint16_t pid = 0; pid < slb->num_ports; pid++) {
-				q->atomic_state->port_stats[pid].load_counter = 0;
 				if (q->per_port_rings[pid] != NULL)
 					slb_drain_ring(dev_id,
 						       q->per_port_rings[pid],
 						       flush, flush_arg);
 			}
+		} else if (q->schedule_type == RTE_SCHED_TYPE_ORDERED &&
+			   q->reorder_buffer != NULL && q->q_ring != NULL) {
+			for (uint32_t s = 0; s < q->q_ring->r.size; s++) {
+				uint8_t st = rte_atomic_load_explicit(
+					&q->reorder_buffer[s].state,
+					rte_memory_order_relaxed);
+
+				if (st == SLB_REORDER_READY && flush != NULL)
+					flush(dev_id,
+					      q->reorder_buffer[s].event,
+					      flush_arg);
+				rte_atomic_store_explicit(
+					&q->reorder_buffer[s].state,
+					SLB_REORDER_EMPTY,
+					rte_memory_order_relaxed);
+			}
+			q->reorder_drain_idx = 0;
 		}
 
 		if (q->q_ring != NULL)
@@ -581,7 +627,10 @@ slb_stop(struct rte_eventdev *dev)
 		struct slb_port *port = &slb->ports[i];
 		port->inflight_credits = 0;
 		port->credits_drained = false;
+		port->pending_releases = 0;
 		port->is_loaded = false;
+		port->last_migrated_time = 0;
+		slb_port_reset_history(port);
 		for (int p = 0; p < SLB_MAX_PRIORITIES; p++)
 			port->next_q[p] = 0;
 	}
diff --git a/drivers/event/slb/slb_evdev.h b/drivers/event/slb/slb_evdev.h
index f727a1b83c..bf262903cd 100644
--- a/drivers/event/slb/slb_evdev.h
+++ b/drivers/event/slb/slb_evdev.h
@@ -28,7 +28,7 @@
 #define SLB_MAX_FLOWS_MASK (SLB_MAX_FLOWS - 1)
 
 /* Avoid making small 'loans' from the central in-flight event credit pool */
-#define SLB_MIN_CREDIT_LOAN (512)
+#define SLB_MIN_CREDIT_LOAN (256)
 #define SLB_PORT_MAX_CREDITS (2 * SLB_MIN_CREDIT_LOAN)
 #define SLB_PORT_MIN_CREDITS (SLB_MIN_CREDIT_LOAN)
 
@@ -56,7 +56,8 @@ struct slb_port_q_entry {
 	struct slb_queue *queue;
 	uint8_t queue_id;
 	uint8_t schedule_type;
-	uint8_t pad[6];
+	bool is_single_link;
+	uint8_t pad[5];
 };
 
 #define SLB_PORT_HISTORY_SIZE 256
diff --git a/drivers/event/slb/slb_event.c b/drivers/event/slb/slb_event.c
index 3a0f7f6fde..c44deba905 100644
--- a/drivers/event/slb/slb_event.c
+++ b/drivers/event/slb/slb_event.c
@@ -976,8 +976,10 @@ slb_port_dequeue(struct slb_port *port, struct rte_event events[],
 			return 0;
 		dequeued = rte_event_ring_dequeue_burst(port->single_linked_ring,
 							events, num, NULL);
-		for (uint16_t j = 0; j < dequeued; j++)
+		for (uint16_t j = 0; j < dequeued; j++) {
+			events[j].sched_type = RTE_SCHED_TYPE_ATOMIC;
 			events[j].impl_opaque = 0;
+		}
 		return dequeued;
 	}
 
@@ -1015,8 +1017,11 @@ slb_port_dequeue(struct slb_port *port, struct rte_event events[],
 				continue;
 
 			uint8_t sched_type = qent->schedule_type;
-			bool is_ordered = (sched_type == RTE_SCHED_TYPE_ORDERED);
-			bool is_atomic = (sched_type == RTE_SCHED_TYPE_ATOMIC);
+			bool is_single_link = qent->is_single_link;
+			bool is_ordered = !is_single_link &&
+					  (sched_type == RTE_SCHED_TYPE_ORDERED);
+			bool is_atomic = !is_single_link &&
+					 (sched_type == RTE_SCHED_TYPE_ATOMIC);
 
 			if (is_ordered || is_atomic) {
 				if (unlikely(port->history_avail == 0))
@@ -1050,8 +1055,16 @@ slb_port_dequeue(struct slb_port *port, struct rte_event events[],
 			} else {
 				dequeued = rte_event_ring_dequeue_burst(
 					ring_to_dq, events, num, NULL);
-				for (uint16_t j = 0; j < dequeued; j++)
-					events[j].impl_opaque = 0;
+				if (is_single_link) {
+					for (uint16_t j = 0; j < dequeued; j++) {
+						events[j].sched_type =
+							RTE_SCHED_TYPE_ATOMIC;
+						events[j].impl_opaque = 0;
+					}
+				} else {
+					for (uint16_t j = 0; j < dequeued; j++)
+						events[j].impl_opaque = 0;
+				}
 			}
 
 			if (dequeued > 0) {
diff --git a/drivers/event/slb/slb_selftest.c b/drivers/event/slb/slb_selftest.c
index 4a072b811b..776b6d6ab4 100644
--- a/drivers/event/slb/slb_selftest.c
+++ b/drivers/event/slb/slb_selftest.c
@@ -362,6 +362,12 @@ test_ordered_forward(void)
 					     cons_rx, rx[i].u64);
 				return -1;
 			}
+			if (rx[i].sched_type != RTE_SCHED_TYPE_ATOMIC) {
+				SLB_LOG_LINE(ERR,
+					     "Single-link dequeue sched_type expected %u, got %u",
+					     RTE_SCHED_TYPE_ATOMIC, rx[i].sched_type);
+				return -1;
+			}
 			cons_rx++;
 			rx[i].op = RTE_EVENT_OP_RELEASE;
 		}
@@ -416,6 +422,12 @@ test_single_link(void)
 	for (i = 0; i < 16; i++) {
 		if (rx[i].u64 != (uint64_t)(5000 + i))
 			return -1;
+		if (rx[i].sched_type != RTE_SCHED_TYPE_ATOMIC) {
+			SLB_LOG_LINE(ERR,
+				     "Single-link dequeue sched_type expected %u, got %u",
+				     RTE_SCHED_TYPE_ATOMIC, rx[i].sched_type);
+			return -1;
+		}
 		rx[i].op = RTE_EVENT_OP_RELEASE;
 	}
 	rte_event_enqueue_burst(g_dev_id, PORT_CONS, rx, 16);
-- 
2.53.0


  parent reply	other threads:[~2026-11-07  1:31 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-07  1:30 [PATCH v1 0/8] event/slb: introducing software load balancer eventdev PMD Pravin Pathak
2026-11-07  1:30 ` [PATCH v1 1/8] event/slb: introduce software load balancer PMD Pravin Pathak
2026-11-07  1:30 ` [PATCH v1 2/8] event/slb: add support for ordered queues Pravin Pathak
2026-11-07  1:30 ` [PATCH v1 3/8] event/slb: add support for atomic queues Pravin Pathak
2026-11-07  1:30 ` [PATCH v1 4/8] event/slb: add dynamic flow migration " Pravin Pathak
2026-11-07  1:30 ` [PATCH v1 5/8] event/slb: add extended statistics and diagnostics Pravin Pathak
2026-11-07  1:30 ` [PATCH v1 6/8] event/slb: add self-test and documentation Pravin Pathak
2026-11-07  1:30 ` Pravin Pathak [this message]
2026-11-07  1:30 ` [PATCH v1 8/8] event/slb: improve port linking, config checks and atomic refill Pravin Pathak
2026-11-07  7:29 ` [PATCH v1 0/8] event/slb: introducing software load balancer eventdev PMD Jerin Jacob
2026-11-08 17:10   ` Stephen Hemminger
2026-11-09  2:30   ` Pravin Pathak
2026-11-09 12:55     ` Jerin Jacob
2026-11-11 14:22       ` Sarkar, Tirthendu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261107013011.2443138-8-pravinpathakdev@gmail.com \
    --to=pravinpathakdev@gmail.com \
    --cc=bruce.richardson@intel.com \
    --cc=chenbox@nvidia.com \
    --cc=david.marchand@redhat.com \
    --cc=dev@dpdk.org \
    --cc=jerinj@marvell.com \
    --cc=mike.ximing.chen@intel.com \
    --cc=nipun.gupta@amd.com \
    --cc=pravin.pathak.dev@gmail.com \
    --cc=thomas@monjalon.net \
    --cc=tirthendu.sarkar@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox