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 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 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 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 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