summaryrefslogtreecommitdiff
path: root/src/ipcpd/unicast/psched.c
diff options
context:
space:
mode:
authorDimitri Staessens <dimitri@ouroboros.rocks>2026-07-21 04:45:48 +0000
committerSander Vrijders <sander@ouroboros.rocks>2026-07-22 09:04:33 +0200
commit1ee9c1cfb5ecffbf4766a6c05d333dab712f4e77 (patch)
tree26445677170b25e1c1b2cd61a4e61687006ec171 /src/ipcpd/unicast/psched.c
parent736de20b2b152c6124f5de1d1f4b9fb810119847 (diff)
downloadouroboros-1ee9c1cfb5ecffbf4766a6c05d333dab712f4e77.tar.gz
ouroboros-1ee9c1cfb5ecffbf4766a6c05d333dab712f4e77.zip
ipcpd: Process DT flows round-robin
The deadline scheduler kept draining the same flow with fevent() until its queue was empty, so a single greedy flow monopolizes the link. Now it does a per-packet round-robin to ensure each flow is served. Signed-off-by: Dimitri Staessens <dimitri@ouroboros.rocks> Signed-off-by: Sander Vrijders <sander@ouroboros.rocks>
Diffstat (limited to 'src/ipcpd/unicast/psched.c')
-rw-r--r--src/ipcpd/unicast/psched.c56
1 files changed, 36 insertions, 20 deletions
diff --git a/src/ipcpd/unicast/psched.c b/src/ipcpd/unicast/psched.c
index 2b535d67..01c4b066 100644
--- a/src/ipcpd/unicast/psched.c
+++ b/src/ipcpd/unicast/psched.c
@@ -116,6 +116,16 @@ static void dsched_untrack(struct dsched * d,
d->posn[fd] = -1;
}
+/* Fold a deadline into the earliest pending one (0 = none yet). */
+static uint64_t dmin_fold(uint64_t dmin,
+ uint64_t deadline)
+{
+ if (dmin == 0 || deadline < dmin)
+ return deadline;
+
+ return dmin;
+}
+
static uint64_t dsched_serve(struct dsched * d,
struct psched * sched,
qoscube_t qc,
@@ -126,31 +136,37 @@ static uint64_t dsched_serve(struct dsched * d,
size_t i;
int fd;
time_t wait;
+ bool served;
- for (i = 0; i < d->n; ) {
- fd = d->active[i];
+ /* Round-robin one packet per flow so none monopolises egress. */
+ do {
+ served = false;
- if (d->deadline[fd] > now) {
- if (dmin == 0 || d->deadline[fd] < dmin)
- dmin = d->deadline[fd];
- ++i;
- continue;
- }
+ for (i = 0; i < d->n; ) {
+ fd = d->active[i];
- if (sched->read(fd, &spb) < 0) {
- dsched_untrack(d, fd);
- continue;
- }
+ if (d->deadline[fd] > now) {
+ dmin = dmin_fold(dmin, d->deadline[fd]);
+ ++i;
+ continue;
+ }
- wait = sched->callback(fd, qc, spb);
- if (wait == 0)
- continue;
+ if (sched->read(fd, &spb) < 0) {
+ dsched_untrack(d, fd);
+ continue;
+ }
- d->deadline[fd] = now + (uint64_t) wait;
- if (dmin == 0 || d->deadline[fd] < dmin)
- dmin = d->deadline[fd];
- ++i;
- }
+ wait = sched->callback(fd, qc, spb);
+ served = true;
+
+ if (wait > 0) {
+ d->deadline[fd] = now + (uint64_t) wait;
+ dmin = dmin_fold(dmin, d->deadline[fd]);
+ }
+
+ ++i;
+ }
+ } while (served);
return dmin;
}