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