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.
Unified · Split
| @@ -81,6 +81,8 @@ enum { · 80 unmodified lines | |||
| 81 | #define IPPROTO_ETHERNET IPPROTO_ETHERNET | 81 | #define IPPROTO_ETHERNET IPPROTO_ETHERNET |
| 82 | IPPROTO_RAW = 255, /* Raw IP packets */ | 82 | IPPROTO_RAW = 255, /* Raw IP packets */ |
| 83 | #define IPPROTO_RAW IPPROTO_RAW | 83 | #define IPPROTO_RAW IPPROTO_RAW |
| 84 | IPPROTO_SMC = 256, /* Shared Memory Communications */ | ||
| 85 | #define IPPROTO_SMC IPPROTO_SMC | ||
| 84 | IPPROTO_MPTCP = 262, /* Multipath TCP connection */ | 86 | IPPROTO_MPTCP = 262, /* Multipath TCP connection */ |
| 85 | #define IPPROTO_MPTCP IPPROTO_MPTCP | 87 | #define IPPROTO_MPTCP IPPROTO_MPTCP |
| 86 | IPPROTO_MAX | 88 | IPPROTO_MAX |
| @@ -4,6 +4,6 @@ obj-$(CONFIG_SMC) += smc.o · 3 unmodified lines | |||
| 4 | obj-$(CONFIG_SMC_DIAG) += smc_diag.o | 4 | obj-$(CONFIG_SMC_DIAG) += smc_diag.o |
| 5 | smc-y := af_smc.o smc_pnet.o smc_ib.o smc_clc.o smc_core.o smc_wr.o smc_llc.o | 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 | smc-y += smc_cdc.o smc_tx.o smc_rx.o smc_close.o smc_ism.o smc_netlink.o smc_stats.o | 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 | smc-$(CONFIG_SYSCTL) += smc_sysctl.o | 8 | smc-$(CONFIG_SYSCTL) += smc_sysctl.o |
| 9 | smc-$(CONFIG_SMC_LO) += smc_loopback.o | 9 | smc-$(CONFIG_SMC_LO) += smc_loopback.o |
| @@ -54,6 +54,7 @@ · 53 unmodified lines | |||
| 54 | #include "smc_tracepoint.h" | 54 | #include "smc_tracepoint.h" |
| 55 | #include "smc_sysctl.h" | 55 | #include "smc_sysctl.h" |
| 56 | #include "smc_loopback.h" | 56 | #include "smc_loopback.h" |
| 57 | #include "smc_inet.h" | ||
| 57 | 58 | ||
| 58 | static DEFINE_MUTEX(smc_server_lgr_pending); /* serialize link group | 59 | static DEFINE_MUTEX(smc_server_lgr_pending); /* serialize link group |
| 59 | * creation on server | 60 | * creation on server |
| @@ -3575,10 +3576,15 @@ static int __init smc_init(void) · 3515 unmodified lines | |||
| 3575 | pr_err("%s: tcp_ulp_register fails with %d\n", __func__, rc); | 3576 | pr_err("%s: tcp_ulp_register fails with %d\n", __func__, rc); |
| 3576 | goto out_lo; | 3577 | goto out_lo; |
| 3577 | } | 3578 | } |
| 3578 | 3579 | rc = smc_inet_init(); | |
| 3580 | if (rc) { | ||
| 3581 | pr_err("%s: smc_inet_init fails with %d\n", __func__, rc); | ||
| 3582 | goto out_ulp; | ||
| 3583 | } | ||
| 3579 | static_branch_enable(&tcp_have_smc); | 3584 | static_branch_enable(&tcp_have_smc); |
| 3580 | return 0; | 3585 | return 0; |
| 3581 | 3586 | out_ulp: | |
| 3587 | tcp_unregister_ulp(&smc_ulp_ops); | ||
| 3582 | out_lo: | 3588 | out_lo: |
| 3583 | smc_loopback_exit(); | 3589 | smc_loopback_exit(); |
| 3584 | out_ib: | 3590 | out_ib: |
| @@ -3615,6 +3621,7 @@ out_pernet_subsys: · 30 unmodified lines | |||
| 3615 | static void __exit smc_exit(void) | 3621 | static void __exit smc_exit(void) |
| 3616 | { | 3622 | { |
| 3617 | static_branch_disable(&tcp_have_smc); | 3623 | static_branch_disable(&tcp_have_smc); |
| 3624 | smc_inet_exit(); | ||
| 3618 | tcp_unregister_ulp(&smc_ulp_ops); | 3625 | tcp_unregister_ulp(&smc_ulp_ops); |
| 3619 | sock_unregister(PF_SMC); | 3626 | sock_unregister(PF_SMC); |
| 3620 | smc_core_exit(); | 3627 | smc_core_exit(); |
| @@ -3642,4 +3649,9 @@ MODULE_DESCRIPTION("smc socket address family"); · 21 unmodified lines | |||
| 3642 | MODULE_LICENSE("GPL"); | 3649 | MODULE_LICENSE("GPL"); |
| 3643 | MODULE_ALIAS_NETPROTO(PF_SMC); | 3650 | MODULE_ALIAS_NETPROTO(PF_SMC); |
| 3644 | MODULE_ALIAS_TCP_ULP("smc"); | 3651 | MODULE_ALIAS_TCP_ULP("smc"); |
| 3652 | /* 256 for IPPROTO_SMC and 1 for SOCK_STREAM */ | ||
| 3653 | MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 256, 1); | ||
| 3654 | #if IS_ENABLED(CONFIG_IPV6) | ||
| 3655 | MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET6, 256, 1); | ||
| 3656 | #endif /* CONFIG_IPV6 */ | ||
| 3645 | MODULE_ALIAS_GENL_FAMILY(SMC_GENL_FAMILY_NAME); | 3657 | MODULE_ALIAS_GENL_FAMILY(SMC_GENL_FAMILY_NAME); |
| @@ -0,0 +1,159 @@ | |||
| 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 | } | ||
| @@ -0,0 +1,22 @@ | |||
| 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 */ | ||