Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net/smc: Introduce IPPROTO_SMC

This patch allows to create smc socket via AF_INET,
similar to the following code,

/* create v4 smc sock */
v4 = socket(AF_INET, SOCK_STREAM, IPPROTO_SMC);

/* create v6 smc sock */
v6 = socket(AF_INET6, SOCK_STREAM, IPPROTO_SMC);

There are several reasons why we believe it is appropriate here:

1. For smc sockets, it actually use IPv4 (AF-INET) or IPv6 (AF-INET6)
address. There is no AF_SMC address at all.

2. Create smc socket in the AF_INET(6) path, which allows us to reuse
the infrastructure of AF_INET(6) path, such as common ebpf hooks.
Otherwise, smc have to implement it again in AF_SMC path.

Signed-off-by: D. Wythe <alibuda@linux.alibaba.com>
Reviewed-by: Wenjia Zhang <wenjia@linux.ibm.com>
Reviewed-by: Dust Li <dust.li@linux.alibaba.com>
Tested-by: Niklas Schnelle <schnelle@linux.ibm.com>
Tested-by: Wenjia Zhang <wenjia@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

D. Wythe and committed by
David S. Miller
d25a92cc 13543d02

+198 -3
+2
include/uapi/linux/in.h
··· 81 81 #define IPPROTO_ETHERNET IPPROTO_ETHERNET 82 82 IPPROTO_RAW = 255, /* Raw IP packets */ 83 83 #define IPPROTO_RAW IPPROTO_RAW 84 + IPPROTO_SMC = 256, /* Shared Memory Communications */ 85 + #define IPPROTO_SMC IPPROTO_SMC 84 86 IPPROTO_MPTCP = 262, /* Multipath TCP connection */ 85 87 #define IPPROTO_MPTCP IPPROTO_MPTCP 86 88 IPPROTO_MAX
+1 -1
net/smc/Makefile
··· 4 4 obj-$(CONFIG_SMC_DIAG) += smc_diag.o 5 5 smc-y := af_smc.o smc_pnet.o smc_ib.o smc_clc.o smc_core.o smc_wr.o smc_llc.o 6 6 smc-y += smc_cdc.o smc_tx.o smc_rx.o smc_close.o smc_ism.o smc_netlink.o smc_stats.o 7 - smc-y += smc_tracepoint.o 7 + smc-y += smc_tracepoint.o smc_inet.o 8 8 smc-$(CONFIG_SYSCTL) += smc_sysctl.o 9 9 smc-$(CONFIG_SMC_LO) += smc_loopback.o
+14 -2
net/smc/af_smc.c
··· 54 54 #include "smc_tracepoint.h" 55 55 #include "smc_sysctl.h" 56 56 #include "smc_loopback.h" 57 + #include "smc_inet.h" 57 58 58 59 static DEFINE_MUTEX(smc_server_lgr_pending); /* serialize link group 59 60 * creation on server ··· 3576 3575 pr_err("%s: tcp_ulp_register fails with %d\n", __func__, rc); 3577 3576 goto out_lo; 3578 3577 } 3579 - 3578 + rc = smc_inet_init(); 3579 + if (rc) { 3580 + pr_err("%s: smc_inet_init fails with %d\n", __func__, rc); 3581 + goto out_ulp; 3582 + } 3580 3583 static_branch_enable(&tcp_have_smc); 3581 3584 return 0; 3582 - 3585 + out_ulp: 3586 + tcp_unregister_ulp(&smc_ulp_ops); 3583 3587 out_lo: 3584 3588 smc_loopback_exit(); 3585 3589 out_ib: ··· 3621 3615 static void __exit smc_exit(void) 3622 3616 { 3623 3617 static_branch_disable(&tcp_have_smc); 3618 + smc_inet_exit(); 3624 3619 tcp_unregister_ulp(&smc_ulp_ops); 3625 3620 sock_unregister(PF_SMC); 3626 3621 smc_core_exit(); ··· 3649 3642 MODULE_LICENSE("GPL"); 3650 3643 MODULE_ALIAS_NETPROTO(PF_SMC); 3651 3644 MODULE_ALIAS_TCP_ULP("smc"); 3645 + /* 256 for IPPROTO_SMC and 1 for SOCK_STREAM */ 3646 + MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 256, 1); 3647 + #if IS_ENABLED(CONFIG_IPV6) 3648 + MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET6, 256, 1); 3649 + #endif /* CONFIG_IPV6 */ 3652 3650 MODULE_ALIAS_GENL_FAMILY(SMC_GENL_FAMILY_NAME);
+159
net/smc/smc_inet.c
··· 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 + }
+22
net/smc/smc_inet.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 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 8 + * Copyright (c) 2024, Alibaba Inc. 9 + * 10 + * Author: D. Wythe <alibuda@linux.alibaba.com> 11 + */ 12 + #ifndef __INET_SMC 13 + #define __INET_SMC 14 + 15 + /* Initialize protocol registration on IPPROTO_SMC, 16 + * @return 0 on success 17 + */ 18 + int smc_inet_init(void); 19 + 20 + void smc_inet_exit(void); 21 + 22 + #endif /* __INET_SMC */