All of lore.kernel.org
 help / color / mirror / Atom feed
From: Pablo Neira Ayuso <pablo@netfilter.org>
To: netfilter-devel@vger.kernel.org
Cc: fw@strlen.de
Subject: Re: [PATCH nf,v3] netfilter: nfnetlink_queue: hash queue instance by portid too
Date: Wed, 23 Sep 2026 22:04:05 +0200	[thread overview]
Message-ID: <arQwtSh6BNUZ8BsJ@chamomile> (raw)
In-Reply-To: <20260923184047.48492-1-pablo@netfilter.org>

On Wed, Sep 23, 2026 at 08:40:46PM +0200, Pablo Neira Ayuso wrote:
> netlink_release() calls netlink_remove() before delivering the
> NETLINK_URELEASE event. And a new queue instance can be created before
> delivering such NETLINK_URELEASE event. This allows for two different
> queue instances with the same portid to co-exist for a little while.
> Since the instance that is going away is destroyed by portid via netlink
> notifier, both the newly created instance and the one that is going away
> with the same portid are destroyed.

It seems I cannot fix this in this way. I forgot same socket can be
bound to several queues.

> Fixes: 7af4cc3fa158 ("[NETFILTER]: Add "nfnetlink_queue" netfilter queue handler over nfnetlink")
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
> ---
> v3: - use siphash instead of lazy hash
>     - fix incorrect hlist and wrong instance_lookup_by_portid()
> 
>  net/netfilter/nfnetlink_queue.c | 36 +++++++++++++++++++++++++++++++--
>  1 file changed, 34 insertions(+), 2 deletions(-)
> 
> diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
> index c727668b0c5b..a2086c192063 100644
> --- a/net/netfilter/nfnetlink_queue.c
> +++ b/net/netfilter/nfnetlink_queue.c
> @@ -69,6 +69,7 @@
>  
>  struct nfqnl_instance {
>  	struct hlist_node hlist;		/* global list of queues */
> +	struct hlist_node hlist_portid;		/* global list of queues, by portid */
>  	struct rhashtable nfqnl_packet_map;
>  	struct rcu_work	rwork;
>  
> @@ -96,11 +97,13 @@ typedef int (*nfqnl_cmpfn)(struct nf_queue_entry *, unsigned long);
>  
>  static struct workqueue_struct *nfq_cleanup_wq __read_mostly;
>  static unsigned int nfnl_queue_net_id __read_mostly;
> +static siphash_aligned_key_t nfnl_queue_hash_key;
>  
>  #define INSTANCE_BUCKETS	16
>  struct nfnl_queue_net {
>  	spinlock_t instances_lock;
>  	struct hlist_head instance_table[INSTANCE_BUCKETS];
> +	struct hlist_head instance_table_portid[INSTANCE_BUCKETS];
>  };
>  
>  static struct nfnl_queue_net *nfnl_queue_pernet(struct net *net)
> @@ -113,6 +116,15 @@ static inline u_int8_t instance_hashfn(u_int16_t queue_num)
>  	return ((queue_num >> 8) ^ queue_num) % INSTANCE_BUCKETS;
>  }
>  
> +static inline u8 instance_portid_hashfn(u32 portid)
> +{
> +	u64 hash = siphash_1u32(portid, &nfnl_queue_hash_key);
> +
> +	net_get_random_once(&nfnl_queue_hash_key, sizeof(nfnl_queue_hash_key));
> +
> +	return reciprocal_scale(hash, INSTANCE_BUCKETS);
> +}
> +
>  static const struct rhashtable_params nfqnl_rhashtable_params = {
>  	.head_offset = offsetof(struct nf_queue_entry, hash_node),
>  	.key_offset = offsetof(struct nf_queue_entry, id),
> @@ -136,6 +148,20 @@ instance_lookup(struct nfnl_queue_net *q, u_int16_t queue_num)
>  	return NULL;
>  }
>  
> +static struct nfqnl_instance *
> +instance_lookup_by_portid(struct nfnl_queue_net *q, u32 portid)
> +{
> +	struct nfqnl_instance *inst;
> +	struct hlist_head *head;
> +
> +	head = &q->instance_table_portid[instance_portid_hashfn(portid)];
> +	hlist_for_each_entry(inst, head, hlist_portid) {
> +		if (inst->peer_portid == portid)
> +			return inst;
> +	}
> +	return NULL;
> +}
> +
>  static struct nfqnl_instance *
>  instance_create(struct nfnl_queue_net *q, u_int16_t queue_num, u32 portid)
>  {
> @@ -160,7 +186,8 @@ instance_create(struct nfnl_queue_net *q, u_int16_t queue_num, u32 portid)
>  		goto out_free;
>  
>  	spin_lock(&q->instances_lock);
> -	if (instance_lookup(q, queue_num)) {
> +	if (instance_lookup(q, queue_num) ||
> +	    unlikely(instance_lookup_by_portid(q, portid))) {
>  		err = -EEXIST;
>  		goto out_unlock;
>  	}
> @@ -172,6 +199,8 @@ instance_create(struct nfnl_queue_net *q, u_int16_t queue_num, u32 portid)
>  
>  	h = instance_hashfn(queue_num);
>  	hlist_add_head_rcu(&inst->hlist, &q->instance_table[h]);
> +	h = instance_portid_hashfn(portid);
> +	hlist_add_head(&inst->hlist_portid, &q->instance_table_portid[h]);
>  
>  	spin_unlock(&q->instances_lock);
>  
> @@ -208,6 +237,7 @@ static void
>  __instance_destroy(struct nfqnl_instance *inst)
>  {
>  	hlist_del_rcu(&inst->hlist);
> +	hlist_del(&inst->hlist_portid);
>  
>  	INIT_RCU_WORK(&inst->rwork, instance_destroy_work);
>  	queue_rcu_work(nfq_cleanup_wq, &inst->rwork);
> @@ -2119,8 +2149,10 @@ static int __net_init nfnl_queue_net_init(struct net *net)
>  	unsigned int i;
>  	struct nfnl_queue_net *q = nfnl_queue_pernet(net);
>  
> -	for (i = 0; i < INSTANCE_BUCKETS; i++)
> +	for (i = 0; i < INSTANCE_BUCKETS; i++) {
>  		INIT_HLIST_HEAD(&q->instance_table[i]);
> +		INIT_HLIST_HEAD(&q->instance_table_portid[i]);
> +	}
>  
>  	spin_lock_init(&q->instances_lock);
>  
> -- 
> 2.47.3
> 
> 

      reply	other threads:[~2026-09-23 20:04 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-23 18:40 [PATCH nf,v3] netfilter: nfnetlink_queue: hash queue instance by portid too Pablo Neira Ayuso
2026-09-23 20:04 ` Pablo Neira Ayuso [this message]

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=arQwtSh6BNUZ8BsJ@chamomile \
    --to=pablo@netfilter.org \
    --cc=fw@strlen.de \
    --cc=netfilter-devel@vger.kernel.org \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.