Skip to content

Commit 6bb218b

Browse files
committed
Merge branch 'napi_threaded_poll-enhancements'
Eric Dumazet says: ==================== net: give napi_threaded_poll() some love There is interest to revert commit 4cd13c2 ("softirq: Let ksoftirqd do its job") and use instead the napi_threaded_poll() mode. https://lore.kernel.org/netdev/140f61e2e1fcb8cf53619709046e312e343b53ca.camel@redhat.com/T/#m8a8f5b09844adba157ad0d22fc1233d97013de50 Before doing so, make sure napi_threaded_poll() benefits from recent core stack improvements, to further reduce softirq triggers. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 19c60fd + 87eff2e commit 6bb218b

3 files changed

Lines changed: 42 additions & 26 deletions

File tree

include/linux/netdevice.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3194,7 +3194,10 @@ struct softnet_data {
31943194
#ifdef CONFIG_RPS
31953195
struct softnet_data *rps_ipi_list;
31963196
#endif
3197+
31973198
bool in_net_rx_action;
3199+
bool in_napi_threaded_poll;
3200+
31983201
#ifdef CONFIG_NET_FLOW_LIMIT
31993202
struct sd_flow_limit __rcu *flow_limit;
32003203
#endif

net/core/dev.c

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4603,10 +4603,10 @@ static void napi_schedule_rps(struct softnet_data *sd)
46034603
sd->rps_ipi_next = mysd->rps_ipi_list;
46044604
mysd->rps_ipi_list = sd;
46054605

4606-
/* If not called from net_rx_action()
4606+
/* If not called from net_rx_action() or napi_threaded_poll()
46074607
* we have to raise NET_RX_SOFTIRQ.
46084608
*/
4609-
if (!mysd->in_net_rx_action)
4609+
if (!mysd->in_net_rx_action && !mysd->in_napi_threaded_poll)
46104610
__raise_softirq_irqoff(NET_RX_SOFTIRQ);
46114611
return;
46124612
}
@@ -6598,21 +6598,53 @@ static int napi_thread_wait(struct napi_struct *napi)
65986598
return -1;
65996599
}
66006600

6601+
static void skb_defer_free_flush(struct softnet_data *sd)
6602+
{
6603+
struct sk_buff *skb, *next;
6604+
6605+
/* Paired with WRITE_ONCE() in skb_attempt_defer_free() */
6606+
if (!READ_ONCE(sd->defer_list))
6607+
return;
6608+
6609+
spin_lock(&sd->defer_lock);
6610+
skb = sd->defer_list;
6611+
sd->defer_list = NULL;
6612+
sd->defer_count = 0;
6613+
spin_unlock(&sd->defer_lock);
6614+
6615+
while (skb != NULL) {
6616+
next = skb->next;
6617+
napi_consume_skb(skb, 1);
6618+
skb = next;
6619+
}
6620+
}
6621+
66016622
static int napi_threaded_poll(void *data)
66026623
{
66036624
struct napi_struct *napi = data;
6625+
struct softnet_data *sd;
66046626
void *have;
66056627

66066628
while (!napi_thread_wait(napi)) {
66076629
for (;;) {
66086630
bool repoll = false;
66096631

66106632
local_bh_disable();
6633+
sd = this_cpu_ptr(&softnet_data);
6634+
sd->in_napi_threaded_poll = true;
66116635

66126636
have = netpoll_poll_lock(napi);
66136637
__napi_poll(napi, &repoll);
66146638
netpoll_poll_unlock(have);
66156639

6640+
sd->in_napi_threaded_poll = false;
6641+
barrier();
6642+
6643+
if (sd_has_rps_ipi_waiting(sd)) {
6644+
local_irq_disable();
6645+
net_rps_action_and_irq_enable(sd);
6646+
}
6647+
skb_defer_free_flush(sd);
66166648
local_bh_enable();
66176649

66186650
if (!repoll)
@@ -6624,27 +6656,6 @@ static int napi_threaded_poll(void *data)
66246656
return 0;
66256657
}
66266658

6627-
static void skb_defer_free_flush(struct softnet_data *sd)
6628-
{
6629-
struct sk_buff *skb, *next;
6630-
6631-
/* Paired with WRITE_ONCE() in skb_attempt_defer_free() */
6632-
if (!READ_ONCE(sd->defer_list))
6633-
return;
6634-
6635-
spin_lock_irq(&sd->defer_lock);
6636-
skb = sd->defer_list;
6637-
sd->defer_list = NULL;
6638-
sd->defer_count = 0;
6639-
spin_unlock_irq(&sd->defer_lock);
6640-
6641-
while (skb != NULL) {
6642-
next = skb->next;
6643-
napi_consume_skb(skb, 1);
6644-
skb = next;
6645-
}
6646-
}
6647-
66486659
static __latent_entropy void net_rx_action(struct softirq_action *h)
66496660
{
66506661
struct softnet_data *sd = this_cpu_ptr(&softnet_data);

net/core/skbuff.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6870,7 +6870,6 @@ void skb_attempt_defer_free(struct sk_buff *skb)
68706870
{
68716871
int cpu = skb->alloc_cpu;
68726872
struct softnet_data *sd;
6873-
unsigned long flags;
68746873
unsigned int defer_max;
68756874
bool kick;
68766875

@@ -6881,12 +6880,15 @@ nodefer: __kfree_skb(skb);
68816880
return;
68826881
}
68836882

6883+
DEBUG_NET_WARN_ON_ONCE(skb_dst(skb));
6884+
DEBUG_NET_WARN_ON_ONCE(skb->destructor);
6885+
68846886
sd = &per_cpu(softnet_data, cpu);
68856887
defer_max = READ_ONCE(sysctl_skb_defer_max);
68866888
if (READ_ONCE(sd->defer_count) >= defer_max)
68876889
goto nodefer;
68886890

6889-
spin_lock_irqsave(&sd->defer_lock, flags);
6891+
spin_lock_bh(&sd->defer_lock);
68906892
/* Send an IPI every time queue reaches half capacity. */
68916893
kick = sd->defer_count == (defer_max >> 1);
68926894
/* Paired with the READ_ONCE() few lines above */
@@ -6895,7 +6897,7 @@ nodefer: __kfree_skb(skb);
68956897
skb->next = sd->defer_list;
68966898
/* Paired with READ_ONCE() in skb_defer_free_flush() */
68976899
WRITE_ONCE(sd->defer_list, skb);
6898-
spin_unlock_irqrestore(&sd->defer_lock, flags);
6900+
spin_unlock_bh(&sd->defer_lock);
68996901

69006902
/* Make sure to trigger NET_RX_SOFTIRQ on the remote CPU
69016903
* if we are unlucky enough (this seems very unlikely).

0 commit comments

Comments
 (0)