xref: /linux/drivers/infiniband/sw/rxe/rxe_ns.c (revision 0fc8f6200d2313278fbf4539bbab74677c685531)
1 /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
2 
3 #include <net/sock.h>
4 #include <net/netns/generic.h>
5 #include <net/net_namespace.h>
6 #include <linux/module.h>
7 #include <linux/skbuff.h>
8 #include <linux/pid_namespace.h>
9 #include <net/udp_tunnel.h>
10 
11 #include "rxe_ns.h"
12 
13 /*
14  * Per network namespace data
15  */
16 struct rxe_ns_sock {
17 	struct sock __rcu *rxe_sk4;
18 	struct sock __rcu *rxe_sk6;
19 };
20 
21 /*
22  * Index to store custom data for each network namespace.
23  */
24 static unsigned int rxe_pernet_id;
25 
26 /*
27  * Called for every existing and added network namespaces
28  */
29 static int rxe_ns_init(struct net *net)
30 {
31 	/* defer socket create in the namespace to the first
32 	 * device create.
33 	 */
34 
35 	return 0;
36 }
37 
38 static void rxe_ns_exit(struct net *net)
39 {
40 	/* called when the network namespace is removed
41 	 */
42 	struct rxe_ns_sock *ns_sk = net_generic(net, rxe_pernet_id);
43 	struct sock *sk;
44 
45 	rcu_read_lock();
46 	sk = rcu_dereference(ns_sk->rxe_sk4);
47 	rcu_read_unlock();
48 	if (sk) {
49 		rcu_assign_pointer(ns_sk->rxe_sk4, NULL);
50 		udp_tunnel_sock_release(sk->sk_socket);
51 	}
52 
53 #if IS_ENABLED(CONFIG_IPV6)
54 	rcu_read_lock();
55 	sk = rcu_dereference(ns_sk->rxe_sk6);
56 	rcu_read_unlock();
57 	if (sk) {
58 		rcu_assign_pointer(ns_sk->rxe_sk6, NULL);
59 		udp_tunnel_sock_release(sk->sk_socket);
60 	}
61 #endif
62 }
63 
64 /*
65  * callback to make the module network namespace aware
66  */
67 static struct pernet_operations rxe_net_ops = {
68 	.init = rxe_ns_init,
69 	.exit = rxe_ns_exit,
70 	.id = &rxe_pernet_id,
71 	.size = sizeof(struct rxe_ns_sock),
72 };
73 
74 struct sock *rxe_ns_pernet_sk4(struct net *net)
75 {
76 	struct rxe_ns_sock *ns_sk = net_generic(net, rxe_pernet_id);
77 	struct sock *sk;
78 
79 	rcu_read_lock();
80 	sk = rcu_dereference(ns_sk->rxe_sk4);
81 	rcu_read_unlock();
82 
83 	return sk;
84 }
85 
86 void rxe_ns_pernet_set_sk4(struct net *net, struct sock *sk)
87 {
88 	struct rxe_ns_sock *ns_sk = net_generic(net, rxe_pernet_id);
89 
90 	rcu_assign_pointer(ns_sk->rxe_sk4, sk);
91 	synchronize_rcu();
92 }
93 
94 #if IS_ENABLED(CONFIG_IPV6)
95 struct sock *rxe_ns_pernet_sk6(struct net *net)
96 {
97 	struct rxe_ns_sock *ns_sk = net_generic(net, rxe_pernet_id);
98 	struct sock *sk;
99 
100 	rcu_read_lock();
101 	sk = rcu_dereference(ns_sk->rxe_sk6);
102 	rcu_read_unlock();
103 
104 	return sk;
105 }
106 
107 void rxe_ns_pernet_set_sk6(struct net *net, struct sock *sk)
108 {
109 	struct rxe_ns_sock *ns_sk = net_generic(net, rxe_pernet_id);
110 
111 	rcu_assign_pointer(ns_sk->rxe_sk6, sk);
112 	synchronize_rcu();
113 }
114 #endif /* IPV6 */
115 
116 int rxe_namespace_init(void)
117 {
118 	return register_pernet_subsys(&rxe_net_ops);
119 }
120 
121 void rxe_namespace_exit(void)
122 {
123 	unregister_pernet_subsys(&rxe_net_ops);
124 }
125