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

net/smc: introduce loopback-ism for SMC intra-OS shortcut

This introduces a kind of Emulated-ISM device named loopback-ism for
SMCv2.1. The loopback-ism device is currently exclusive for SMC usage,
and aims to provide an SMC shortcut for sockets within the same kernel,
leading to improved intra-OS traffic performance. Configuration of this
feature is managed through the config SMC_LO.

Signed-off-by: Wen Gu <guwen@linux.alibaba.com>
Reviewed-by: Gerd Bayer <gbayer@linux.ibm.com>
Reviewed-by: Wenjia Zhang <wenjia@linux.ibm.com>
Reviewed-and-tested-by: Jan Karcher <jaka@linux.ibm.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Wen Gu and committed by
Paolo Abeni
46ac6441 784c46f5

+223 -1
+13
net/smc/Kconfig
··· 20 20 smcss. 21 21 22 22 if unsure, say Y. 23 + 24 + config SMC_LO 25 + bool "SMC intra-OS shortcut with loopback-ism" 26 + depends on SMC 27 + default n 28 + help 29 + SMC_LO enables the creation of an Emulated-ISM device named 30 + loopback-ism in SMC and makes use of it for transferring data 31 + when communication occurs within the same OS. This helps in 32 + convenient testing of SMC-D since loopback-ism is independent 33 + of architecture or hardware. 34 + 35 + if unsure, say N.
+1
net/smc/Makefile
··· 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 7 smc-y += smc_tracepoint.o 8 8 smc-$(CONFIG_SYSCTL) += smc_sysctl.o 9 + smc-$(CONFIG_SMC_LO) += smc_loopback.o
+11 -1
net/smc/af_smc.c
··· 53 53 #include "smc_stats.h" 54 54 #include "smc_tracepoint.h" 55 55 #include "smc_sysctl.h" 56 + #include "smc_loopback.h" 56 57 57 58 static DEFINE_MUTEX(smc_server_lgr_pending); /* serialize link group 58 59 * creation on server ··· 3556 3555 goto out_sock; 3557 3556 } 3558 3557 3558 + rc = smc_loopback_init(); 3559 + if (rc) { 3560 + pr_err("%s: smc_loopback_init fails with %d\n", __func__, rc); 3561 + goto out_ib; 3562 + } 3563 + 3559 3564 rc = tcp_register_ulp(&smc_ulp_ops); 3560 3565 if (rc) { 3561 3566 pr_err("%s: tcp_ulp_register fails with %d\n", __func__, rc); 3562 - goto out_ib; 3567 + goto out_lo; 3563 3568 } 3564 3569 3565 3570 static_branch_enable(&tcp_have_smc); 3566 3571 return 0; 3567 3572 3573 + out_lo: 3574 + smc_loopback_exit(); 3568 3575 out_ib: 3569 3576 smc_ib_unregister_client(); 3570 3577 out_sock: ··· 3610 3601 tcp_unregister_ulp(&smc_ulp_ops); 3611 3602 sock_unregister(PF_SMC); 3612 3603 smc_core_exit(); 3604 + smc_loopback_exit(); 3613 3605 smc_ib_unregister_client(); 3614 3606 smc_ism_exit(); 3615 3607 destroy_workqueue(smc_close_wq);
+156
net/smc/smc_loopback.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Shared Memory Communications Direct over loopback-ism device. 4 + * 5 + * Functions for loopback-ism device. 6 + * 7 + * Copyright (c) 2024, Alibaba Inc. 8 + * 9 + * Author: Wen Gu <guwen@linux.alibaba.com> 10 + * Tony Lu <tonylu@linux.alibaba.com> 11 + * 12 + */ 13 + 14 + #include <linux/device.h> 15 + #include <linux/types.h> 16 + #include <net/smc.h> 17 + 18 + #include "smc_ism.h" 19 + #include "smc_loopback.h" 20 + 21 + static const char smc_lo_dev_name[] = "loopback-ism"; 22 + static struct smc_lo_dev *lo_dev; 23 + 24 + static const struct smcd_ops lo_ops = { 25 + .query_remote_gid = NULL, 26 + .register_dmb = NULL, 27 + .unregister_dmb = NULL, 28 + .add_vlan_id = NULL, 29 + .del_vlan_id = NULL, 30 + .set_vlan_required = NULL, 31 + .reset_vlan_required = NULL, 32 + .signal_event = NULL, 33 + .move_data = NULL, 34 + .supports_v2 = NULL, 35 + .get_local_gid = NULL, 36 + .get_chid = NULL, 37 + .get_dev = NULL, 38 + }; 39 + 40 + static struct smcd_dev *smcd_lo_alloc_dev(const struct smcd_ops *ops, 41 + int max_dmbs) 42 + { 43 + struct smcd_dev *smcd; 44 + 45 + smcd = kzalloc(sizeof(*smcd), GFP_KERNEL); 46 + if (!smcd) 47 + return NULL; 48 + 49 + smcd->conn = kcalloc(max_dmbs, sizeof(struct smc_connection *), 50 + GFP_KERNEL); 51 + if (!smcd->conn) 52 + goto out_smcd; 53 + 54 + smcd->ops = ops; 55 + 56 + spin_lock_init(&smcd->lock); 57 + spin_lock_init(&smcd->lgr_lock); 58 + INIT_LIST_HEAD(&smcd->vlan); 59 + INIT_LIST_HEAD(&smcd->lgr_list); 60 + init_waitqueue_head(&smcd->lgrs_deleted); 61 + return smcd; 62 + 63 + out_smcd: 64 + kfree(smcd); 65 + return NULL; 66 + } 67 + 68 + static int smcd_lo_register_dev(struct smc_lo_dev *ldev) 69 + { 70 + struct smcd_dev *smcd; 71 + 72 + smcd = smcd_lo_alloc_dev(&lo_ops, SMC_LO_MAX_DMBS); 73 + if (!smcd) 74 + return -ENOMEM; 75 + ldev->smcd = smcd; 76 + smcd->priv = ldev; 77 + 78 + /* TODO: 79 + * register loopback-ism to smcd_dev list. 80 + */ 81 + return 0; 82 + } 83 + 84 + static void smcd_lo_unregister_dev(struct smc_lo_dev *ldev) 85 + { 86 + struct smcd_dev *smcd = ldev->smcd; 87 + 88 + /* TODO: 89 + * unregister loopback-ism from smcd_dev list. 90 + */ 91 + kfree(smcd->conn); 92 + kfree(smcd); 93 + } 94 + 95 + static int smc_lo_dev_init(struct smc_lo_dev *ldev) 96 + { 97 + return smcd_lo_register_dev(ldev); 98 + } 99 + 100 + static void smc_lo_dev_exit(struct smc_lo_dev *ldev) 101 + { 102 + smcd_lo_unregister_dev(ldev); 103 + } 104 + 105 + static void smc_lo_dev_release(struct device *dev) 106 + { 107 + struct smc_lo_dev *ldev = 108 + container_of(dev, struct smc_lo_dev, dev); 109 + 110 + kfree(ldev); 111 + } 112 + 113 + static int smc_lo_dev_probe(void) 114 + { 115 + struct smc_lo_dev *ldev; 116 + int ret; 117 + 118 + ldev = kzalloc(sizeof(*ldev), GFP_KERNEL); 119 + if (!ldev) 120 + return -ENOMEM; 121 + 122 + ldev->dev.parent = NULL; 123 + ldev->dev.release = smc_lo_dev_release; 124 + device_initialize(&ldev->dev); 125 + dev_set_name(&ldev->dev, smc_lo_dev_name); 126 + 127 + ret = smc_lo_dev_init(ldev); 128 + if (ret) 129 + goto free_dev; 130 + 131 + lo_dev = ldev; /* global loopback device */ 132 + return 0; 133 + 134 + free_dev: 135 + put_device(&ldev->dev); 136 + return ret; 137 + } 138 + 139 + static void smc_lo_dev_remove(void) 140 + { 141 + if (!lo_dev) 142 + return; 143 + 144 + smc_lo_dev_exit(lo_dev); 145 + put_device(&lo_dev->dev); /* device_initialize in smc_lo_dev_probe */ 146 + } 147 + 148 + int smc_loopback_init(void) 149 + { 150 + return smc_lo_dev_probe(); 151 + } 152 + 153 + void smc_loopback_exit(void) 154 + { 155 + smc_lo_dev_remove(); 156 + }
+42
net/smc/smc_loopback.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Shared Memory Communications Direct over loopback-ism device. 4 + * 5 + * SMC-D loopback-ism device structure definitions. 6 + * 7 + * Copyright (c) 2024, Alibaba Inc. 8 + * 9 + * Author: Wen Gu <guwen@linux.alibaba.com> 10 + * Tony Lu <tonylu@linux.alibaba.com> 11 + * 12 + */ 13 + 14 + #ifndef _SMC_LOOPBACK_H 15 + #define _SMC_LOOPBACK_H 16 + 17 + #include <linux/device.h> 18 + #include <linux/err.h> 19 + #include <net/smc.h> 20 + 21 + #if IS_ENABLED(CONFIG_SMC_LO) 22 + #define SMC_LO_MAX_DMBS 5000 23 + 24 + struct smc_lo_dev { 25 + struct smcd_dev *smcd; 26 + struct device dev; 27 + }; 28 + 29 + int smc_loopback_init(void); 30 + void smc_loopback_exit(void); 31 + #else 32 + static inline int smc_loopback_init(void) 33 + { 34 + return 0; 35 + } 36 + 37 + static inline void smc_loopback_exit(void) 38 + { 39 + } 40 + #endif 41 + 42 + #endif /* _SMC_LOOPBACK_H */