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 int __net_init smc_sysctl_net_init(struct net *net) 96 { 97 size_t table_size = ARRAY_SIZE(smc_table); 98 struct ctl_table *table; 99 100 table = smc_table; 101 if (!net_eq(net, &init_net)) { 102 int i; 103 104 table = kmemdup(table, sizeof(smc_table), GFP_KERNEL); 105 if (!table) 106 goto err_alloc; 107 108 for (i = 0; i < table_size; i++) 109 table[i].data += (void *)net - (void *)&init_net; 110 } 111 112 net->smc.smc_hdr = register_net_sysctl_sz(net, "net/smc", table, 113 table_size); 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(net, &init_net)) 129 kfree(table); 130 err_alloc: 131 return -ENOMEM; 132 } 133 134 void __net_exit smc_sysctl_net_exit(struct net *net) 135 { 136 const struct ctl_table *table; 137 138 table = net->smc.smc_hdr->ctl_table_arg; 139 unregister_net_sysctl_table(net->smc.smc_hdr); 140 if (!net_eq(net, &init_net)) 141 kfree(table); 142 } 143