Skip to content

Commit 52d8b8a

Browse files
edumazetgregkh
authored andcommitted
net: better skb->sender_cpu and skb->napi_id cohabitation
commit 52bd2d62ce6758d811edcbd2256eb9ea7f6a56cb upstream. skb->sender_cpu and skb->napi_id share a common storage, and we had various bugs about this. We had to call skb_sender_cpu_clear() in some places to not leave a prior skb->napi_id and fool netdev_pick_tx() As suggested by Alexei, we could split the space so that these errors can not happen. 0 value being reserved as the common (not initialized) value, let's reserve [1 .. NR_CPUS] range for valid sender_cpu, and [NR_CPUS+1 .. ~0U] for valid napi_id. This will allow proper busy polling support over tunnels. Signed-off-by: Eric Dumazet <edumazet@google.com> Suggested-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net> Cc: Paul Menzel <pmenzel@molgen.mpg.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 3c0fcb5 commit 52d8b8a

2 files changed

Lines changed: 16 additions & 20 deletions

File tree

include/linux/skbuff.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,9 +1084,6 @@ static inline void skb_copy_hash(struct sk_buff *to, const struct sk_buff *from)
10841084

10851085
static inline void skb_sender_cpu_clear(struct sk_buff *skb)
10861086
{
1087-
#ifdef CONFIG_XPS
1088-
skb->sender_cpu = 0;
1089-
#endif
10901087
}
10911088

10921089
#ifdef NET_SKBUFF_DATA_USES_OFFSET

net/core/dev.c

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ EXPORT_SYMBOL(dev_base_lock);
182182
/* protects napi_hash addition/deletion and napi_gen_id */
183183
static DEFINE_SPINLOCK(napi_hash_lock);
184184

185-
static unsigned int napi_gen_id;
185+
static unsigned int napi_gen_id = NR_CPUS;
186186
static DEFINE_HASHTABLE(napi_hash, 8);
187187

188188
static seqcount_t devnet_rename_seq;
@@ -3049,7 +3049,9 @@ struct netdev_queue *netdev_pick_tx(struct net_device *dev,
30493049
int queue_index = 0;
30503050

30513051
#ifdef CONFIG_XPS
3052-
if (skb->sender_cpu == 0)
3052+
u32 sender_cpu = skb->sender_cpu - 1;
3053+
3054+
if (sender_cpu >= (u32)NR_CPUS)
30533055
skb->sender_cpu = raw_smp_processor_id() + 1;
30543056
#endif
30553057

@@ -4726,25 +4728,22 @@ EXPORT_SYMBOL_GPL(napi_by_id);
47264728

47274729
void napi_hash_add(struct napi_struct *napi)
47284730
{
4729-
if (!test_and_set_bit(NAPI_STATE_HASHED, &napi->state)) {
4731+
if (test_and_set_bit(NAPI_STATE_HASHED, &napi->state))
4732+
return;
47304733

4731-
spin_lock(&napi_hash_lock);
4734+
spin_lock(&napi_hash_lock);
47324735

4733-
/* 0 is not a valid id, we also skip an id that is taken
4734-
* we expect both events to be extremely rare
4735-
*/
4736-
napi->napi_id = 0;
4737-
while (!napi->napi_id) {
4738-
napi->napi_id = ++napi_gen_id;
4739-
if (napi_by_id(napi->napi_id))
4740-
napi->napi_id = 0;
4741-
}
4736+
/* 0..NR_CPUS+1 range is reserved for sender_cpu use */
4737+
do {
4738+
if (unlikely(++napi_gen_id < NR_CPUS + 1))
4739+
napi_gen_id = NR_CPUS + 1;
4740+
} while (napi_by_id(napi_gen_id));
4741+
napi->napi_id = napi_gen_id;
47424742

4743-
hlist_add_head_rcu(&napi->napi_hash_node,
4744-
&napi_hash[napi->napi_id % HASH_SIZE(napi_hash)]);
4743+
hlist_add_head_rcu(&napi->napi_hash_node,
4744+
&napi_hash[napi->napi_id % HASH_SIZE(napi_hash)]);
47454745

4746-
spin_unlock(&napi_hash_lock);
4747-
}
4746+
spin_unlock(&napi_hash_lock);
47484747
}
47494748
EXPORT_SYMBOL_GPL(napi_hash_add);
47504749

0 commit comments

Comments
 (0)