mirror of
https://github.com/torvalds/linux
synced 2024-10-15 15:59:15 +00:00
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>
This commit is contained in:
parent
784c46f546
commit
46ac64419d
|
@ -20,3 +20,16 @@ config SMC_DIAG
|
||||||
smcss.
|
smcss.
|
||||||
|
|
||||||
if unsure, say Y.
|
if unsure, say Y.
|
||||||
|
|
||||||
|
config SMC_LO
|
||||||
|
bool "SMC intra-OS shortcut with loopback-ism"
|
||||||
|
depends on SMC
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
SMC_LO enables the creation of an Emulated-ISM device named
|
||||||
|
loopback-ism in SMC and makes use of it for transferring data
|
||||||
|
when communication occurs within the same OS. This helps in
|
||||||
|
convenient testing of SMC-D since loopback-ism is independent
|
||||||
|
of architecture or hardware.
|
||||||
|
|
||||||
|
if unsure, say N.
|
||||||
|
|
|
@ -6,3 +6,4 @@ smc-y := af_smc.o smc_pnet.o smc_ib.o smc_clc.o smc_core.o smc_wr.o smc_llc.o
|
||||||
smc-y += smc_cdc.o smc_tx.o smc_rx.o smc_close.o smc_ism.o smc_netlink.o smc_stats.o
|
smc-y += smc_cdc.o smc_tx.o smc_rx.o smc_close.o smc_ism.o smc_netlink.o smc_stats.o
|
||||||
smc-y += smc_tracepoint.o
|
smc-y += smc_tracepoint.o
|
||||||
smc-$(CONFIG_SYSCTL) += smc_sysctl.o
|
smc-$(CONFIG_SYSCTL) += smc_sysctl.o
|
||||||
|
smc-$(CONFIG_SMC_LO) += smc_loopback.o
|
||||||
|
|
|
@ -53,6 +53,7 @@
|
||||||
#include "smc_stats.h"
|
#include "smc_stats.h"
|
||||||
#include "smc_tracepoint.h"
|
#include "smc_tracepoint.h"
|
||||||
#include "smc_sysctl.h"
|
#include "smc_sysctl.h"
|
||||||
|
#include "smc_loopback.h"
|
||||||
|
|
||||||
static DEFINE_MUTEX(smc_server_lgr_pending); /* serialize link group
|
static DEFINE_MUTEX(smc_server_lgr_pending); /* serialize link group
|
||||||
* creation on server
|
* creation on server
|
||||||
|
@ -3555,15 +3556,23 @@ static int __init smc_init(void)
|
||||||
goto out_sock;
|
goto out_sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = smc_loopback_init();
|
||||||
|
if (rc) {
|
||||||
|
pr_err("%s: smc_loopback_init fails with %d\n", __func__, rc);
|
||||||
|
goto out_ib;
|
||||||
|
}
|
||||||
|
|
||||||
rc = tcp_register_ulp(&smc_ulp_ops);
|
rc = tcp_register_ulp(&smc_ulp_ops);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
pr_err("%s: tcp_ulp_register fails with %d\n", __func__, rc);
|
pr_err("%s: tcp_ulp_register fails with %d\n", __func__, rc);
|
||||||
goto out_ib;
|
goto out_lo;
|
||||||
}
|
}
|
||||||
|
|
||||||
static_branch_enable(&tcp_have_smc);
|
static_branch_enable(&tcp_have_smc);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
out_lo:
|
||||||
|
smc_loopback_exit();
|
||||||
out_ib:
|
out_ib:
|
||||||
smc_ib_unregister_client();
|
smc_ib_unregister_client();
|
||||||
out_sock:
|
out_sock:
|
||||||
|
@ -3601,6 +3610,7 @@ static void __exit smc_exit(void)
|
||||||
tcp_unregister_ulp(&smc_ulp_ops);
|
tcp_unregister_ulp(&smc_ulp_ops);
|
||||||
sock_unregister(PF_SMC);
|
sock_unregister(PF_SMC);
|
||||||
smc_core_exit();
|
smc_core_exit();
|
||||||
|
smc_loopback_exit();
|
||||||
smc_ib_unregister_client();
|
smc_ib_unregister_client();
|
||||||
smc_ism_exit();
|
smc_ism_exit();
|
||||||
destroy_workqueue(smc_close_wq);
|
destroy_workqueue(smc_close_wq);
|
||||||
|
|
156
net/smc/smc_loopback.c
Normal file
156
net/smc/smc_loopback.c
Normal file
|
@ -0,0 +1,156 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
/*
|
||||||
|
* Shared Memory Communications Direct over loopback-ism device.
|
||||||
|
*
|
||||||
|
* Functions for loopback-ism device.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2024, Alibaba Inc.
|
||||||
|
*
|
||||||
|
* Author: Wen Gu <guwen@linux.alibaba.com>
|
||||||
|
* Tony Lu <tonylu@linux.alibaba.com>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <net/smc.h>
|
||||||
|
|
||||||
|
#include "smc_ism.h"
|
||||||
|
#include "smc_loopback.h"
|
||||||
|
|
||||||
|
static const char smc_lo_dev_name[] = "loopback-ism";
|
||||||
|
static struct smc_lo_dev *lo_dev;
|
||||||
|
|
||||||
|
static const struct smcd_ops lo_ops = {
|
||||||
|
.query_remote_gid = NULL,
|
||||||
|
.register_dmb = NULL,
|
||||||
|
.unregister_dmb = NULL,
|
||||||
|
.add_vlan_id = NULL,
|
||||||
|
.del_vlan_id = NULL,
|
||||||
|
.set_vlan_required = NULL,
|
||||||
|
.reset_vlan_required = NULL,
|
||||||
|
.signal_event = NULL,
|
||||||
|
.move_data = NULL,
|
||||||
|
.supports_v2 = NULL,
|
||||||
|
.get_local_gid = NULL,
|
||||||
|
.get_chid = NULL,
|
||||||
|
.get_dev = NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct smcd_dev *smcd_lo_alloc_dev(const struct smcd_ops *ops,
|
||||||
|
int max_dmbs)
|
||||||
|
{
|
||||||
|
struct smcd_dev *smcd;
|
||||||
|
|
||||||
|
smcd = kzalloc(sizeof(*smcd), GFP_KERNEL);
|
||||||
|
if (!smcd)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
smcd->conn = kcalloc(max_dmbs, sizeof(struct smc_connection *),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!smcd->conn)
|
||||||
|
goto out_smcd;
|
||||||
|
|
||||||
|
smcd->ops = ops;
|
||||||
|
|
||||||
|
spin_lock_init(&smcd->lock);
|
||||||
|
spin_lock_init(&smcd->lgr_lock);
|
||||||
|
INIT_LIST_HEAD(&smcd->vlan);
|
||||||
|
INIT_LIST_HEAD(&smcd->lgr_list);
|
||||||
|
init_waitqueue_head(&smcd->lgrs_deleted);
|
||||||
|
return smcd;
|
||||||
|
|
||||||
|
out_smcd:
|
||||||
|
kfree(smcd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int smcd_lo_register_dev(struct smc_lo_dev *ldev)
|
||||||
|
{
|
||||||
|
struct smcd_dev *smcd;
|
||||||
|
|
||||||
|
smcd = smcd_lo_alloc_dev(&lo_ops, SMC_LO_MAX_DMBS);
|
||||||
|
if (!smcd)
|
||||||
|
return -ENOMEM;
|
||||||
|
ldev->smcd = smcd;
|
||||||
|
smcd->priv = ldev;
|
||||||
|
|
||||||
|
/* TODO:
|
||||||
|
* register loopback-ism to smcd_dev list.
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void smcd_lo_unregister_dev(struct smc_lo_dev *ldev)
|
||||||
|
{
|
||||||
|
struct smcd_dev *smcd = ldev->smcd;
|
||||||
|
|
||||||
|
/* TODO:
|
||||||
|
* unregister loopback-ism from smcd_dev list.
|
||||||
|
*/
|
||||||
|
kfree(smcd->conn);
|
||||||
|
kfree(smcd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int smc_lo_dev_init(struct smc_lo_dev *ldev)
|
||||||
|
{
|
||||||
|
return smcd_lo_register_dev(ldev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void smc_lo_dev_exit(struct smc_lo_dev *ldev)
|
||||||
|
{
|
||||||
|
smcd_lo_unregister_dev(ldev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void smc_lo_dev_release(struct device *dev)
|
||||||
|
{
|
||||||
|
struct smc_lo_dev *ldev =
|
||||||
|
container_of(dev, struct smc_lo_dev, dev);
|
||||||
|
|
||||||
|
kfree(ldev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int smc_lo_dev_probe(void)
|
||||||
|
{
|
||||||
|
struct smc_lo_dev *ldev;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ldev = kzalloc(sizeof(*ldev), GFP_KERNEL);
|
||||||
|
if (!ldev)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
ldev->dev.parent = NULL;
|
||||||
|
ldev->dev.release = smc_lo_dev_release;
|
||||||
|
device_initialize(&ldev->dev);
|
||||||
|
dev_set_name(&ldev->dev, smc_lo_dev_name);
|
||||||
|
|
||||||
|
ret = smc_lo_dev_init(ldev);
|
||||||
|
if (ret)
|
||||||
|
goto free_dev;
|
||||||
|
|
||||||
|
lo_dev = ldev; /* global loopback device */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
free_dev:
|
||||||
|
put_device(&ldev->dev);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void smc_lo_dev_remove(void)
|
||||||
|
{
|
||||||
|
if (!lo_dev)
|
||||||
|
return;
|
||||||
|
|
||||||
|
smc_lo_dev_exit(lo_dev);
|
||||||
|
put_device(&lo_dev->dev); /* device_initialize in smc_lo_dev_probe */
|
||||||
|
}
|
||||||
|
|
||||||
|
int smc_loopback_init(void)
|
||||||
|
{
|
||||||
|
return smc_lo_dev_probe();
|
||||||
|
}
|
||||||
|
|
||||||
|
void smc_loopback_exit(void)
|
||||||
|
{
|
||||||
|
smc_lo_dev_remove();
|
||||||
|
}
|
42
net/smc/smc_loopback.h
Normal file
42
net/smc/smc_loopback.h
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/*
|
||||||
|
* Shared Memory Communications Direct over loopback-ism device.
|
||||||
|
*
|
||||||
|
* SMC-D loopback-ism device structure definitions.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2024, Alibaba Inc.
|
||||||
|
*
|
||||||
|
* Author: Wen Gu <guwen@linux.alibaba.com>
|
||||||
|
* Tony Lu <tonylu@linux.alibaba.com>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SMC_LOOPBACK_H
|
||||||
|
#define _SMC_LOOPBACK_H
|
||||||
|
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <net/smc.h>
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_SMC_LO)
|
||||||
|
#define SMC_LO_MAX_DMBS 5000
|
||||||
|
|
||||||
|
struct smc_lo_dev {
|
||||||
|
struct smcd_dev *smcd;
|
||||||
|
struct device dev;
|
||||||
|
};
|
||||||
|
|
||||||
|
int smc_loopback_init(void);
|
||||||
|
void smc_loopback_exit(void);
|
||||||
|
#else
|
||||||
|
static inline int smc_loopback_init(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void smc_loopback_exit(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _SMC_LOOPBACK_H */
|
Loading…
Reference in a new issue