xref: /linux/net/smc/smc_inet.c (revision da5b2ad1c2f18834cb1ce429e2e5a5cf5cbdf21b)
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 int smc_inet_init_sock(struct sock *sk)
112 {
113 	struct net *net = sock_net(sk);
114 
115 	/* init common smc sock */
116 	smc_sk_init(net, sk, IPPROTO_SMC);
117 	/* create clcsock */
118 	return smc_create_clcsk(net, sk, sk->sk_family);
119 }
120 
121 int __init smc_inet_init(void)
122 {
123 	int rc;
124 
125 	rc = proto_register(&smc_inet_prot, 1);
126 	if (rc) {
127 		pr_err("%s: proto_register smc_inet_prot fails with %d\n",
128 		       __func__, rc);
129 		return rc;
130 	}
131 	/* no return value */
132 	inet_register_protosw(&smc_inet_protosw);
133 
134 #if IS_ENABLED(CONFIG_IPV6)
135 	rc = proto_register(&smc_inet6_prot, 1);
136 	if (rc) {
137 		pr_err("%s: proto_register smc_inet6_prot fails with %d\n",
138 		       __func__, rc);
139 		goto out_inet6_prot;
140 	}
141 	rc = inet6_register_protosw(&smc_inet6_protosw);
142 	if (rc) {
143 		pr_err("%s: inet6_register_protosw smc_inet6_protosw fails with %d\n",
144 		       __func__, rc);
145 		goto out_inet6_protosw;
146 	}
147 	return rc;
148 out_inet6_protosw:
149 	proto_unregister(&smc_inet6_prot);
150 out_inet6_prot:
151 	inet_unregister_protosw(&smc_inet_protosw);
152 	proto_unregister(&smc_inet_prot);
153 #endif /* CONFIG_IPV6 */
154 	return rc;
155 }
156 
157 void smc_inet_exit(void)
158 {
159 #if IS_ENABLED(CONFIG_IPV6)
160 	inet6_unregister_protosw(&smc_inet6_protosw);
161 	proto_unregister(&smc_inet6_prot);
162 #endif /* CONFIG_IPV6 */
163 	inet_unregister_protosw(&smc_inet_protosw);
164 	proto_unregister(&smc_inet_prot);
165 }
166