xref: /linux/net/smc/smc_inet.c (revision e3966940559d52aa1800a008dcfeec218dd31f88)
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 };
60 
61 #if IS_ENABLED(CONFIG_IPV6)
62 struct smc6_sock {
63 	struct smc_sock		smc;
64 	struct ipv6_pinfo	inet6;
65 };
66 
67 static struct proto smc_inet6_prot = {
68 	.name		= "INET6_SMC",
69 	.owner		= THIS_MODULE,
70 	.init		= smc_inet_init_sock,
71 	.hash		= smc_hash_sk,
72 	.unhash		= smc_unhash_sk,
73 	.release_cb	= smc_release_cb,
74 	.obj_size	= sizeof(struct smc6_sock),
75 	.h.smc_hash	= &smc_v6_hashinfo,
76 	.slab_flags	= SLAB_TYPESAFE_BY_RCU,
77 	.ipv6_pinfo_offset	= offsetof(struct smc6_sock, inet6),
78 };
79 
80 static const struct proto_ops smc_inet6_stream_ops = {
81 	.family		= PF_INET6,
82 	.owner		= THIS_MODULE,
83 	.release	= smc_release,
84 	.bind		= smc_bind,
85 	.connect	= smc_connect,
86 	.socketpair	= sock_no_socketpair,
87 	.accept		= smc_accept,
88 	.getname	= smc_getname,
89 	.poll		= smc_poll,
90 	.ioctl		= smc_ioctl,
91 	.listen		= smc_listen,
92 	.shutdown	= smc_shutdown,
93 	.setsockopt	= smc_setsockopt,
94 	.getsockopt	= smc_getsockopt,
95 	.sendmsg	= smc_sendmsg,
96 	.recvmsg	= smc_recvmsg,
97 	.mmap		= sock_no_mmap,
98 	.splice_read	= smc_splice_read,
99 };
100 
101 static struct inet_protosw smc_inet6_protosw = {
102 	.type		= SOCK_STREAM,
103 	.protocol	= IPPROTO_SMC,
104 	.prot		= &smc_inet6_prot,
105 	.ops		= &smc_inet6_stream_ops,
106 };
107 #endif /* CONFIG_IPV6 */
108 
109 static int smc_inet_init_sock(struct sock *sk)
110 {
111 	struct net *net = sock_net(sk);
112 
113 	/* init common smc sock */
114 	smc_sk_init(net, sk, IPPROTO_SMC);
115 	/* create clcsock */
116 	return smc_create_clcsk(net, sk, sk->sk_family);
117 }
118 
119 int __init smc_inet_init(void)
120 {
121 	int rc;
122 
123 	rc = proto_register(&smc_inet_prot, 1);
124 	if (rc) {
125 		pr_err("%s: proto_register smc_inet_prot fails with %d\n",
126 		       __func__, rc);
127 		return rc;
128 	}
129 	/* no return value */
130 	inet_register_protosw(&smc_inet_protosw);
131 
132 #if IS_ENABLED(CONFIG_IPV6)
133 	rc = proto_register(&smc_inet6_prot, 1);
134 	if (rc) {
135 		pr_err("%s: proto_register smc_inet6_prot fails with %d\n",
136 		       __func__, rc);
137 		goto out_inet6_prot;
138 	}
139 	rc = inet6_register_protosw(&smc_inet6_protosw);
140 	if (rc) {
141 		pr_err("%s: inet6_register_protosw smc_inet6_protosw fails with %d\n",
142 		       __func__, rc);
143 		goto out_inet6_protosw;
144 	}
145 	return rc;
146 out_inet6_protosw:
147 	proto_unregister(&smc_inet6_prot);
148 out_inet6_prot:
149 	inet_unregister_protosw(&smc_inet_protosw);
150 	proto_unregister(&smc_inet_prot);
151 #endif /* CONFIG_IPV6 */
152 	return rc;
153 }
154 
155 void smc_inet_exit(void)
156 {
157 #if IS_ENABLED(CONFIG_IPV6)
158 	inet6_unregister_protosw(&smc_inet6_protosw);
159 	proto_unregister(&smc_inet6_prot);
160 #endif /* CONFIG_IPV6 */
161 	inet_unregister_protosw(&smc_inet_protosw);
162 	proto_unregister(&smc_inet_prot);
163 }
164