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 | |
33 | static struct ctl_table smc_table[] = { |
34 | { |
35 | .procname = "autocorking_size" , |
36 | .data = &init_net.smc.sysctl_autocorking_size, |
37 | .maxlen = sizeof(unsigned int), |
38 | .mode = 0644, |
39 | .proc_handler = proc_douintvec, |
40 | }, |
41 | { |
42 | .procname = "smcr_buf_type" , |
43 | .data = &init_net.smc.sysctl_smcr_buf_type, |
44 | .maxlen = sizeof(unsigned int), |
45 | .mode = 0644, |
46 | .proc_handler = proc_douintvec_minmax, |
47 | .extra1 = SYSCTL_ZERO, |
48 | .extra2 = SYSCTL_TWO, |
49 | }, |
50 | { |
51 | .procname = "smcr_testlink_time" , |
52 | .data = &init_net.smc.sysctl_smcr_testlink_time, |
53 | .maxlen = sizeof(int), |
54 | .mode = 0644, |
55 | .proc_handler = proc_dointvec_jiffies, |
56 | }, |
57 | { |
58 | .procname = "wmem" , |
59 | .data = &init_net.smc.sysctl_wmem, |
60 | .maxlen = sizeof(int), |
61 | .mode = 0644, |
62 | .proc_handler = proc_dointvec_minmax, |
63 | .extra1 = &min_sndbuf, |
64 | .extra2 = &max_sndbuf, |
65 | }, |
66 | { |
67 | .procname = "rmem" , |
68 | .data = &init_net.smc.sysctl_rmem, |
69 | .maxlen = sizeof(int), |
70 | .mode = 0644, |
71 | .proc_handler = proc_dointvec_minmax, |
72 | .extra1 = &min_rcvbuf, |
73 | .extra2 = &max_rcvbuf, |
74 | }, |
75 | { |
76 | .procname = "smcr_max_links_per_lgr" , |
77 | .data = &init_net.smc.sysctl_max_links_per_lgr, |
78 | .maxlen = sizeof(int), |
79 | .mode = 0644, |
80 | .proc_handler = proc_dointvec_minmax, |
81 | .extra1 = &links_per_lgr_min, |
82 | .extra2 = &links_per_lgr_max, |
83 | }, |
84 | { |
85 | .procname = "smcr_max_conns_per_lgr" , |
86 | .data = &init_net.smc.sysctl_max_conns_per_lgr, |
87 | .maxlen = sizeof(int), |
88 | .mode = 0644, |
89 | .proc_handler = proc_dointvec_minmax, |
90 | .extra1 = &conns_per_lgr_min, |
91 | .extra2 = &conns_per_lgr_max, |
92 | }, |
93 | { } |
94 | }; |
95 | |
96 | int __net_init smc_sysctl_net_init(struct net *net) |
97 | { |
98 | struct ctl_table *table; |
99 | |
100 | table = smc_table; |
101 | if (!net_eq(net1: net, net2: &init_net)) { |
102 | int i; |
103 | |
104 | table = kmemdup(p: table, size: sizeof(smc_table), GFP_KERNEL); |
105 | if (!table) |
106 | goto err_alloc; |
107 | |
108 | for (i = 0; i < ARRAY_SIZE(smc_table) - 1; i++) |
109 | table[i].data += (void *)net - (void *)&init_net; |
110 | } |
111 | |
112 | net->smc.smc_hdr = register_net_sysctl_sz(net, path: "net/smc" , table, |
113 | ARRAY_SIZE(smc_table)); |
114 | if (!net->smc.smc_hdr) |
115 | goto err_reg; |
116 | |
117 | net->smc.sysctl_autocorking_size = SMC_AUTOCORKING_DEFAULT_SIZE; |
118 | net->smc.sysctl_smcr_buf_type = SMCR_PHYS_CONT_BUFS; |
119 | net->smc.sysctl_smcr_testlink_time = SMC_LLC_TESTLINK_DEFAULT_TIME; |
120 | WRITE_ONCE(net->smc.sysctl_wmem, net_smc_wmem_init); |
121 | WRITE_ONCE(net->smc.sysctl_rmem, net_smc_rmem_init); |
122 | net->smc.sysctl_max_links_per_lgr = SMC_LINKS_PER_LGR_MAX_PREFER; |
123 | net->smc.sysctl_max_conns_per_lgr = SMC_CONN_PER_LGR_PREFER; |
124 | |
125 | return 0; |
126 | |
127 | err_reg: |
128 | if (!net_eq(net1: net, net2: &init_net)) |
129 | kfree(objp: table); |
130 | err_alloc: |
131 | return -ENOMEM; |
132 | } |
133 | |
134 | void __net_exit smc_sysctl_net_exit(struct net *net) |
135 | { |
136 | struct ctl_table *table; |
137 | |
138 | table = net->smc.smc_hdr->ctl_table_arg; |
139 | unregister_net_sysctl_table(header: net->smc.smc_hdr); |
140 | if (!net_eq(net1: net, net2: &init_net)) |
141 | kfree(objp: table); |
142 | } |
143 | |