public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
From: David Gibson <david@gibson.dropbear.id.au>
To: Laurent Vivier <lvivier@redhat.com>
Cc: passt-dev@passt.top
Subject: Re: [PATCH v2 05/10] flow: Make flow timer per-caller for thread safety
Date: Mon, 3 Aug 2026 16:11:24 +1000	[thread overview]
Message-ID: <anAw_cEP3vlV4er_@zatzit> (raw)
In-Reply-To: <20260731162329.3552800-6-lvivier@redhat.com>

[-- Attachment #1: Type: text/plain, Size: 5094 bytes --]

On Fri, Jul 31, 2026 at 06:23:24PM +0200, Laurent Vivier wrote:
> Move the static flow_timer_run variable out of flow.c and pass it as a
> parameter to flow_defer_handler().  This allows each caller to maintain
> its own timer state: each vhost-user queue pair worker uses the per-qpair
> context.
> 
> Signed-off-by: Laurent Vivier <lvivier@redhat.com>

One small misgiving about this, although I doubt it can cause a real
problem.  Becayse this timer processing now doesn't happen all at
once, at each queue is on a separate timer cycle, it's theoretically
possible for a flow to change qpair every FLOW_TIMER_INTERVAL and
thereby indefinitely avoid having the timer running on it.

It's pretty tricky to do (depending on how close in real time each
queue's timers end up running), and I don't *think* that can do
anything terribly bad (maybe delay cleanup).  But since the guest
could in principle control the qpair placements to specifically
trigger this, it just makes me think it warrants a good close look to
make sure that something bad can't be triggered that way.

> ---
>  flow.c  | 10 ++++------
>  flow.h  |  2 +-
>  passt.c |  8 +++++---
>  3 files changed, 10 insertions(+), 10 deletions(-)
> 
> diff --git a/flow.c b/flow.c
> index 1efa9b966991..59963ea5b1c2 100644
> --- a/flow.c
> +++ b/flow.c
> @@ -142,9 +142,6 @@ static flow_sidx_t flow_hashtab[FLOW_HASH_SIZE];
>  static_assert(ARRAY_SIZE(flow_hashtab) >= 2 * FLOW_MAX,
>  "Safe linear probing requires hash table with more entries than the number of sides in the flow table");
>  
> -/* Last time the flow timers ran */
> -static struct timespec flow_timer_run;
> -
>  /** flowside_from_af() - Initialise flowside from addresses
>   * @side:	flowside to initialise
>   * @af:		Address family (AF_INET or AF_INET6)
> @@ -875,10 +872,11 @@ flow_sidx_t flow_lookup_sa(const struct ctx *c, uint8_t proto, uint8_t pif,
>   * flow_defer_handler() - Handler for per-flow deferred and timed tasks
>   * @c:		Execution context
>   * @now:	Current timestamp
> + * @timer_run:	Last time the flow timers ran
>   * @qpair:	Queue pair to process
>   */
>  void flow_defer_handler(const struct ctx *c, const struct timespec *now,
> -			unsigned int qpair)
> +			struct timespec *timer_run, unsigned int qpair)
>  {
>  	struct flow_free_cluster *free_head = NULL;
>  	unsigned *last_next = &flow_first_free;
> @@ -886,9 +884,9 @@ void flow_defer_handler(const struct ctx *c, const struct timespec *now,
>  	bool timer = false;
>  	union flow *flow;
>  
> -	if (timespec_diff_ms(now, &flow_timer_run) >= FLOW_TIMER_INTERVAL) {
> +	if (timespec_diff_ms(now, timer_run) >= FLOW_TIMER_INTERVAL) {
>  		timer = true;
> -		flow_timer_run = *now;
> +		*timer_run = *now;
>  	}
>  
>  	assert(!flow_new_entry); /* Incomplete flow at end of cycle */
> diff --git a/flow.h b/flow.h
> index 028d42bccc0c..ac1d3897ca98 100644
> --- a/flow.h
> +++ b/flow.h
> @@ -272,7 +272,7 @@ int flow_epoll_set(const struct flow_common *f, int command, uint32_t events,
>  		   int fd, unsigned int sidei);
>  
>  void flow_defer_handler(const struct ctx *c, const struct timespec *now,
> -			unsigned int qpair);
> +			struct timespec *timer_run, unsigned int qpair);
>  int flow_migrate_source_early(struct ctx *c, const struct migrate_stage *stage,
>  			      int fd);
>  int flow_migrate_source_pre(struct ctx *c, const struct migrate_stage *stage,
> diff --git a/passt.c b/passt.c
> index bc9f1575ef8c..69fd7b12450a 100644
> --- a/passt.c
> +++ b/passt.c
> @@ -108,15 +108,16 @@ struct passt_stats {
>   * post_handler() - Run periodic and deferred tasks for L4 protocol handlers
>   * @c:		Execution context
>   * @now:	Current timestamp
> + * @timer_run:	Last time the flow timers ran
>   * @qpair:	Queue pair to process
>   */
>  static void post_handler(struct ctx *c, const struct timespec *now,
> -			 unsigned int qpair)
> +			 struct timespec *timer_run, unsigned int qpair)
>  {
>  	if (!c->no_tcp)
>  		tcp_defer_handler(c, now, qpair);
>  
> -	flow_defer_handler(c, now, qpair);
> +	flow_defer_handler(c, now, timer_run, qpair);
>  	fwd_scan_ports_timer(c, now);
>  
>  	if (!c->no_ndp)
> @@ -231,6 +232,7 @@ static void print_stats(const struct ctx *c, const struct passt_stats *stats,
>  static void passt_worker(void *opaque, int nfds, struct epoll_event *events)
>  {
>  	static struct passt_stats stats = { 0 };
> +	static struct timespec flow_timer_run;
>  	struct ctx *c = opaque;
>  	struct timespec now;
>  	int i;
> @@ -314,7 +316,7 @@ static void passt_worker(void *opaque, int nfds, struct epoll_event *events)
>  		print_stats(c, &stats, &now);
>  	}
>  
> -	post_handler(c, &now, QPAIR_DEFAULT);
> +	post_handler(c, &now, &flow_timer_run, QPAIR_DEFAULT);
>  
>  	migrate_handler(c, &now);
>  }
> -- 
> 2.54.0
> 

-- 
David Gibson (he or they)	| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you, not the other way
				| around.
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

  reply	other threads:[~2026-08-03  6:11 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-31 16:23 [PATCH v2 00/10] multithreading: Prepare data structures for concurrent queue pair workers Laurent Vivier
2026-07-31 16:23 ` [PATCH v2 01/10] tap: Convert packet pools to per-queue-pair arrays for multiqueue Laurent Vivier
2026-08-03  5:41   ` David Gibson
2026-07-31 16:23 ` [PATCH v2 02/10] tap: Make L4 sequence pools per-qpair for thread safety Laurent Vivier
2026-08-03  5:43   ` David Gibson
2026-08-03  5:55     ` David Gibson
2026-07-31 16:23 ` [PATCH v2 03/10] tcp: Make static buffers stack-local " Laurent Vivier
2026-08-03  5:59   ` David Gibson
2026-07-31 16:23 ` [PATCH v2 04/10] udp_vu: Make virtqueue " Laurent Vivier
2026-08-03  6:00   ` David Gibson
2026-07-31 16:23 ` [PATCH v2 05/10] flow: Make flow timer per-caller " Laurent Vivier
2026-08-03  6:11   ` David Gibson [this message]
2026-08-03  6:35     ` David Gibson
2026-07-31 16:23 ` [PATCH v2 06/10] tcp: Make TCP timer state per-caller and guard global tasks Laurent Vivier
2026-08-03  6:40   ` David Gibson
2026-07-31 16:23 ` [PATCH v2 07/10] tcp: Protect init socket pools with mutex for thread safety Laurent Vivier
2026-08-03  6:53   ` David Gibson
2026-07-31 16:23 ` [PATCH v2 08/10] tcp: Extract tcp_timer_epoll_add() helper Laurent Vivier
2026-08-03  6:54   ` David Gibson
2026-07-31 16:23 ` [PATCH v2 09/10] flow: Add locking, per-qpair filtering, and intermediate state handling Laurent Vivier
2026-08-03  9:58   ` David Gibson
2026-07-31 16:23 ` [PATCH v2 10/10] flow: Add lazy, lock-free flow migration between queue pairs Laurent Vivier

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=anAw_cEP3vlV4er_@zatzit \
    --to=david@gibson.dropbear.id.au \
    --cc=lvivier@redhat.com \
    --cc=passt-dev@passt.top \
    /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.
Code repositories for project(s) associated with this public inbox

	https://passt.top/passt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).