Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'net-add-skb_drop_reason_recursion_limit'

Eric Dumazet says:

====================
net: add SKB_DROP_REASON_RECURSION_LIMIT

Add a new drop reason : SKB_DROP_REASON_RECURSION_LIMIT

Used for packets dropped in a too deep virtual device chain,
from tunnels and __dev_queue_xmit()

__dev_queue_xmit() can also return SKB_DROP_REASON_DEV_READY
====================

Link: https://patch.msgid.link/20260312201824.203093-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+58 -52
+3
include/net/dropreason-core.h
··· 123 123 FN(PFMEMALLOC) \ 124 124 FN(PSP_INPUT) \ 125 125 FN(PSP_OUTPUT) \ 126 + FN(RECURSION_LIMIT) \ 126 127 FNe(MAX) 127 128 128 129 /** ··· 583 582 SKB_DROP_REASON_PSP_INPUT, 584 583 /** @SKB_DROP_REASON_PSP_OUTPUT: PSP output checks failed */ 585 584 SKB_DROP_REASON_PSP_OUTPUT, 585 + /** @SKB_DROP_REASON_RECURSION_LIMIT: Dead loop on virtual device. */ 586 + SKB_DROP_REASON_RECURSION_LIMIT, 586 587 /** 587 588 * @SKB_DROP_REASON_MAX: the maximum of core drop reasons, which 588 589 * shouldn't be used as a real 'reason' - only for tracing code gen
+1 -1
include/net/ip6_tunnel.h
··· 162 162 dev->name); 163 163 DEV_STATS_INC(dev, tx_errors); 164 164 } 165 - kfree_skb(skb); 165 + kfree_skb_reason(skb, SKB_DROP_REASON_RECURSION_LIMIT); 166 166 return; 167 167 } 168 168
+53 -50
net/core/dev.c
··· 4745 4745 { 4746 4746 struct net_device *dev = skb->dev; 4747 4747 struct netdev_queue *txq = NULL; 4748 - struct Qdisc *q; 4749 - int rc = -ENOMEM; 4748 + enum skb_drop_reason reason; 4749 + int cpu, rc = -ENOMEM; 4750 4750 bool again = false; 4751 + struct Qdisc *q; 4751 4752 4752 4753 skb_reset_mac_header(skb); 4753 4754 skb_assert_len(skb); ··· 4817 4816 * Check this and shot the lock. It is not prone from deadlocks. 4818 4817 *Either shot noqueue qdisc, it is even simpler 8) 4819 4818 */ 4820 - if (dev->flags & IFF_UP) { 4821 - int cpu = smp_processor_id(); /* ok because BHs are off */ 4822 - 4823 - if (!netif_tx_owned(txq, cpu)) { 4824 - bool is_list = false; 4825 - 4826 - if (dev_xmit_recursion()) 4827 - goto recursion_alert; 4828 - 4829 - skb = validate_xmit_skb(skb, dev, &again); 4830 - if (!skb) 4831 - goto out; 4832 - 4833 - HARD_TX_LOCK(dev, txq, cpu); 4834 - 4835 - if (!netif_xmit_stopped(txq)) { 4836 - is_list = !!skb->next; 4837 - 4838 - dev_xmit_recursion_inc(); 4839 - skb = dev_hard_start_xmit(skb, dev, txq, &rc); 4840 - dev_xmit_recursion_dec(); 4841 - 4842 - /* GSO segments a single SKB into 4843 - * a list of frames. TCP expects error 4844 - * to mean none of the data was sent. 4845 - */ 4846 - if (is_list) 4847 - rc = NETDEV_TX_OK; 4848 - } 4849 - HARD_TX_UNLOCK(dev, txq); 4850 - if (!skb) /* xmit completed */ 4851 - goto out; 4852 - 4853 - net_crit_ratelimited("Virtual device %s asks to queue packet!\n", 4854 - dev->name); 4855 - /* NETDEV_TX_BUSY or queue was stopped */ 4856 - if (!is_list) 4857 - rc = -ENETDOWN; 4858 - } else { 4859 - /* Recursion is detected! It is possible, 4860 - * unfortunately 4861 - */ 4862 - recursion_alert: 4863 - net_crit_ratelimited("Dead loop on virtual device %s, fix it urgently!\n", 4864 - dev->name); 4865 - rc = -ENETDOWN; 4866 - } 4819 + if (unlikely(!(dev->flags & IFF_UP))) { 4820 + reason = SKB_DROP_REASON_DEV_READY; 4821 + goto drop; 4867 4822 } 4868 4823 4824 + cpu = smp_processor_id(); /* ok because BHs are off */ 4825 + 4826 + if (likely(!netif_tx_owned(txq, cpu))) { 4827 + bool is_list = false; 4828 + 4829 + if (dev_xmit_recursion()) 4830 + goto recursion_alert; 4831 + 4832 + skb = validate_xmit_skb(skb, dev, &again); 4833 + if (!skb) 4834 + goto out; 4835 + 4836 + HARD_TX_LOCK(dev, txq, cpu); 4837 + 4838 + if (!netif_xmit_stopped(txq)) { 4839 + is_list = !!skb->next; 4840 + 4841 + dev_xmit_recursion_inc(); 4842 + skb = dev_hard_start_xmit(skb, dev, txq, &rc); 4843 + dev_xmit_recursion_dec(); 4844 + 4845 + /* GSO segments a single SKB into a list of frames. 4846 + * TCP expects error to mean none of the data was sent. 4847 + */ 4848 + if (is_list) 4849 + rc = NETDEV_TX_OK; 4850 + } 4851 + HARD_TX_UNLOCK(dev, txq); 4852 + if (!skb) /* xmit completed */ 4853 + goto out; 4854 + 4855 + net_crit_ratelimited("Virtual device %s asks to queue packet!\n", 4856 + dev->name); 4857 + /* NETDEV_TX_BUSY or queue was stopped */ 4858 + if (!is_list) 4859 + rc = -ENETDOWN; 4860 + } else { 4861 + /* Recursion is detected! It is possible unfortunately. */ 4862 + recursion_alert: 4863 + net_crit_ratelimited("Dead loop on virtual device %s, fix it urgently!\n", 4864 + dev->name); 4865 + rc = -ENETDOWN; 4866 + } 4867 + 4868 + reason = SKB_DROP_REASON_RECURSION_LIMIT; 4869 + drop: 4869 4870 rcu_read_unlock_bh(); 4870 4871 4871 4872 dev_core_stats_tx_dropped_inc(dev); 4872 - kfree_skb_list(skb); 4873 + kfree_skb_list_reason(skb, reason); 4873 4874 return rc; 4874 4875 out: 4875 4876 rcu_read_unlock_bh();
+1 -1
net/ipv4/ip_tunnel_core.c
··· 65 65 DEV_STATS_INC(dev, tx_errors); 66 66 } 67 67 ip_rt_put(rt); 68 - kfree_skb(skb); 68 + kfree_skb_reason(skb, SKB_DROP_REASON_RECURSION_LIMIT); 69 69 return; 70 70 } 71 71