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
smc_sync_mss(struct sock * sk,u32 pmtu)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
smc_inet_init_sock(struct sock * sk)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
smc_inet_init(void)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
smc_inet_exit(void)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