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 .procname = "limit_smc_hs", 95 .data = &init_net.smc.limit_smc_hs, 96 .maxlen = sizeof(int), 97 .mode = 0644, 98 .proc_handler = proc_dointvec_minmax, 99 .extra1 = SYSCTL_ZERO, 100 .extra2 = SYSCTL_ONE, 101 }, 102 }; 103 104 int __net_init smc_sysctl_net_init(struct net *net) 105 { 106 size_t table_size = ARRAY_SIZE(smc_table); 107 struct ctl_table *table; 108 109 table = smc_table; 110 if (!net_eq(net, &init_net)) { 111 int i; 112 113 table = kmemdup(table, sizeof(smc_table), GFP_KERNEL); 114 if (!table) 115 goto err_alloc; 116 117 for (i = 0; i < table_size; i++) 118 table[i].data += (void *)net - (void *)&init_net; 119 } 120 121 net->smc.smc_hdr = register_net_sysctl_sz(net, "net/smc", table, 122 table_size); 123 if (!net->smc.smc_hdr) 124 goto err_reg; 125 126 net->smc.sysctl_autocorking_size = SMC_AUTOCORKING_DEFAULT_SIZE; 127 net->smc.sysctl_smcr_buf_type = SMCR_PHYS_CONT_BUFS; 128 net->smc.sysctl_smcr_testlink_time = SMC_LLC_TESTLINK_DEFAULT_TIME; 129 WRITE_ONCE(net->smc.sysctl_wmem, net_smc_wmem_init); 130 WRITE_ONCE(net->smc.sysctl_rmem, net_smc_rmem_init); 131 net->smc.sysctl_max_links_per_lgr = SMC_LINKS_PER_LGR_MAX_PREFER; 132 net->smc.sysctl_max_conns_per_lgr = SMC_CONN_PER_LGR_PREFER; 133 /* disable handshake limitation by default */ 134 net->smc.limit_smc_hs = 0; 135 136 return 0; 137 138 err_reg: 139 if (!net_eq(net, &init_net)) 140 kfree(table); 141 err_alloc: 142 return -ENOMEM; 143 } 144 145 void __net_exit smc_sysctl_net_exit(struct net *net) 146 { 147 const struct ctl_table *table; 148 149 table = net->smc.smc_hdr->ctl_table_arg; 150 unregister_net_sysctl_table(net->smc.smc_hdr); 151 if (!net_eq(net, &init_net)) 152 kfree(table); 153 } 154