Skip to content

Commit 4f54dff

Browse files
LGA1150kuba-moo
authored andcommitted
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 <[email protected]> Reviewed-by: Eric Dumazet <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 72cdc67 commit 4f54dff

File tree

1 file changed

+13
-22
lines changed

1 file changed

+13
-22
lines changed

drivers/net/ppp/pppoe.c

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -237,24 +237,22 @@ static inline struct pppox_sock *get_item(struct pppoe_net *pn, __be16 sid,
237237
return po;
238238
}
239239

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)
242242
{
243243
struct net_device *dev;
244244
struct pppoe_net *pn;
245245
struct pppox_sock *pppox_sock = NULL;
246246

247247
int ifindex;
248248

249-
rcu_read_lock();
250249
dev = dev_get_by_name_rcu(net, sp->sa_addr.pppoe.dev);
251250
if (dev) {
252251
ifindex = dev->ifindex;
253252
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);
256255
}
257-
rcu_read_unlock();
258256
return pppox_sock;
259257
}
260258

@@ -381,28 +379,23 @@ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb)
381379
if (sk->sk_state & PPPOX_BOUND) {
382380
ppp_input(&po->chan, skb);
383381
} else if (sk->sk_state & PPPOX_RELAY) {
384-
relay_po = get_item_by_addr(sock_net(sk),
385-
&po->pppoe_relay);
382+
relay_po = __get_item_by_addr(sock_net(sk),
383+
&po->pppoe_relay);
386384
if (relay_po == NULL)
387385
goto abort_kfree;
388386

389387
if ((sk_pppox(relay_po)->sk_state & PPPOX_CONNECTED) == 0)
390-
goto abort_put;
388+
goto abort_kfree;
391389

392390
if (!__pppoe_xmit(sk_pppox(relay_po), skb))
393-
goto abort_put;
394-
395-
sock_put(sk_pppox(relay_po));
391+
goto abort_kfree;
396392
} else {
397393
if (sock_queue_rcv_skb(sk, skb))
398394
goto abort_kfree;
399395
}
400396

401397
return NET_RX_SUCCESS;
402398

403-
abort_put:
404-
sock_put(sk_pppox(relay_po));
405-
406399
abort_kfree:
407400
kfree_skb(skb);
408401
return NET_RX_DROP;
@@ -447,14 +440,11 @@ static int pppoe_rcv(struct sk_buff *skb, struct net_device *dev,
447440
ph = pppoe_hdr(skb);
448441
pn = pppoe_pernet(dev_net(dev));
449442

450-
/* Note that get_item does a sock_hold(), so sk_pppox(po)
451-
* is known to be safe.
452-
*/
453-
po = get_item(pn, ph->sid, eth_hdr(skb)->h_source, dev->ifindex);
443+
po = __get_item(pn, ph->sid, eth_hdr(skb)->h_source, dev->ifindex);
454444
if (!po)
455445
goto drop;
456446

457-
return sk_receive_skb(sk_pppox(po), skb, 0);
447+
return __sk_receive_skb(sk_pppox(po), skb, 0, 1, false);
458448

459449
drop:
460450
kfree_skb(skb);
@@ -820,11 +810,12 @@ static int pppoe_ioctl(struct socket *sock, unsigned int cmd,
820810

821811
/* Check that the socket referenced by the address
822812
actually exists. */
823-
relay_po = get_item_by_addr(sock_net(sk), &po->pppoe_relay);
813+
rcu_read_lock();
814+
relay_po = __get_item_by_addr(sock_net(sk), &po->pppoe_relay);
815+
rcu_read_unlock();
824816
if (!relay_po)
825817
break;
826818

827-
sock_put(sk_pppox(relay_po));
828819
sk->sk_state |= PPPOX_RELAY;
829820
err = 0;
830821
break;

0 commit comments

Comments
 (0)