xref: /linux/net/smc/smc_sysctl.c (revision 0e50474fa514822e9d990874e554bf8043a201d7)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  *  Shared Memory Communications over RDMA (SMC-R) and RoCE
4  *
5  *  smc_sysctl.c: sysctl interface to SMC subsystem.
6  *
7  *  Copyright (c) 2022, Alibaba Inc.
8  *
9  *  Author: Tony Lu <tonylu@linux.alibaba.com>
10  *
11  */
12 
13 #include <linux/init.h>
14 #include <linux/sysctl.h>
15 #include <net/net_namespace.h>
16 
17 #include "smc.h"
18 #include "smc_core.h"
19 #include "smc_llc.h"
20 #include "smc_sysctl.h"
21 
22 static int min_sndbuf = SMC_BUF_MIN_SIZE;
23 static int min_rcvbuf = SMC_BUF_MIN_SIZE;
24 static int max_sndbuf = INT_MAX / 2;
25 static int max_rcvbuf = INT_MAX / 2;
26 static const int net_smc_wmem_init = (64 * 1024);
27 static const int net_smc_rmem_init = (64 * 1024);
28 static int links_per_lgr_min = SMC_LINKS_ADD_LNK_MIN;
29 static int links_per_lgr_max = SMC_LINKS_ADD_LNK_MAX;
30 static int conns_per_lgr_min = SMC_CONN_PER_LGR_MIN;
31 static int conns_per_lgr_max = SMC_CONN_PER_LGR_MAX;
32 static unsigned int smcr_max_wr_min = 2;
33 static unsigned int smcr_max_wr_max = 2048;
34 
35 static struct ctl_table smc_table[] = {
36 	{
37 		.procname       = "autocorking_size",
38 		.data           = &init_net.smc.sysctl_autocorking_size,
39 		.maxlen         = sizeof(unsigned int),
40 		.mode           = 0644,
41 		.proc_handler	= proc_douintvec,
42 	},
43 	{
44 		.procname	= "smcr_buf_type",
45 		.data		= &init_net.smc.sysctl_smcr_buf_type,
46 		.maxlen		= sizeof(unsigned int),
47 		.mode		= 0644,
48 		.proc_handler	= proc_douintvec_minmax,
49 		.extra1		= SYSCTL_ZERO,
50 		.extra2		= SYSCTL_TWO,
51 	},
52 	{
53 		.procname	= "smcr_testlink_time",
54 		.data		= &init_net.smc.sysctl_smcr_testlink_time,
55 		.maxlen		= sizeof(int),
56 		.mode		= 0644,
57 		.proc_handler	= proc_dointvec_jiffies,
58 	},
59 	{
60 		.procname	= "wmem",
61 		.data		= &init_net.smc.sysctl_wmem,
62 		.maxlen		= sizeof(int),
63 		.mode		= 0644,
64 		.proc_handler	= proc_dointvec_minmax,
65 		.extra1		= &min_sndbuf,
66 		.extra2		= &max_sndbuf,
67 	},
68 	{
69 		.procname	= "rmem",
70 		.data		= &init_net.smc.sysctl_rmem,
71 		.maxlen		= sizeof(int),
72 		.mode		= 0644,
73 		.proc_handler	= proc_dointvec_minmax,
74 		.extra1		= &min_rcvbuf,
75 		.extra2		= &max_rcvbuf,
76 	},
77 	{
78 		.procname	= "smcr_max_links_per_lgr",
79 		.data		= &init_net.smc.sysctl_max_links_per_lgr,
80 		.maxlen		= sizeof(int),
81 		.mode		= 0644,
82 		.proc_handler	= proc_dointvec_minmax,
83 		.extra1		= &links_per_lgr_min,
84 		.extra2		= &links_per_lgr_max,
85 	},
86 	{
87 		.procname	= "smcr_max_conns_per_lgr",
88 		.data		= &init_net.smc.sysctl_max_conns_per_lgr,
89 		.maxlen		= sizeof(int),
90 		.mode		= 0644,
91 		.proc_handler	= proc_dointvec_minmax,
92 		.extra1		= &conns_per_lgr_min,
93 		.extra2		= &conns_per_lgr_max,
94 	},
95 	{
96 		.procname	= "limit_smc_hs",
97 		.data		= &init_net.smc.limit_smc_hs,
98 		.maxlen		= sizeof(int),
99 		.mode		= 0644,
100 		.proc_handler	= proc_dointvec_minmax,
101 		.extra1		= SYSCTL_ZERO,
102 		.extra2		= SYSCTL_ONE,
103 	},
104 	{
105 		.procname	= "smcr_max_send_wr",
106 		.data		= &init_net.smc.sysctl_smcr_max_send_wr,
107 		.maxlen		= sizeof(int),
108 		.mode		= 0644,
109 		.proc_handler	= proc_dointvec_minmax,
110 		.extra1		= &smcr_max_wr_min,
111 		.extra2		= &smcr_max_wr_max,
112 	},
113 	{
114 		.procname	= "smcr_max_recv_wr",
115 		.data		= &init_net.smc.sysctl_smcr_max_recv_wr,
116 		.maxlen		= sizeof(int),
117 		.mode		= 0644,
118 		.proc_handler	= proc_dointvec_minmax,
119 		.extra1		= &smcr_max_wr_min,
120 		.extra2		= &smcr_max_wr_max,
121 	},
122 };
123 
124 int __net_init smc_sysctl_net_init(struct net *net)
125 {
126 	size_t table_size = ARRAY_SIZE(smc_table);
127 	struct ctl_table *table;
128 
129 	table = smc_table;
130 	if (!net_eq(net, &init_net)) {
131 		int i;
132 
133 		table = kmemdup(table, sizeof(smc_table), GFP_KERNEL);
134 		if (!table)
135 			goto err_alloc;
136 
137 		for (i = 0; i < table_size; i++)
138 			table[i].data += (void *)net - (void *)&init_net;
139 	}
140 
141 	net->smc.smc_hdr = register_net_sysctl_sz(net, "net/smc", table,
142 						  table_size);
143 	if (!net->smc.smc_hdr)
144 		goto err_reg;
145 
146 	net->smc.sysctl_autocorking_size = SMC_AUTOCORKING_DEFAULT_SIZE;
147 	net->smc.sysctl_smcr_buf_type = SMCR_PHYS_CONT_BUFS;
148 	net->smc.sysctl_smcr_testlink_time = SMC_LLC_TESTLINK_DEFAULT_TIME;
149 	WRITE_ONCE(net->smc.sysctl_wmem, net_smc_wmem_init);
150 	WRITE_ONCE(net->smc.sysctl_rmem, net_smc_rmem_init);
151 	net->smc.sysctl_max_links_per_lgr = SMC_LINKS_PER_LGR_MAX_PREFER;
152 	net->smc.sysctl_max_conns_per_lgr = SMC_CONN_PER_LGR_PREFER;
153 	net->smc.sysctl_smcr_max_send_wr = SMCR_MAX_SEND_WR_DEF;
154 	net->smc.sysctl_smcr_max_recv_wr = SMCR_MAX_RECV_WR_DEF;
155 	/* disable handshake limitation by default */
156 	net->smc.limit_smc_hs = 0;
157 
158 	return 0;
159 
160 err_reg:
161 	if (!net_eq(net, &init_net))
162 		kfree(table);
163 err_alloc:
164 	return -ENOMEM;
165 }
166 
167 void __net_exit smc_sysctl_net_exit(struct net *net)
168 {
169 	const struct ctl_table *table;
170 
171 	table = net->smc.smc_hdr->ctl_table_arg;
172 	unregister_net_sysctl_table(net->smc.smc_hdr);
173 	if (!net_eq(net, &init_net))
174 		kfree(table);
175 }
176