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