lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20241015232529.67605-1-kuniyu@amazon.com>
Date: Tue, 15 Oct 2024 16:25:29 -0700
From: Kuniyuki Iwashima <kuniyu@...zon.com>
To: <gnaaman@...venets.com>
CC: <davem@...emloft.net>, <edumazet@...gle.com>, <kuba@...nel.org>,
	<kuniyu@...zon.com>, <netdev@...r.kernel.org>, <pabeni@...hat.com>
Subject: Re: [PATCH net-next v4 3/6] Convert neigh_* seq_file functions to use hlist

From: Gilad Naaman <gnaaman@...venets.com>
Date: Tue, 15 Oct 2024 16:59:23 +0000
> Convert seq_file-related neighbour functionality to use neighbour::hash
> and the related for_each macro.
> 
> Signed-off-by: Gilad Naaman <gnaaman@...venets.com>
> ---
>  include/net/neighbour.h |  4 ++++
>  net/core/neighbour.c    | 26 ++++++++++----------------
>  2 files changed, 14 insertions(+), 16 deletions(-)
> 
> diff --git a/include/net/neighbour.h b/include/net/neighbour.h
> index 2f4cb9e51364..7dc0d4d6a4a8 100644
> --- a/include/net/neighbour.h
> +++ b/include/net/neighbour.h
> @@ -279,6 +279,10 @@ static inline void *neighbour_priv(const struct neighbour *n)
>  extern const struct nla_policy nda_policy[];
>  
>  #define neigh_for_each(pos, head) hlist_for_each_entry(pos, head, hash)
> +#define neigh_hlist_entry(n) hlist_entry_safe(n, struct neighbour, hash)
> +#define neigh_first_rcu(bucket) \
> +	neigh_hlist_entry(rcu_dereference(hlist_first_rcu(bucket)))

No RCU helpers are needed, seq file is under RCU & tbl->lock

#define neigh_first_entry(bucket)				\
	hlist_entry_safe((bucket)->first, struct neighbour, hash)

> +

nit: unnecessary newline.


>  
>  static inline bool neigh_key_eq32(const struct neighbour *n, const void *pkey)
>  {
> diff --git a/net/core/neighbour.c b/net/core/neighbour.c
> index e91105a4c5ee..4bdf7649ca57 100644
> --- a/net/core/neighbour.c
> +++ b/net/core/neighbour.c
> @@ -3207,25 +3207,21 @@ static struct neighbour *neigh_get_first(struct seq_file *seq)
>  
>  	state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
>  	for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) {
> -		n = rcu_dereference(nht->hash_buckets[bucket]);
> -
> -		while (n) {
> +		neigh_for_each(n, &nht->hash_heads[bucket]) {
>  			if (!net_eq(dev_net(n->dev), net))
> -				goto next;
> +				continue;
>  			if (state->neigh_sub_iter) {
>  				loff_t fakep = 0;
>  				void *v;
>  
>  				v = state->neigh_sub_iter(state, n, &fakep);
>  				if (!v)
> -					goto next;
> +					continue;
>  			}
>  			if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
>  				break;

Let's avoid double-break and use goto just before setting bucket like:

out:
	state->bucket = bucket


>  			if (READ_ONCE(n->nud_state) & ~NUD_NOARP)
>  				break;

Same here.


> -next:
> -			n = rcu_dereference(n->next);
>  		}
>  
>  		if (n)

Then, this null check & break will be unnecessary.


> @@ -3249,34 +3245,32 @@ static struct neighbour *neigh_get_next(struct seq_file *seq,
>  		if (v)
>  			return n;
>  	}
> -	n = rcu_dereference(n->next);
>  
>  	while (1) {
> -		while (n) {
> +		hlist_for_each_entry_continue_rcu(n, hash) {
>  			if (!net_eq(dev_net(n->dev), net))
> -				goto next;
> +				continue;
>  			if (state->neigh_sub_iter) {
>  				void *v = state->neigh_sub_iter(state, n, pos);
>  				if (v)
>  					return n;
> -				goto next;
> +				continue;
>  			}
>  			if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
>  				break;
>  
>  			if (READ_ONCE(n->nud_state) & ~NUD_NOARP)
>  				break;

Same remark here.


> -next:
> -			n = rcu_dereference(n->next);
>  		}
>  
>  		if (n)
>  			break;

and here.

>  
> -		if (++state->bucket >= (1 << nht->hash_shift))
> -			break;

Let's keep this,


> +		while (!n && ++state->bucket < (1 << nht->hash_shift))
> +			n = neigh_first_rcu(&nht->hash_heads[state->bucket]);
>  
> -		n = rcu_dereference(nht->hash_buckets[state->bucket]);

and simply fetch neigh_first_entry().

Then, we can let the next loop handle the termination condition
and keep the code simple.


> +		if (!n)
> +			break;
>  	}
>  
>  	if (n && pos)
> -- 
> 2.46.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ