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:
Wen Gu 2024-04-28 14:07:29 +08:00 committed by Paolo Abeni
parent 784c46f546
commit 46ac64419d
5 changed files with 223 additions and 1 deletions

View File

@ -20,3 +20,16 @@ config SMC_DIAG
smcss.
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.

View File

@ -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_tracepoint.o
smc-$(CONFIG_SYSCTL) += smc_sysctl.o
smc-$(CONFIG_SMC_LO) += smc_loopback.o

View File

@ -53,6 +53,7 @@
#include "smc_stats.h"
#include "smc_tracepoint.h"
#include "smc_sysctl.h"
#include "smc_loopback.h"
static DEFINE_MUTEX(smc_server_lgr_pending); /* serialize link group
* creation on server
@ -3555,15 +3556,23 @@ static int __init smc_init(void)
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);
if (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);
return 0;
out_lo:
smc_loopback_exit();
out_ib:
smc_ib_unregister_client();
out_sock:
@ -3601,6 +3610,7 @@ static void __exit smc_exit(void)
tcp_unregister_ulp(&smc_ulp_ops);
sock_unregister(PF_SMC);
smc_core_exit();
smc_loopback_exit();
smc_ib_unregister_client();
smc_ism_exit();
destroy_workqueue(smc_close_wq);

156
net/smc/smc_loopback.c Normal file
View 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
View 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 */