pfcp does not need to access struct socket itself in the fast path; it only reads struct sock, and struct socket is only used for tunnel setup and teardown. Let's store struct sock directly in struct pfcp_dev. pfcp_del_sock() is called from dev->netdev_ops->ndo_uninit(). The 2nd synchronize_net() in unregister_netdevice_many_notify() ensures that inflight pfcp RX fast paths finish before pfcp_dev is freed. Note that synchronize_rcu() is added in the error path of pfcp_newlink() since free_netdev() will free pfcp_dev immediately once we remove synchronize_rcu() in udp_tunnel_sock_release(). Signed-off-by: Kuniyuki Iwashima --- drivers/net/pfcp.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/net/pfcp.c b/drivers/net/pfcp.c index 870137695e8a..5f1c9d2c0b49 100644 --- a/drivers/net/pfcp.c +++ b/drivers/net/pfcp.c @@ -18,7 +18,7 @@ struct pfcp_dev { struct list_head list; - struct socket *sock; + struct sock *sk; struct net_device *dev; struct net *net; @@ -104,8 +104,8 @@ static int pfcp_encap_recv(struct sock *sk, struct sk_buff *skb) static void pfcp_del_sock(struct pfcp_dev *pfcp) { - udp_tunnel_sock_release(pfcp->sock->sk); - pfcp->sock = NULL; + udp_tunnel_sock_release(pfcp->sk); + pfcp->sk = NULL; } static void pfcp_dev_uninit(struct net_device *dev) @@ -151,7 +151,7 @@ static void pfcp_link_setup(struct net_device *dev) netif_keep_dst(dev); } -static struct socket *pfcp_create_sock(struct pfcp_dev *pfcp) +static struct sock *pfcp_create_sock(struct pfcp_dev *pfcp) { struct udp_tunnel_sock_cfg tuncfg = {}; struct udp_port_cfg udp_conf = { @@ -174,14 +174,14 @@ static struct socket *pfcp_create_sock(struct pfcp_dev *pfcp) setup_udp_tunnel_sock(net, sock->sk, &tuncfg); - return sock; + return sock->sk; } static int pfcp_add_sock(struct pfcp_dev *pfcp) { - pfcp->sock = pfcp_create_sock(pfcp); + pfcp->sk = pfcp_create_sock(pfcp); - return PTR_ERR_OR_ZERO(pfcp->sock); + return PTR_ERR_OR_ZERO(pfcp->sk); } static int pfcp_newlink(struct net_device *dev, @@ -216,6 +216,7 @@ static int pfcp_newlink(struct net_device *dev, exit_del_pfcp_sock: pfcp_del_sock(pfcp); + synchronize_rcu(); exit_err: pfcp->net = NULL; return err; -- 2.54.0.545.g6539524ca2-goog