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.

pppoe: drop sock reference counting on fast path

Now that PPPoE sockets are freed via RCU (SOCK_RCU_FREE), it is no longer
necessary to take a reference count when looking up sockets on the receive
path. Readers are protected by RCU, so the socket memory remains valid
until after a grace period.

Convert fast-path lookups to avoid refcounting:
- Replace get_item() and sk_receive_skb() in pppoe_rcv() with
__get_item() and __sk_receive_skb().
- Rework get_item_by_addr() into __get_item_by_addr() (no refcount and
move RCU lock into pppoe_ioctl)
- Remove unnecessary sock_put() calls.

This avoids cacheline bouncing from atomic reference counting and improves
performance on the receive fast path.

Signed-off-by: Qingfang Deng <dqfext@gmail.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20250828012018.15922-2-dqfext@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Qingfang Deng and committed by
Jakub Kicinski
4f54dff8 72cdc67e

+13 -22
+13 -22
drivers/net/ppp/pppoe.c
··· 237 237 return po; 238 238 } 239 239 240 - static inline struct pppox_sock *get_item_by_addr(struct net *net, 241 - struct sockaddr_pppox *sp) 240 + static inline struct pppox_sock *__get_item_by_addr(struct net *net, 241 + struct sockaddr_pppox *sp) 242 242 { 243 243 struct net_device *dev; 244 244 struct pppoe_net *pn; ··· 246 246 247 247 int ifindex; 248 248 249 - rcu_read_lock(); 250 249 dev = dev_get_by_name_rcu(net, sp->sa_addr.pppoe.dev); 251 250 if (dev) { 252 251 ifindex = dev->ifindex; 253 252 pn = pppoe_pernet(net); 254 - pppox_sock = get_item(pn, sp->sa_addr.pppoe.sid, 255 - sp->sa_addr.pppoe.remote, ifindex); 253 + pppox_sock = __get_item(pn, sp->sa_addr.pppoe.sid, 254 + sp->sa_addr.pppoe.remote, ifindex); 256 255 } 257 - rcu_read_unlock(); 258 256 return pppox_sock; 259 257 } 260 258 ··· 379 381 if (sk->sk_state & PPPOX_BOUND) { 380 382 ppp_input(&po->chan, skb); 381 383 } else if (sk->sk_state & PPPOX_RELAY) { 382 - relay_po = get_item_by_addr(sock_net(sk), 383 - &po->pppoe_relay); 384 + relay_po = __get_item_by_addr(sock_net(sk), 385 + &po->pppoe_relay); 384 386 if (relay_po == NULL) 385 387 goto abort_kfree; 386 388 387 389 if ((sk_pppox(relay_po)->sk_state & PPPOX_CONNECTED) == 0) 388 - goto abort_put; 390 + goto abort_kfree; 389 391 390 392 if (!__pppoe_xmit(sk_pppox(relay_po), skb)) 391 - goto abort_put; 392 - 393 - sock_put(sk_pppox(relay_po)); 393 + goto abort_kfree; 394 394 } else { 395 395 if (sock_queue_rcv_skb(sk, skb)) 396 396 goto abort_kfree; 397 397 } 398 398 399 399 return NET_RX_SUCCESS; 400 - 401 - abort_put: 402 - sock_put(sk_pppox(relay_po)); 403 400 404 401 abort_kfree: 405 402 kfree_skb(skb); ··· 440 447 ph = pppoe_hdr(skb); 441 448 pn = pppoe_pernet(dev_net(dev)); 442 449 443 - /* Note that get_item does a sock_hold(), so sk_pppox(po) 444 - * is known to be safe. 445 - */ 446 - po = get_item(pn, ph->sid, eth_hdr(skb)->h_source, dev->ifindex); 450 + po = __get_item(pn, ph->sid, eth_hdr(skb)->h_source, dev->ifindex); 447 451 if (!po) 448 452 goto drop; 449 453 450 - return sk_receive_skb(sk_pppox(po), skb, 0); 454 + return __sk_receive_skb(sk_pppox(po), skb, 0, 1, false); 451 455 452 456 drop: 453 457 kfree_skb(skb); ··· 810 820 811 821 /* Check that the socket referenced by the address 812 822 actually exists. */ 813 - relay_po = get_item_by_addr(sock_net(sk), &po->pppoe_relay); 823 + rcu_read_lock(); 824 + relay_po = __get_item_by_addr(sock_net(sk), &po->pppoe_relay); 825 + rcu_read_unlock(); 814 826 if (!relay_po) 815 827 break; 816 828 817 - sock_put(sk_pppox(relay_po)); 818 829 sk->sk_state |= PPPOX_RELAY; 819 830 err = 0; 820 831 break;