Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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
19static int smc_inet_init_sock(struct sock *sk);
20
21static 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
33static 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
54static 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)
62struct smc6_sock {
63 struct smc_sock smc;
64 struct ipv6_pinfo inet6;
65};
66
67static 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
80static 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
101static 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
109static 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
119int __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;
146out_inet6_protosw:
147 proto_unregister(&smc_inet6_prot);
148out_inet6_prot:
149 inet_unregister_protosw(&smc_inet_protosw);
150 proto_unregister(&smc_inet_prot);
151#endif /* CONFIG_IPV6 */
152 return rc;
153}
154
155void 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}