162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  Shared Memory Communications over RDMA (SMC-R) and RoCE
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *  Generic netlink support functions to interact with SMC module
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci *  Copyright IBM Corp. 2020
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci *  Author(s):	Guvenc Gulce <guvenc@linux.ibm.com>
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/module.h>
1362306a36Sopenharmony_ci#include <linux/list.h>
1462306a36Sopenharmony_ci#include <linux/ctype.h>
1562306a36Sopenharmony_ci#include <linux/mutex.h>
1662306a36Sopenharmony_ci#include <linux/if.h>
1762306a36Sopenharmony_ci#include <linux/smc.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#include "smc_core.h"
2062306a36Sopenharmony_ci#include "smc_ism.h"
2162306a36Sopenharmony_ci#include "smc_ib.h"
2262306a36Sopenharmony_ci#include "smc_clc.h"
2362306a36Sopenharmony_ci#include "smc_stats.h"
2462306a36Sopenharmony_ci#include "smc_netlink.h"
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ciconst struct nla_policy
2762306a36Sopenharmony_cismc_gen_ueid_policy[SMC_NLA_EID_TABLE_MAX + 1] = {
2862306a36Sopenharmony_ci	[SMC_NLA_EID_TABLE_UNSPEC]	= { .type = NLA_UNSPEC },
2962306a36Sopenharmony_ci	[SMC_NLA_EID_TABLE_ENTRY]	= { .type = NLA_STRING,
3062306a36Sopenharmony_ci					    .len = SMC_MAX_EID_LEN,
3162306a36Sopenharmony_ci					  },
3262306a36Sopenharmony_ci};
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#define SMC_CMD_MAX_ATTR 1
3562306a36Sopenharmony_ci/* SMC_GENL generic netlink operation definition */
3662306a36Sopenharmony_cistatic const struct genl_ops smc_gen_nl_ops[] = {
3762306a36Sopenharmony_ci	{
3862306a36Sopenharmony_ci		.cmd = SMC_NETLINK_GET_SYS_INFO,
3962306a36Sopenharmony_ci		/* can be retrieved by unprivileged users */
4062306a36Sopenharmony_ci		.dumpit = smc_nl_get_sys_info,
4162306a36Sopenharmony_ci	},
4262306a36Sopenharmony_ci	{
4362306a36Sopenharmony_ci		.cmd = SMC_NETLINK_GET_LGR_SMCR,
4462306a36Sopenharmony_ci		/* can be retrieved by unprivileged users */
4562306a36Sopenharmony_ci		.dumpit = smcr_nl_get_lgr,
4662306a36Sopenharmony_ci	},
4762306a36Sopenharmony_ci	{
4862306a36Sopenharmony_ci		.cmd = SMC_NETLINK_GET_LINK_SMCR,
4962306a36Sopenharmony_ci		/* can be retrieved by unprivileged users */
5062306a36Sopenharmony_ci		.dumpit = smcr_nl_get_link,
5162306a36Sopenharmony_ci	},
5262306a36Sopenharmony_ci	{
5362306a36Sopenharmony_ci		.cmd = SMC_NETLINK_GET_LGR_SMCD,
5462306a36Sopenharmony_ci		/* can be retrieved by unprivileged users */
5562306a36Sopenharmony_ci		.dumpit = smcd_nl_get_lgr,
5662306a36Sopenharmony_ci	},
5762306a36Sopenharmony_ci	{
5862306a36Sopenharmony_ci		.cmd = SMC_NETLINK_GET_DEV_SMCD,
5962306a36Sopenharmony_ci		/* can be retrieved by unprivileged users */
6062306a36Sopenharmony_ci		.dumpit = smcd_nl_get_device,
6162306a36Sopenharmony_ci	},
6262306a36Sopenharmony_ci	{
6362306a36Sopenharmony_ci		.cmd = SMC_NETLINK_GET_DEV_SMCR,
6462306a36Sopenharmony_ci		/* can be retrieved by unprivileged users */
6562306a36Sopenharmony_ci		.dumpit = smcr_nl_get_device,
6662306a36Sopenharmony_ci	},
6762306a36Sopenharmony_ci	{
6862306a36Sopenharmony_ci		.cmd = SMC_NETLINK_GET_STATS,
6962306a36Sopenharmony_ci		/* can be retrieved by unprivileged users */
7062306a36Sopenharmony_ci		.dumpit = smc_nl_get_stats,
7162306a36Sopenharmony_ci	},
7262306a36Sopenharmony_ci	{
7362306a36Sopenharmony_ci		.cmd = SMC_NETLINK_GET_FBACK_STATS,
7462306a36Sopenharmony_ci		/* can be retrieved by unprivileged users */
7562306a36Sopenharmony_ci		.dumpit = smc_nl_get_fback_stats,
7662306a36Sopenharmony_ci	},
7762306a36Sopenharmony_ci	{
7862306a36Sopenharmony_ci		.cmd = SMC_NETLINK_DUMP_UEID,
7962306a36Sopenharmony_ci		/* can be retrieved by unprivileged users */
8062306a36Sopenharmony_ci		.dumpit = smc_nl_dump_ueid,
8162306a36Sopenharmony_ci	},
8262306a36Sopenharmony_ci	{
8362306a36Sopenharmony_ci		.cmd = SMC_NETLINK_ADD_UEID,
8462306a36Sopenharmony_ci		.flags = GENL_ADMIN_PERM,
8562306a36Sopenharmony_ci		.doit = smc_nl_add_ueid,
8662306a36Sopenharmony_ci		.policy = smc_gen_ueid_policy,
8762306a36Sopenharmony_ci	},
8862306a36Sopenharmony_ci	{
8962306a36Sopenharmony_ci		.cmd = SMC_NETLINK_REMOVE_UEID,
9062306a36Sopenharmony_ci		.flags = GENL_ADMIN_PERM,
9162306a36Sopenharmony_ci		.doit = smc_nl_remove_ueid,
9262306a36Sopenharmony_ci		.policy = smc_gen_ueid_policy,
9362306a36Sopenharmony_ci	},
9462306a36Sopenharmony_ci	{
9562306a36Sopenharmony_ci		.cmd = SMC_NETLINK_FLUSH_UEID,
9662306a36Sopenharmony_ci		.flags = GENL_ADMIN_PERM,
9762306a36Sopenharmony_ci		.doit = smc_nl_flush_ueid,
9862306a36Sopenharmony_ci	},
9962306a36Sopenharmony_ci	{
10062306a36Sopenharmony_ci		.cmd = SMC_NETLINK_DUMP_SEID,
10162306a36Sopenharmony_ci		/* can be retrieved by unprivileged users */
10262306a36Sopenharmony_ci		.dumpit = smc_nl_dump_seid,
10362306a36Sopenharmony_ci	},
10462306a36Sopenharmony_ci	{
10562306a36Sopenharmony_ci		.cmd = SMC_NETLINK_ENABLE_SEID,
10662306a36Sopenharmony_ci		.flags = GENL_ADMIN_PERM,
10762306a36Sopenharmony_ci		.doit = smc_nl_enable_seid,
10862306a36Sopenharmony_ci	},
10962306a36Sopenharmony_ci	{
11062306a36Sopenharmony_ci		.cmd = SMC_NETLINK_DISABLE_SEID,
11162306a36Sopenharmony_ci		.flags = GENL_ADMIN_PERM,
11262306a36Sopenharmony_ci		.doit = smc_nl_disable_seid,
11362306a36Sopenharmony_ci	},
11462306a36Sopenharmony_ci	{
11562306a36Sopenharmony_ci		.cmd = SMC_NETLINK_DUMP_HS_LIMITATION,
11662306a36Sopenharmony_ci		/* can be retrieved by unprivileged users */
11762306a36Sopenharmony_ci		.dumpit = smc_nl_dump_hs_limitation,
11862306a36Sopenharmony_ci	},
11962306a36Sopenharmony_ci	{
12062306a36Sopenharmony_ci		.cmd = SMC_NETLINK_ENABLE_HS_LIMITATION,
12162306a36Sopenharmony_ci		.flags = GENL_ADMIN_PERM,
12262306a36Sopenharmony_ci		.doit = smc_nl_enable_hs_limitation,
12362306a36Sopenharmony_ci	},
12462306a36Sopenharmony_ci	{
12562306a36Sopenharmony_ci		.cmd = SMC_NETLINK_DISABLE_HS_LIMITATION,
12662306a36Sopenharmony_ci		.flags = GENL_ADMIN_PERM,
12762306a36Sopenharmony_ci		.doit = smc_nl_disable_hs_limitation,
12862306a36Sopenharmony_ci	},
12962306a36Sopenharmony_ci};
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_cistatic const struct nla_policy smc_gen_nl_policy[2] = {
13262306a36Sopenharmony_ci	[SMC_CMD_MAX_ATTR]	= { .type = NLA_REJECT, },
13362306a36Sopenharmony_ci};
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci/* SMC_GENL family definition */
13662306a36Sopenharmony_cistruct genl_family smc_gen_nl_family __ro_after_init = {
13762306a36Sopenharmony_ci	.hdrsize =	0,
13862306a36Sopenharmony_ci	.name =		SMC_GENL_FAMILY_NAME,
13962306a36Sopenharmony_ci	.version =	SMC_GENL_FAMILY_VERSION,
14062306a36Sopenharmony_ci	.maxattr =	SMC_CMD_MAX_ATTR,
14162306a36Sopenharmony_ci	.policy =	smc_gen_nl_policy,
14262306a36Sopenharmony_ci	.netnsok =	true,
14362306a36Sopenharmony_ci	.module =	THIS_MODULE,
14462306a36Sopenharmony_ci	.ops =		smc_gen_nl_ops,
14562306a36Sopenharmony_ci	.n_ops =	ARRAY_SIZE(smc_gen_nl_ops),
14662306a36Sopenharmony_ci	.resv_start_op = SMC_NETLINK_DISABLE_HS_LIMITATION + 1,
14762306a36Sopenharmony_ci};
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ciint __init smc_nl_init(void)
15062306a36Sopenharmony_ci{
15162306a36Sopenharmony_ci	return genl_register_family(&smc_gen_nl_family);
15262306a36Sopenharmony_ci}
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_civoid smc_nl_exit(void)
15562306a36Sopenharmony_ci{
15662306a36Sopenharmony_ci	genl_unregister_family(&smc_gen_nl_family);
15762306a36Sopenharmony_ci}
158