From 48d81d7a1bc242efb2b164b68a606ad883033d73 Mon Sep 17 00:00:00 2001 From: "yang.yang29@zte.com.cn" Date: Fri, 9 Jun 2023 10:05:51 +0800 Subject: [PATCH 1/3] net: Use skbufhead with raw lock commit c8d69a1f487ea62a36379aec5621e16febac45d3 upstream. Use the rps lock as rawlock so we can keep irq-off regions. It looks low latency. However we can't kfree() from this context therefore we defer this to the softirq and use the tofree_queue list for it (similar to process_queue). Signed-off-by: Thomas Gleixner --- include/linux/skbuff.h | 7 +++++++ net/core/dev.c | 6 +++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 0b8b354447d6..6c12e506aca8 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -296,6 +296,7 @@ struct sk_buff_head { __u32 qlen; spinlock_t lock; + raw_spinlock_t raw_lock; }; struct sk_buff; @@ -1903,6 +1904,12 @@ static inline void skb_queue_head_init(struct sk_buff_head *list) __skb_queue_head_init(list); } +static inline void skb_queue_head_init_raw(struct sk_buff_head *list) +{ + raw_spin_lock_init(&list->raw_lock); + __skb_queue_head_init(list); +} + static inline void skb_queue_head_init_class(struct sk_buff_head *list, struct lock_class_key *class) { diff --git a/net/core/dev.c b/net/core/dev.c index a2e7a4d510cd..4c5a0da5e482 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -222,14 +222,14 @@ static inline struct hlist_head *dev_index_hash(struct net *net, int ifindex) static inline void rps_lock(struct softnet_data *sd) { #ifdef CONFIG_RPS - spin_lock(&sd->input_pkt_queue.lock); + raw_spin_lock(&sd->input_pkt_queue.raw_lock); #endif } static inline void rps_unlock(struct softnet_data *sd) { #ifdef CONFIG_RPS - spin_unlock(&sd->input_pkt_queue.lock); + raw_spin_unlock(&sd->input_pkt_queue.raw_lock); #endif } @@ -11324,7 +11324,7 @@ static int __init net_dev_init(void) INIT_WORK(flush, flush_backlog); - skb_queue_head_init(&sd->input_pkt_queue); + skb_queue_head_init_raw(&sd->input_pkt_queue); skb_queue_head_init(&sd->process_queue); #ifdef CONFIG_XFRM_OFFLOAD skb_queue_head_init(&sd->xfrm_backlog); -- Gitee From a9676a96042ed012246ca4c7509b13b3524439e0 Mon Sep 17 00:00:00 2001 From: "yang.yang29@zte.com.cn" Date: Fri, 9 Jun 2023 10:06:01 +0800 Subject: [PATCH 2/3] net: Dequeue in dev_cpu_dead() without the lock commit a071aba3ba59731db1cdb52a24ae87863655c327 upstream. Upstream uses skb_dequeue() to acquire lock of `input_pkt_queue'. The reason is to synchronize against a remote CPU which still thinks that the CPU is online enqueues packets to this CPU. There are no guarantees that the packet is enqueued before the callback is run, it just hope. RT however complains about an not initialized lock because it uses another lock for `input_pkt_queue' due to the IRQ-off nature of the context. Use the unlocked dequeue version for `input_pkt_queue'. Signed-off-by: Sebastian Andrzej Siewior --- net/core/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index 4c5a0da5e482..4a21c26d44f4 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -11008,7 +11008,7 @@ static int dev_cpu_dead(unsigned int oldcpu) netif_rx_ni(skb); input_queue_head_incr(oldsd); } - while ((skb = skb_dequeue(&oldsd->input_pkt_queue))) { + while ((skb = __skb_dequeue(&oldsd->input_pkt_queue))) { netif_rx_ni(skb); input_queue_head_incr(oldsd); } -- Gitee From e1ba8e0167399cf4d51b3812d8a6aeec40c7f125 Mon Sep 17 00:00:00 2001 From: "yang.yang29@zte.com.cn" Date: Fri, 9 Jun 2023 10:07:06 +0800 Subject: [PATCH 3/3] net: dev: always take qdisc's busylock in __dev_xmit_skb() commit 632d87162e02123196deed4c3ddb9a0d7e6c090f upstream. The root-lock is dropped before dev_hard_start_xmit() is invoked and after setting the __QDISC___STATE_RUNNING bit. If this task is now pushed away by a task with a higher priority then the task with the higher priority won't be able to submit packets to the NIC directly instead they will be enqueued into the Qdisc. The NIC will remain idle until the task(s) with higher priority leave the CPU and the task with lower priority gets back and finishes the job. If we take always the busylock we ensure that the RT task can boost the low-prio task and submit the packet. Signed-off-by: Sebastian Andrzej Siewior --- net/core/dev.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/core/dev.c b/net/core/dev.c index 4a21c26d44f4..23a1534fd991 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3805,7 +3805,11 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q, * This permits qdisc->running owner to get the lock more * often and dequeue packets faster. */ +#ifdef CONFIG_PREEMPT_RT + contended = true; +#else contended = qdisc_is_running(q); +#endif if (unlikely(contended)) spin_lock(&q->busylock); -- Gitee