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 int smc_inet_init_sock(struct sock *sk) 112 { 113 struct net *net = sock_net(sk); 114 115 /* init common smc sock */ 116 smc_sk_init(net, sk, IPPROTO_SMC); 117 /* create clcsock */ 118 return smc_create_clcsk(net, sk, sk->sk_family); 119 } 120 121 int __init smc_inet_init(void) 122 { 123 int rc; 124 125 rc = proto_register(&smc_inet_prot, 1); 126 if (rc) { 127 pr_err("%s: proto_register smc_inet_prot fails with %d\n", 128 __func__, rc); 129 return rc; 130 } 131 /* no return value */ 132 inet_register_protosw(&smc_inet_protosw); 133 134 #if IS_ENABLED(CONFIG_IPV6) 135 rc = proto_register(&smc_inet6_prot, 1); 136 if (rc) { 137 pr_err("%s: proto_register smc_inet6_prot fails with %d\n", 138 __func__, rc); 139 goto out_inet6_prot; 140 } 141 rc = inet6_register_protosw(&smc_inet6_protosw); 142 if (rc) { 143 pr_err("%s: inet6_register_protosw smc_inet6_protosw fails with %d\n", 144 __func__, rc); 145 goto out_inet6_protosw; 146 } 147 return rc; 148 out_inet6_protosw: 149 proto_unregister(&smc_inet6_prot); 150 out_inet6_prot: 151 inet_unregister_protosw(&smc_inet_protosw); 152 proto_unregister(&smc_inet_prot); 153 #endif /* CONFIG_IPV6 */ 154 return rc; 155 } 156 157 void smc_inet_exit(void) 158 { 159 #if IS_ENABLED(CONFIG_IPV6) 160 inet6_unregister_protosw(&smc_inet6_protosw); 161 proto_unregister(&smc_inet6_prot); 162 #endif /* CONFIG_IPV6 */ 163 inet_unregister_protosw(&smc_inet_protosw); 164 proto_unregister(&smc_inet_prot); 165 } 166