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