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

Configure Feed

Select the types of activity you want to include in your feed.

ppp: enable TX scatter-gather

PPP channels using chan->direct_xmit prepend the PPP header to a skb and
call dev_queue_xmit() directly. In this mode the skb does not need to be
linear, but the PPP netdevice currently does not advertise
scatter-gather features, causing unnecessary linearization and
preventing GSO.

Enable NETIF_F_SG and NETIF_F_FRAGLIST on PPP devices. In case a linear
buffer is required (PPP compression, multilink, and channels without
direct_xmit), call skb_linearize() explicitly.

Signed-off-by: Qingfang Deng <dqfext@gmail.com>
Link: https://patch.msgid.link/20260129012902.941-1-dqfext@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Qingfang Deng and committed by
Paolo Abeni
42fcb213 3e5aa52b

+25 -5
+25 -5
drivers/net/ppp/ppp_generic.c
··· 1641 1641 dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; 1642 1642 dev->priv_destructor = ppp_dev_priv_destructor; 1643 1643 dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS; 1644 + dev->features = NETIF_F_SG | NETIF_F_FRAGLIST; 1645 + dev->hw_features = dev->features; 1644 1646 netif_keep_dst(dev); 1645 1647 } 1646 1648 ··· 1712 1710 ppp->xcomp->comp_extra + ppp->dev->hard_header_len; 1713 1711 int compressor_skb_size = ppp->dev->mtu + 1714 1712 ppp->xcomp->comp_extra + PPP_HDRLEN; 1713 + 1714 + if (skb_linearize(skb)) 1715 + return NULL; 1716 + 1715 1717 new_skb = alloc_skb(new_skb_size, GFP_ATOMIC); 1716 1718 if (!new_skb) { 1717 1719 if (net_ratelimit()) ··· 1803 1797 case PPP_IP: 1804 1798 if (!ppp->vj || (ppp->flags & SC_COMP_TCP) == 0) 1805 1799 break; 1800 + 1801 + if (skb_linearize(skb)) 1802 + goto drop; 1803 + 1806 1804 /* try to do VJ TCP header compression */ 1807 1805 new_skb = alloc_skb(skb->len + ppp->dev->hard_header_len - 2, 1808 1806 GFP_ATOMIC); ··· 1904 1894 } 1905 1895 1906 1896 if ((ppp->flags & SC_MULTILINK) == 0) { 1897 + struct ppp_channel *chan; 1907 1898 /* not doing multilink: send it down the first channel */ 1908 1899 list = list->next; 1909 1900 pch = list_entry(list, struct channel, clist); 1910 1901 1911 1902 spin_lock(&pch->downl); 1912 - if (pch->chan) { 1913 - if (pch->chan->ops->start_xmit(pch->chan, skb)) 1914 - ppp->xmit_pending = NULL; 1915 - } else { 1916 - /* channel got unregistered */ 1903 + chan = pch->chan; 1904 + if (unlikely(!chan || (!chan->direct_xmit && skb_linearize(skb)))) { 1905 + /* channel got unregistered, or it requires a linear 1906 + * skb but linearization failed 1907 + */ 1917 1908 kfree_skb(skb); 1918 1909 ppp->xmit_pending = NULL; 1910 + goto out; 1919 1911 } 1912 + 1913 + if (chan->ops->start_xmit(chan, skb)) 1914 + ppp->xmit_pending = NULL; 1915 + 1916 + out: 1920 1917 spin_unlock(&pch->downl); 1921 1918 return; 1922 1919 } ··· 2008 1991 return 0; /* can't take now, leave it in xmit_pending */ 2009 1992 2010 1993 /* Do protocol field compression */ 1994 + if (skb_linearize(skb)) 1995 + goto err_linearize; 2011 1996 p = skb->data; 2012 1997 len = skb->len; 2013 1998 if (*p == 0 && mp_protocol_compress) { ··· 2168 2149 2169 2150 noskb: 2170 2151 spin_unlock(&pch->downl); 2152 + err_linearize: 2171 2153 if (ppp->debug & 1) 2172 2154 netdev_err(ppp->dev, "PPP: no memory (fragment)\n"); 2173 2155 ++ppp->dev->stats.tx_errors;