xref: /linux/net/smc/smc_inet.c (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *  Shared Memory Communications over RDMA (SMC-R) and RoCE
4  *
5  *  Definitions for the IPPROTO_SMC (socket related)
6  *
7  *  Copyright IBM Corp. 2016, 2018
8  *  Copyright (c) 2024, Alibaba Inc.
9  *
10  *  Author: D. Wythe <alibuda@linux.alibaba.com>
11  */
12 
13 #include <net/protocol.h>
14 #include <net/sock.h>
15 
16 #include "smc_inet.h"
17 #include "smc.h"
18 
19 static int smc_inet_init_sock(struct sock *sk);
20 
21 static struct proto smc_inet_prot = {
22 	.name		= "INET_SMC",
23 	.owner		= THIS_MODULE,
24 	.init		= smc_inet_init_sock,
25 	.hash		= smc_hash_sk,
26 	.unhash		= smc_unhash_sk,
27 	.release_cb	= smc_release_cb,
28 	.obj_size	= sizeof(struct smc_sock),
29 	.h.smc_hash	= &smc_v4_hashinfo,
30 	.slab_flags	= SLAB_TYPESAFE_BY_RCU,
31 };
32 
33 static const struct proto_ops smc_inet_stream_ops = {
34 	.family		= PF_INET,
35 	.owner		= THIS_MODULE,
36 	.release	= smc_release,
37 	.bind		= smc_bind,
38 	.connect	= smc_connect,
39 	.socketpair	= sock_no_socketpair,
40 	.accept		= smc_accept,
41 	.getname	= smc_getname,
42 	.poll		= smc_poll,
43 	.ioctl		= smc_ioctl,
44 	.listen		= smc_listen,
45 	.shutdown	= smc_shutdown,
46 	.setsockopt	= smc_setsockopt,
47 	.getsockopt	= smc_getsockopt,
48 	.sendmsg	= smc_sendmsg,
49 	.recvmsg	= smc_recvmsg,
50 	.mmap		= sock_no_mmap,
51 	.splice_read	= smc_splice_read,
52 };
53 
54 static struct inet_protosw smc_inet_protosw = {
55 	.type		= SOCK_STREAM,
56 	.protocol	= IPPROTO_SMC,
57 	.prot		= &smc_inet_prot,
58 	.ops		= &smc_inet_stream_ops,
59 	.flags		= INET_PROTOSW_ICSK,
60 };
61 
62 #if IS_ENABLED(CONFIG_IPV6)
63 struct smc6_sock {
64 	struct smc_sock		smc;
65 	struct ipv6_pinfo	inet6;
66 };
67 
68 static struct proto smc_inet6_prot = {
69 	.name		= "INET6_SMC",
70 	.owner		= THIS_MODULE,
71 	.init		= smc_inet_init_sock,
72 	.hash		= smc_hash_sk,
73 	.unhash		= smc_unhash_sk,
74 	.release_cb	= smc_release_cb,
75 	.obj_size	= sizeof(struct smc6_sock),
76 	.h.smc_hash	= &smc_v6_hashinfo,
77 	.slab_flags	= SLAB_TYPESAFE_BY_RCU,
78 	.ipv6_pinfo_offset	= offsetof(struct smc6_sock, inet6),
79 };
80 
81 static const struct proto_ops smc_inet6_stream_ops = {
82 	.family		= PF_INET6,
83 	.owner		= THIS_MODULE,
84 	.release	= smc_release,
85 	.bind		= smc_bind,
86 	.connect	= smc_connect,
87 	.socketpair	= sock_no_socketpair,
88 	.accept		= smc_accept,
89 	.getname	= smc_getname,
90 	.poll		= smc_poll,
91 	.ioctl		= smc_ioctl,
92 	.listen		= smc_listen,
93 	.shutdown	= smc_shutdown,
94 	.setsockopt	= smc_setsockopt,
95 	.getsockopt	= smc_getsockopt,
96 	.sendmsg	= smc_sendmsg,
97 	.recvmsg	= smc_recvmsg,
98 	.mmap		= sock_no_mmap,
99 	.splice_read	= smc_splice_read,
100 };
101 
102 static struct inet_protosw smc_inet6_protosw = {
103 	.type		= SOCK_STREAM,
104 	.protocol	= IPPROTO_SMC,
105 	.prot		= &smc_inet6_prot,
106 	.ops		= &smc_inet6_stream_ops,
107 	.flags		= INET_PROTOSW_ICSK,
108 };
109 #endif /* CONFIG_IPV6 */
110 
111 static unsigned int smc_sync_mss(struct sock *sk, u32 pmtu)
112 {
113 	/* No need pass it through to clcsock, mss can always be set by
114 	 * sock_create_kern or smc_setsockopt.
115 	 */
116 	return 0;
117 }
118 
119 static int smc_inet_init_sock(struct sock *sk)
120 {
121 	struct net *net = sock_net(sk);
122 
123 	/* init common smc sock */
124 	smc_sk_init(net, sk, IPPROTO_SMC);
125 
126 	inet_csk(sk)->icsk_sync_mss = smc_sync_mss;
127 
128 	/* create clcsock */
129 	return smc_create_clcsk(net, sk, sk->sk_family);
130 }
131 
132 int __init smc_inet_init(void)
133 {
134 	int rc;
135 
136 	rc = proto_register(&smc_inet_prot, 1);
137 	if (rc) {
138 		pr_err("%s: proto_register smc_inet_prot fails with %d\n",
139 		       __func__, rc);
140 		return rc;
141 	}
142 	/* no return value */
143 	inet_register_protosw(&smc_inet_protosw);
144 
145 #if IS_ENABLED(CONFIG_IPV6)
146 	rc = proto_register(&smc_inet6_prot, 1);
147 	if (rc) {
148 		pr_err("%s: proto_register smc_inet6_prot fails with %d\n",
149 		       __func__, rc);
150 		goto out_inet6_prot;
151 	}
152 	rc = inet6_register_protosw(&smc_inet6_protosw);
153 	if (rc) {
154 		pr_err("%s: inet6_register_protosw smc_inet6_protosw fails with %d\n",
155 		       __func__, rc);
156 		goto out_inet6_protosw;
157 	}
158 	return rc;
159 out_inet6_protosw:
160 	proto_unregister(&smc_inet6_prot);
161 out_inet6_prot:
162 	inet_unregister_protosw(&smc_inet_protosw);
163 	proto_unregister(&smc_inet_prot);
164 #endif /* CONFIG_IPV6 */
165 	return rc;
166 }
167 
168 void smc_inet_exit(void)
169 {
170 #if IS_ENABLED(CONFIG_IPV6)
171 	inet6_unregister_protosw(&smc_inet6_protosw);
172 	proto_unregister(&smc_inet6_prot);
173 #endif /* CONFIG_IPV6 */
174 	inet_unregister_protosw(&smc_inet_protosw);
175 	proto_unregister(&smc_inet_prot);
176 }
177