Commit 00df5e1a authored by Gilad Naaman's avatar Gilad Naaman Committed by Jakub Kicinski
Browse files

neighbour: Convert seq_file functions to use hlist



Convert seq_file-related neighbour functionality to use neighbour::hash
and the related for_each macro.

Signed-off-by: default avatarGilad Naaman <gnaaman@drivenets.com>
Reviewed-by: default avatarKuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: default avatarEric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20241107160444.2913124-4-gnaaman@drivenets.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent d7ddee1a
Loading
Loading
Loading
Loading
+48 −56
Original line number Diff line number Diff line
@@ -3193,43 +3193,53 @@ EXPORT_SYMBOL(neigh_xmit);

#ifdef CONFIG_PROC_FS

static struct neighbour *neigh_get_first(struct seq_file *seq)
static struct neighbour *neigh_get_valid(struct seq_file *seq,
					 struct neighbour *n,
					 loff_t *pos)
{
	struct neigh_seq_state *state = seq->private;
	struct net *net = seq_file_net(seq);
	struct neigh_hash_table *nht = state->nht;
	struct neighbour *n = NULL;
	int bucket;

	state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
	for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) {
		n = rcu_dereference(nht->hash_buckets[bucket]);

		while (n) {
	if (!net_eq(dev_net(n->dev), net))
				goto next;
		return NULL;

	if (state->neigh_sub_iter) {
		loff_t fakep = 0;
		void *v;

				v = state->neigh_sub_iter(state, n, &fakep);
		v = state->neigh_sub_iter(state, n, pos ? pos : &fakep);
		if (!v)
					goto next;
			return NULL;
		if (pos)
			return v;
	}

	if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
				break;
		return n;

	if (READ_ONCE(n->nud_state) & ~NUD_NOARP)
				break;
next:
			n = rcu_dereference(n->next);
		return n;

	return NULL;
}

		if (n)
			break;
static struct neighbour *neigh_get_first(struct seq_file *seq)
{
	struct neigh_seq_state *state = seq->private;
	struct neigh_hash_table *nht = state->nht;
	struct neighbour *n, *tmp;

	state->flags &= ~NEIGH_SEQ_IS_PNEIGH;

	while (++state->bucket < (1 << nht->hash_shift)) {
		neigh_for_each_in_bucket(n, &nht->hash_heads[state->bucket]) {
			tmp = neigh_get_valid(seq, n, NULL);
			if (tmp)
				return tmp;
		}
	}
	state->bucket = bucket;

	return n;
	return NULL;
}

static struct neighbour *neigh_get_next(struct seq_file *seq,
@@ -3237,46 +3247,28 @@ static struct neighbour *neigh_get_next(struct seq_file *seq,
					loff_t *pos)
{
	struct neigh_seq_state *state = seq->private;
	struct net *net = seq_file_net(seq);
	struct neigh_hash_table *nht = state->nht;
	struct neighbour *tmp;

	if (state->neigh_sub_iter) {
		void *v = state->neigh_sub_iter(state, n, pos);
		if (v)
			return n;
	}
	n = rcu_dereference(n->next);

	while (1) {
		while (n) {
			if (!net_eq(dev_net(n->dev), net))
				goto next;
			if (state->neigh_sub_iter) {
				void *v = state->neigh_sub_iter(state, n, pos);
		if (v)
			return n;
				goto next;
	}
			if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
				break;

			if (READ_ONCE(n->nud_state) & ~NUD_NOARP)
				break;
next:
			n = rcu_dereference(n->next);
	hlist_for_each_entry_continue(n, hash) {
		tmp = neigh_get_valid(seq, n, pos);
		if (tmp) {
			n = tmp;
			goto out;
		}

		if (n)
			break;

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

		n = rcu_dereference(nht->hash_buckets[state->bucket]);
	}

	n = neigh_get_first(seq);
out:
	if (n && pos)
		--(*pos);

	return n;
}

@@ -3379,7 +3371,7 @@ void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl
	struct neigh_seq_state *state = seq->private;

	state->tbl = tbl;
	state->bucket = 0;
	state->bucket = -1;
	state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH);

	rcu_read_lock();