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 static struct proto smc_inet6_prot = { 64 .name = "INET6_SMC", 65 .owner = THIS_MODULE, 66 .init = smc_inet_init_sock, 67 .hash = smc_hash_sk, 68 .unhash = smc_unhash_sk, 69 .release_cb = smc_release_cb, 70 .obj_size = sizeof(struct smc_sock), 71 .h.smc_hash = &smc_v6_hashinfo, 72 .slab_flags = SLAB_TYPESAFE_BY_RCU, 73 }; 74 75 static const struct proto_ops smc_inet6_stream_ops = { 76 .family = PF_INET6, 77 .owner = THIS_MODULE, 78 .release = smc_release, 79 .bind = smc_bind, 80 .connect = smc_connect, 81 .socketpair = sock_no_socketpair, 82 .accept = smc_accept, 83 .getname = smc_getname, 84 .poll = smc_poll, 85 .ioctl = smc_ioctl, 86 .listen = smc_listen, 87 .shutdown = smc_shutdown, 88 .setsockopt = smc_setsockopt, 89 .getsockopt = smc_getsockopt, 90 .sendmsg = smc_sendmsg, 91 .recvmsg = smc_recvmsg, 92 .mmap = sock_no_mmap, 93 .splice_read = smc_splice_read, 94 }; 95 96 static struct inet_protosw smc_inet6_protosw = { 97 .type = SOCK_STREAM, 98 .protocol = IPPROTO_SMC, 99 .prot = &smc_inet6_prot, 100 .ops = &smc_inet6_stream_ops, 101 .flags = INET_PROTOSW_ICSK, 102 }; 103 #endif /* CONFIG_IPV6 */ 104 105 static int smc_inet_init_sock(struct sock *sk) 106 { 107 struct net *net = sock_net(sk); 108 109 /* init common smc sock */ 110 smc_sk_init(net, sk, IPPROTO_SMC); 111 /* create clcsock */ 112 return smc_create_clcsk(net, sk, sk->sk_family); 113 } 114 115 int __init smc_inet_init(void) 116 { 117 int rc; 118 119 rc = proto_register(&smc_inet_prot, 1); 120 if (rc) { 121 pr_err("%s: proto_register smc_inet_prot fails with %d\n", 122 __func__, rc); 123 return rc; 124 } 125 /* no return value */ 126 inet_register_protosw(&smc_inet_protosw); 127 128 #if IS_ENABLED(CONFIG_IPV6) 129 rc = proto_register(&smc_inet6_prot, 1); 130 if (rc) { 131 pr_err("%s: proto_register smc_inet6_prot fails with %d\n", 132 __func__, rc); 133 goto out_inet6_prot; 134 } 135 rc = inet6_register_protosw(&smc_inet6_protosw); 136 if (rc) { 137 pr_err("%s: inet6_register_protosw smc_inet6_protosw fails with %d\n", 138 __func__, rc); 139 goto out_inet6_protosw; 140 } 141 return rc; 142 out_inet6_protosw: 143 proto_unregister(&smc_inet6_prot); 144 out_inet6_prot: 145 inet_unregister_protosw(&smc_inet_protosw); 146 proto_unregister(&smc_inet_prot); 147 #endif /* CONFIG_IPV6 */ 148 return rc; 149 } 150 151 void smc_inet_exit(void) 152 { 153 #if IS_ENABLED(CONFIG_IPV6) 154 inet6_unregister_protosw(&smc_inet6_protosw); 155 proto_unregister(&smc_inet6_prot); 156 #endif /* CONFIG_IPV6 */ 157 inet_unregister_protosw(&smc_inet_protosw); 158 proto_unregister(&smc_inet_prot); 159 } 160