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: don't store tx skb in the fastpath

Currently, ppp->xmit_pending is used in ppp_send_frame() to pass a skb
to ppp_push(), and holds the skb when a PPP channel cannot immediately
transmit it. This state is redundant because the transmit queue
(ppp->file.xq) can already handle the backlog. Furthermore, during
normal operation, an skb is queued in file.xq only to be immediately
dequeued, causing unnecessary overhead.

Refactor the transmit path to avoid stashing the skb when possible:
- Remove ppp->xmit_pending.
- Rename ppp_send_frame() to ppp_prepare_tx_skb(), and don't call
ppp_push() in it. It returns 1 if the skb is consumed
(dropped/handled) or 0 if it can be passed to ppp_push().
- Update ppp_push() to accept the skb. It returns 1 if the skb is
consumed, or 0 if the channel is busy.
- Optimize __ppp_xmit_process():
- Fastpath: If the queue is empty, attempt to send the skb directly
via ppp_push(). If busy, queue it.
- Slowpath: If the queue is not empty, process the backlog in
file.xq. Split dequeuing loop into a separate function
ppp_xmit_flush() so ppp_channel_push() uses that directly instead of
passing a NULL skb to __ppp_xmit_process().

This simplifies the states and reduces locking in the fastpath.

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

authored by

Qingfang Deng and committed by
Paolo Abeni
70836c8d 0172f8d8

+66 -47
+66 -47
drivers/net/ppp/ppp_generic.c
··· 134 134 int debug; /* debug flags 70 */ 135 135 struct slcompress *vj; /* state for VJ header compression */ 136 136 enum NPmode npmode[NUM_NP]; /* what to do with each net proto 78 */ 137 - struct sk_buff *xmit_pending; /* a packet ready to go out 88 */ 138 137 struct compressor *xcomp; /* transmit packet compressor 8c */ 139 138 void *xc_state; /* its internal state 90 */ 140 139 struct compressor *rcomp; /* receive decompressor 94 */ ··· 263 264 static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf, 264 265 struct file *file, unsigned int cmd, unsigned long arg); 265 266 static void ppp_xmit_process(struct ppp *ppp, struct sk_buff *skb); 266 - static void ppp_send_frame(struct ppp *ppp, struct sk_buff *skb); 267 - static void ppp_push(struct ppp *ppp); 267 + static int ppp_prepare_tx_skb(struct ppp *ppp, struct sk_buff **pskb); 268 + static int ppp_push(struct ppp *ppp, struct sk_buff *skb); 268 269 static void ppp_channel_push(struct channel *pch); 269 270 static void ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, 270 271 struct channel *pch); ··· 1650 1651 */ 1651 1652 1652 1653 /* Called to do any work queued up on the transmit side that can now be done */ 1654 + static void ppp_xmit_flush(struct ppp *ppp) 1655 + { 1656 + struct sk_buff *skb; 1657 + 1658 + while ((skb = skb_dequeue(&ppp->file.xq))) { 1659 + if (unlikely(!ppp_push(ppp, skb))) { 1660 + skb_queue_head(&ppp->file.xq, skb); 1661 + return; 1662 + } 1663 + } 1664 + /* If there's no work left to do, tell the core net code that we can 1665 + * accept some more. 1666 + */ 1667 + netif_wake_queue(ppp->dev); 1668 + } 1669 + 1653 1670 static void __ppp_xmit_process(struct ppp *ppp, struct sk_buff *skb) 1654 1671 { 1655 1672 ppp_xmit_lock(ppp); 1656 - if (!ppp->closing) { 1657 - ppp_push(ppp); 1658 - 1659 - if (skb) 1660 - skb_queue_tail(&ppp->file.xq, skb); 1661 - while (!ppp->xmit_pending && 1662 - (skb = skb_dequeue(&ppp->file.xq))) 1663 - ppp_send_frame(ppp, skb); 1664 - /* If there's no work left to do, tell the core net 1665 - code that we can accept some more. */ 1666 - if (!ppp->xmit_pending && !skb_peek(&ppp->file.xq)) 1667 - netif_wake_queue(ppp->dev); 1668 - else 1669 - netif_stop_queue(ppp->dev); 1670 - } else { 1673 + if (unlikely(ppp->closing)) { 1671 1674 kfree_skb(skb); 1675 + goto out; 1672 1676 } 1677 + if (unlikely(ppp_prepare_tx_skb(ppp, &skb))) 1678 + goto out; 1679 + /* Fastpath: No backlog, just send the new skb. */ 1680 + if (likely(skb_queue_empty(&ppp->file.xq))) { 1681 + if (unlikely(!ppp_push(ppp, skb))) { 1682 + skb_queue_tail(&ppp->file.xq, skb); 1683 + netif_stop_queue(ppp->dev); 1684 + } 1685 + goto out; 1686 + } 1687 + 1688 + /* Slowpath: Enqueue the new skb and process backlog */ 1689 + skb_queue_tail(&ppp->file.xq, skb); 1690 + ppp_xmit_flush(ppp); 1691 + out: 1673 1692 ppp_xmit_unlock(ppp); 1674 1693 } 1675 1694 ··· 1774 1757 } 1775 1758 1776 1759 /* 1777 - * Compress and send a frame. 1778 - * The caller should have locked the xmit path, 1779 - * and xmit_pending should be 0. 1760 + * Compress and prepare to send a frame. 1761 + * The caller should have locked the xmit path. 1762 + * Returns 1 if the skb was consumed, 0 if it can be passed to ppp_push(). 1763 + * @pskb is updated if a compressor is in use. 1780 1764 */ 1781 - static void 1782 - ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) 1765 + static int 1766 + ppp_prepare_tx_skb(struct ppp *ppp, struct sk_buff **pskb) 1783 1767 { 1768 + struct sk_buff *skb = *pskb; 1784 1769 int proto = PPP_PROTO(skb); 1785 1770 struct sk_buff *new_skb; 1786 1771 int len; ··· 1803 1784 "PPP: outbound frame " 1804 1785 "not passed\n"); 1805 1786 kfree_skb(skb); 1806 - return; 1787 + return 1; 1807 1788 } 1808 1789 /* if this packet passes the active filter, record the time */ 1809 1790 if (!(ppp->active_filter && ··· 1851 1832 } 1852 1833 consume_skb(skb); 1853 1834 skb = new_skb; 1835 + *pskb = skb; 1854 1836 cp = skb_put(skb, len + 2); 1855 1837 cp[0] = 0; 1856 1838 cp[1] = proto; ··· 1878 1858 if (!new_skb) 1879 1859 goto drop; 1880 1860 skb = new_skb; 1861 + *pskb = skb; 1881 1862 } 1882 1863 1883 1864 /* ··· 1890 1869 goto drop; 1891 1870 skb_queue_tail(&ppp->file.rq, skb); 1892 1871 wake_up_interruptible(&ppp->file.rwait); 1893 - return; 1872 + return 1; 1894 1873 } 1895 1874 1896 - ppp->xmit_pending = skb; 1897 - ppp_push(ppp); 1898 - return; 1875 + return 0; 1899 1876 1900 1877 drop: 1901 1878 kfree_skb(skb); 1902 1879 ++ppp->dev->stats.tx_errors; 1880 + return 1; 1903 1881 } 1904 1882 1905 1883 /* 1906 - * Try to send the frame in xmit_pending. 1884 + * Try to send the frame. 1907 1885 * The caller should have the xmit path locked. 1886 + * Returns 1 if the skb was consumed, 0 if not. 1908 1887 */ 1909 - static void 1910 - ppp_push(struct ppp *ppp) 1888 + static int 1889 + ppp_push(struct ppp *ppp, struct sk_buff *skb) 1911 1890 { 1912 1891 struct list_head *list; 1913 1892 struct channel *pch; 1914 - struct sk_buff *skb = ppp->xmit_pending; 1915 - 1916 - if (!skb) 1917 - return; 1918 1893 1919 1894 list = &ppp->channels; 1920 1895 if (list_empty(list)) { 1921 1896 /* nowhere to send the packet, just drop it */ 1922 - ppp->xmit_pending = NULL; 1923 1897 kfree_skb(skb); 1924 - return; 1898 + return 1; 1925 1899 } 1926 1900 1927 1901 if ((ppp->flags & SC_MULTILINK) == 0) { 1928 1902 struct ppp_channel *chan; 1903 + int ret; 1929 1904 /* not doing multilink: send it down the first channel */ 1930 1905 list = list->next; 1931 1906 pch = list_entry(list, struct channel, clist); ··· 1933 1916 * skb but linearization failed 1934 1917 */ 1935 1918 kfree_skb(skb); 1936 - ppp->xmit_pending = NULL; 1919 + ret = 1; 1937 1920 goto out; 1938 1921 } 1939 1922 1940 - if (chan->ops->start_xmit(chan, skb)) 1941 - ppp->xmit_pending = NULL; 1923 + ret = chan->ops->start_xmit(chan, skb); 1942 1924 1943 1925 out: 1944 1926 spin_unlock(&pch->downl); 1945 - return; 1927 + return ret; 1946 1928 } 1947 1929 1948 1930 #ifdef CONFIG_PPP_MULTILINK 1949 1931 /* Multilink: fragment the packet over as many links 1950 1932 as can take the packet at the moment. */ 1951 1933 if (!ppp_mp_explode(ppp, skb)) 1952 - return; 1934 + return 0; 1953 1935 #endif /* CONFIG_PPP_MULTILINK */ 1954 1936 1955 - ppp->xmit_pending = NULL; 1956 1937 kfree_skb(skb); 1938 + return 1; 1957 1939 } 1958 1940 1959 1941 #ifdef CONFIG_PPP_MULTILINK ··· 2021 2005 * performance if we have a lot of channels. 2022 2006 */ 2023 2007 if (nfree == 0 || nfree < navail / 2) 2024 - return 0; /* can't take now, leave it in xmit_pending */ 2008 + return 0; /* can't take now, leave it in transmit queue */ 2025 2009 2026 2010 /* Do protocol field compression */ 2027 2011 if (skb_linearize(skb)) ··· 2215 2199 spin_unlock(&pch->downl); 2216 2200 /* see if there is anything from the attached unit to be sent */ 2217 2201 if (skb_queue_empty(&pch->file.xq)) { 2218 - if (ppp) 2219 - __ppp_xmit_process(ppp, NULL); 2202 + if (ppp) { 2203 + ppp_xmit_lock(ppp); 2204 + if (!ppp->closing) 2205 + ppp_xmit_flush(ppp); 2206 + ppp_xmit_unlock(ppp); 2207 + } 2220 2208 } 2221 2209 } 2222 2210 ··· 3480 3460 } 3481 3461 #endif /* CONFIG_PPP_FILTER */ 3482 3462 3483 - kfree_skb(ppp->xmit_pending); 3484 3463 free_percpu(ppp->xmit_recursion); 3485 3464 3486 3465 free_netdev(ppp->dev);