1 /* 2 * Copyright (c) 1999-2024 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 /* 29 * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce 30 * support for mandatory and extensible security protections. This notice 31 * is included in support of clause 2.2 (b) of the Apple Public License, 32 * Version 2.0. 33 */ 34 35 #include <stdint.h> 36 37 #include <net/dlil_sysctl.h> 38 #include <net/dlil_var_private.h> 39 #include <net/net_api_stats.h> 40 #include <net/net_sysctl.h> 41 42 #if SKYWALK 43 #include <skywalk/os_skywalk_private.h> 44 #endif /* SKYWALK */ 45 46 static int sysctl_rxpoll SYSCTL_HANDLER_ARGS; 47 static int sysctl_rxpoll_mode_holdtime SYSCTL_HANDLER_ARGS; 48 static int sysctl_rxpoll_sample_holdtime SYSCTL_HANDLER_ARGS; 49 static int sysctl_rxpoll_interval_time SYSCTL_HANDLER_ARGS; 50 static int sysctl_rxpoll_wlowat SYSCTL_HANDLER_ARGS; 51 static int sysctl_rxpoll_whiwat SYSCTL_HANDLER_ARGS; 52 static int sysctl_sndq_maxlen SYSCTL_HANDLER_ARGS; 53 static int sysctl_rcvq_maxlen SYSCTL_HANDLER_ARGS; 54 static int sysctl_rcvq_burst_limit SYSCTL_HANDLER_ARGS; 55 static int sysctl_rcvq_trim_pct SYSCTL_HANDLER_ARGS; 56 static int sysctl_hwcksum_dbg_mode SYSCTL_HANDLER_ARGS; 57 static int sysctl_hwcksum_dbg_partial_rxoff_forced SYSCTL_HANDLER_ARGS; 58 static int sysctl_hwcksum_dbg_partial_rxoff_adj SYSCTL_HANDLER_ARGS; 59 static int sysctl_tx_chain_len_stats SYSCTL_HANDLER_ARGS; 60 static int if_enable_fsw_transport_netagent_sysctl SYSCTL_HANDLER_ARGS; 61 62 #if TEST_INPUT_THREAD_TERMINATION 63 static int sysctl_input_thread_termination_spin SYSCTL_HANDLER_ARGS; 64 #endif /* TEST_INPUT_THREAD_TERMINATION */ 65 66 #if (DEVELOPMENT || DEBUG) 67 static int sysctl_get_kao_frames SYSCTL_HANDLER_ARGS; 68 static int if_attach_nx_sysctl SYSCTL_HANDLER_ARGS; 69 #endif /* DEVELOPMENT | DEBUG */ 70 71 72 73 SYSCTL_DECL(_net_link_generic_system); 74 75 /****************************************************************************** 76 * Section: DLIL send and receive queues. * 77 ******************************************************************************/ 78 #define IF_SNDQ_MINLEN 32 79 uint32_t if_sndq_maxlen = IFQ_MAXLEN; /* should it be IFQ_SNDQ_MAXLEN ? */ 80 SYSCTL_PROC(_net_link_generic_system, OID_AUTO, sndq_maxlen, 81 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, &if_sndq_maxlen, IFQ_MAXLEN, 82 sysctl_sndq_maxlen, "I", "Default transmit queue max length"); 83 84 uint32_t if_rcvq_maxlen = IF_RCVQ_MAXLEN; 85 SYSCTL_PROC(_net_link_generic_system, OID_AUTO, rcvq_maxlen, 86 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, &if_rcvq_maxlen, IFQ_MAXLEN, 87 sysctl_rcvq_maxlen, "I", "Default receive queue max length"); 88 89 uint32_t if_delaybased_queue = 1; 90 SYSCTL_UINT(_net_link_generic_system, OID_AUTO, delaybased_queue, 91 CTLFLAG_RW | CTLFLAG_LOCKED, &if_delaybased_queue, 1, 92 "enable delay based dynamic queue sizing"); 93 94 uint32_t ifnet_start_delayed = 0; 95 SYSCTL_UINT(_net_link_generic_system, OID_AUTO, start_delayed, 96 CTLFLAG_RW | CTLFLAG_LOCKED, &ifnet_start_delayed, 0, 97 "number of times start was delayed"); 98 99 uint32_t ifnet_delay_start_disabled = 0; 100 SYSCTL_UINT(_net_link_generic_system, OID_AUTO, start_delay_disabled, 101 CTLFLAG_RW | CTLFLAG_LOCKED, &ifnet_delay_start_disabled, 0, 102 "number of times start was delayed"); 103 104 /* 105 * Protect against possible memory starvation that may happen 106 * when the driver is pushing data faster than the AP can process. 107 * 108 * If at any point during DLIL input phase any of the input queues 109 * exceeds the burst limit, DLIL will start to trim the queue, 110 * by returning mbufs in the input queue to the cache from which 111 * the mbufs were originally allocated, starting from the oldest 112 * mbuf and continuing until the new limit (see below) is reached. 113 * 114 * In order to avoid a steplocked equilibrium, the trimming 115 * will continue PAST the burst limit, until the corresponding 116 * input queue is reduced to `if_rcvq_trim_pct' %. 117 * 118 * For example, if the input queue limit is 1024 packets, 119 * and the trim percentage (`if_rcvq_trim_pct') is 80 %, 120 * the trimming will continue until the queue contains 819 packets 121 * (1024 * 80 / 100 == 819). 122 * 123 * Setting the burst limit too low can hurt the throughput, 124 * while setting the burst limit too high can defeat the purpose. 125 */ 126 #define IF_RCVQ_BURST_LIMIT_MIN 1024 127 #define IF_RCVQ_BURST_LIMIT_DEFAULT 8192 128 #define IF_RCVQ_BURST_LIMIT_MAX 32768 129 uint32_t if_rcvq_burst_limit = IF_RCVQ_BURST_LIMIT_DEFAULT; 130 SYSCTL_PROC(_net_link_generic_system, OID_AUTO, rcvq_burst_limit, 131 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, &if_rcvq_burst_limit, IF_RCVQ_BURST_LIMIT_DEFAULT, 132 sysctl_rcvq_burst_limit, "I", "Upper memory limit for inbound data"); 133 134 #define IF_RCVQ_TRIM_PCT_MIN 20 135 #define IF_RCVQ_TRIM_PCT_DEFAULT 80 136 #define IF_RCVQ_TRIM_PCT_MAX 100 137 uint32_t if_rcvq_trim_pct = IF_RCVQ_TRIM_PCT_DEFAULT; 138 SYSCTL_PROC(_net_link_generic_system, OID_AUTO, rcvq_trim_pct, 139 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, &if_rcvq_trim_pct, IF_RCVQ_TRIM_PCT_DEFAULT, 140 sysctl_rcvq_trim_pct, "I", 141 "Percentage (0 - 100) of the queue limit to keep after detecting an overflow burst"); 142 143 struct chain_len_stats tx_chain_len_stats; 144 SYSCTL_PROC(_net_link_generic_system, OID_AUTO, tx_chain_len_stats, 145 CTLFLAG_RD | CTLFLAG_LOCKED, 0, 9, 146 sysctl_tx_chain_len_stats, "S", ""); 147 148 uint32_t tx_chain_len_count = 0; 149 SYSCTL_UINT(_net_link_generic_system, OID_AUTO, tx_chain_len_count, 150 CTLFLAG_RW | CTLFLAG_LOCKED, &tx_chain_len_count, 0, ""); 151 152 /****************************************************************************** 153 * Section: DLIL opportunistic rx polling. * 154 ******************************************************************************/ 155 156 uint32_t if_rxpoll = 1; 157 SYSCTL_PROC(_net_link_generic_system, OID_AUTO, rxpoll, 158 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, &if_rxpoll, 0, 159 sysctl_rxpoll, "I", "enable opportunistic input polling"); 160 161 #define IF_RXPOLL_DECAY 2 /* ilog2 of EWMA decay rate (4) */ 162 uint32_t if_rxpoll_decay = IF_RXPOLL_DECAY; 163 SYSCTL_UINT(_net_link_generic_system, OID_AUTO, rxpoll_decay, 164 CTLFLAG_RW | CTLFLAG_LOCKED, &if_rxpoll_decay, IF_RXPOLL_DECAY, 165 "ilog2 of EWMA decay rate of avg inbound packets"); 166 167 #define IF_RXPOLL_MODE_HOLDTIME_MIN (10ULL * 1000 * 1000) /* 10 ms */ 168 #define IF_RXPOLL_MODE_HOLDTIME (1000ULL * 1000 * 1000) /* 1 sec */ 169 uint64_t if_rxpoll_mode_holdtime = IF_RXPOLL_MODE_HOLDTIME; 170 SYSCTL_PROC(_net_link_generic_system, OID_AUTO, rxpoll_freeze_time, 171 CTLTYPE_QUAD | CTLFLAG_RW | CTLFLAG_LOCKED, &if_rxpoll_mode_holdtime, 172 IF_RXPOLL_MODE_HOLDTIME, sysctl_rxpoll_mode_holdtime, 173 "Q", "input poll mode freeze time"); 174 175 #define IF_RXPOLL_SAMPLETIME_MIN (1ULL * 1000 * 1000) /* 1 ms */ 176 #define IF_RXPOLL_SAMPLETIME (10ULL * 1000 * 1000) /* 10 ms */ 177 uint64_t if_rxpoll_sample_holdtime = IF_RXPOLL_SAMPLETIME; 178 SYSCTL_PROC(_net_link_generic_system, OID_AUTO, rxpoll_sample_time, 179 CTLTYPE_QUAD | CTLFLAG_RW | CTLFLAG_LOCKED, &if_rxpoll_sample_holdtime, 180 IF_RXPOLL_SAMPLETIME, sysctl_rxpoll_sample_holdtime, 181 "Q", "input poll sampling time"); 182 183 /* Input poll interval definitions */ 184 #define IF_RXPOLL_INTERVALTIME_MIN (1ULL * 1000) /* 1 us */ 185 #define IF_RXPOLL_INTERVALTIME (1ULL * 1000 * 1000) /* 1 ms */ 186 uint64_t if_rxpoll_interval_time = IF_RXPOLL_INTERVALTIME; 187 SYSCTL_PROC(_net_link_generic_system, OID_AUTO, rxpoll_interval_time, 188 CTLTYPE_QUAD | CTLFLAG_RW | CTLFLAG_LOCKED, &if_rxpoll_interval_time, 189 IF_RXPOLL_INTERVALTIME, sysctl_rxpoll_interval_time, 190 "Q", "input poll interval (time)"); 191 192 #define IF_RXPOLL_INTERVAL_PKTS 0 /* 0 (disabled) */ 193 uint32_t if_rxpoll_interval_pkts = IF_RXPOLL_INTERVAL_PKTS; 194 SYSCTL_UINT(_net_link_generic_system, OID_AUTO, rxpoll_interval_pkts, 195 CTLFLAG_RW | CTLFLAG_LOCKED, &if_rxpoll_interval_pkts, 196 IF_RXPOLL_INTERVAL_PKTS, "input poll interval (packets)"); 197 198 #define IF_RXPOLL_WLOWAT 10 199 uint32_t if_sysctl_rxpoll_wlowat = IF_RXPOLL_WLOWAT; 200 SYSCTL_PROC(_net_link_generic_system, OID_AUTO, rxpoll_wakeups_lowat, 201 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, &if_sysctl_rxpoll_wlowat, 202 IF_RXPOLL_WLOWAT, sysctl_rxpoll_wlowat, 203 "I", "input poll wakeup low watermark"); 204 205 #define IF_RXPOLL_WHIWAT 100 206 uint32_t if_sysctl_rxpoll_whiwat = IF_RXPOLL_WHIWAT; 207 SYSCTL_PROC(_net_link_generic_system, OID_AUTO, rxpoll_wakeups_hiwat, 208 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, &if_sysctl_rxpoll_whiwat, 209 IF_RXPOLL_WHIWAT, sysctl_rxpoll_whiwat, 210 "I", "input poll wakeup high watermark"); 211 212 uint32_t if_rxpoll_max = 0; /* automatic */ 213 SYSCTL_UINT(_net_link_generic_system, OID_AUTO, rxpoll_max, 214 CTLFLAG_RW | CTLFLAG_LOCKED, &if_rxpoll_max, 0, 215 "max packets per poll call"); 216 217 #if TEST_INPUT_THREAD_TERMINATION 218 uint32_t if_input_thread_termination_spin = 0 /* disabled */; 219 SYSCTL_PROC(_net_link_generic_system, OID_AUTO, input_thread_termination_spin, 220 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, 221 &if_input_thread_termination_spin, 0, 222 sysctl_input_thread_termination_spin, 223 "I", "input thread termination spin limit"); 224 #endif /* TEST_INPUT_THREAD_TERMINATION */ 225 226 uint32_t cur_dlil_input_threads = 0; 227 SYSCTL_UINT(_net_link_generic_system, OID_AUTO, dlil_input_threads, 228 CTLFLAG_RD | CTLFLAG_LOCKED, &cur_dlil_input_threads, 0, 229 "Current number of DLIL input threads"); 230 231 232 /****************************************************************************** 233 * Section: hardware-assisted checksum mechanism. * 234 ******************************************************************************/ 235 236 uint32_t hwcksum_tx = 1; 237 SYSCTL_UINT(_net_link_generic_system, OID_AUTO, hwcksum_tx, 238 CTLFLAG_RW | CTLFLAG_LOCKED, &hwcksum_tx, 0, 239 "enable transmit hardware checksum offload"); 240 241 uint32_t hwcksum_rx = 1; 242 SYSCTL_UINT(_net_link_generic_system, OID_AUTO, hwcksum_rx, 243 CTLFLAG_RW | CTLFLAG_LOCKED, &hwcksum_rx, 0, 244 "enable receive hardware checksum offload"); 245 246 uint64_t hwcksum_in_invalidated = 0; 247 SYSCTL_QUAD(_net_link_generic_system, OID_AUTO, 248 hwcksum_in_invalidated, CTLFLAG_RD | CTLFLAG_LOCKED, 249 &hwcksum_in_invalidated, "inbound packets with invalidated hardware cksum"); 250 251 uint32_t hwcksum_dbg = 0; 252 SYSCTL_UINT(_net_link_generic_system, OID_AUTO, hwcksum_dbg, 253 CTLFLAG_RW | CTLFLAG_LOCKED, &hwcksum_dbg, 0, 254 "enable hardware cksum debugging"); 255 256 uint32_t hwcksum_dbg_mode = 0; 257 SYSCTL_PROC(_net_link_generic_system, OID_AUTO, hwcksum_dbg_mode, 258 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, &hwcksum_dbg_mode, 259 0, sysctl_hwcksum_dbg_mode, "I", "hardware cksum debugging mode"); 260 261 uint64_t hwcksum_dbg_partial_forced = 0; 262 SYSCTL_QUAD(_net_link_generic_system, OID_AUTO, 263 hwcksum_dbg_partial_forced, CTLFLAG_RD | CTLFLAG_LOCKED, 264 &hwcksum_dbg_partial_forced, "packets forced using partial cksum"); 265 266 uint64_t hwcksum_dbg_partial_forced_bytes = 0; 267 SYSCTL_QUAD(_net_link_generic_system, OID_AUTO, 268 hwcksum_dbg_partial_forced_bytes, CTLFLAG_RD | CTLFLAG_LOCKED, 269 &hwcksum_dbg_partial_forced_bytes, "bytes forced using partial cksum"); 270 271 uint32_t hwcksum_dbg_partial_rxoff_forced = 0; 272 SYSCTL_PROC(_net_link_generic_system, OID_AUTO, 273 hwcksum_dbg_partial_rxoff_forced, CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, 274 &hwcksum_dbg_partial_rxoff_forced, 0, 275 sysctl_hwcksum_dbg_partial_rxoff_forced, "I", 276 "forced partial cksum rx offset"); 277 278 uint32_t hwcksum_dbg_partial_rxoff_adj = 0; 279 SYSCTL_PROC(_net_link_generic_system, OID_AUTO, hwcksum_dbg_partial_rxoff_adj, 280 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, &hwcksum_dbg_partial_rxoff_adj, 281 0, sysctl_hwcksum_dbg_partial_rxoff_adj, "I", 282 "adjusted partial cksum rx offset"); 283 284 uint64_t hwcksum_dbg_verified = 0; 285 SYSCTL_QUAD(_net_link_generic_system, OID_AUTO, 286 hwcksum_dbg_verified, CTLFLAG_RD | CTLFLAG_LOCKED, 287 &hwcksum_dbg_verified, "packets verified for having good checksum"); 288 289 uint64_t hwcksum_dbg_bad_cksum = 0; 290 SYSCTL_QUAD(_net_link_generic_system, OID_AUTO, 291 hwcksum_dbg_bad_cksum, CTLFLAG_RD | CTLFLAG_LOCKED, 292 &hwcksum_dbg_bad_cksum, "packets with bad hardware calculated checksum"); 293 294 uint64_t hwcksum_dbg_bad_rxoff = 0; 295 SYSCTL_QUAD(_net_link_generic_system, OID_AUTO, 296 hwcksum_dbg_bad_rxoff, CTLFLAG_RD | CTLFLAG_LOCKED, 297 &hwcksum_dbg_bad_rxoff, "packets with invalid rxoff"); 298 299 uint64_t hwcksum_dbg_adjusted = 0; 300 SYSCTL_QUAD(_net_link_generic_system, OID_AUTO, 301 hwcksum_dbg_adjusted, CTLFLAG_RD | CTLFLAG_LOCKED, 302 &hwcksum_dbg_adjusted, "packets with rxoff adjusted"); 303 304 uint64_t hwcksum_dbg_finalized_hdr = 0; 305 SYSCTL_QUAD(_net_link_generic_system, OID_AUTO, 306 hwcksum_dbg_finalized_hdr, CTLFLAG_RD | CTLFLAG_LOCKED, 307 &hwcksum_dbg_finalized_hdr, "finalized headers"); 308 309 uint64_t hwcksum_dbg_finalized_data = 0; 310 SYSCTL_QUAD(_net_link_generic_system, OID_AUTO, 311 hwcksum_dbg_finalized_data, CTLFLAG_RD | CTLFLAG_LOCKED, 312 &hwcksum_dbg_finalized_data, "finalized payloads"); 313 314 315 /****************************************************************************** 316 * Section: DLIL debugging, notifications and sanity checks * 317 ******************************************************************************/ 318 319 uint32_t if_flowadv = 1; 320 SYSCTL_UINT(_net_link_generic_system, OID_AUTO, flow_advisory, 321 CTLFLAG_RW | CTLFLAG_LOCKED, &if_flowadv, 1, 322 "enable flow-advisory mechanism"); 323 324 uint32_t threshold_notify = 1; /* enable/disable */ 325 SYSCTL_UINT(_net_link_generic_system, OID_AUTO, threshold_notify, 326 CTLFLAG_RW | CTLFLAG_LOCKED, &threshold_notify, 0, ""); 327 328 uint32_t threshold_interval = 2; /* in seconds */; 329 SYSCTL_UINT(_net_link_generic_system, OID_AUTO, threshold_interval, 330 CTLFLAG_RW | CTLFLAG_LOCKED, &threshold_interval, 0, ""); 331 332 struct net_api_stats net_api_stats; 333 SYSCTL_STRUCT(_net, OID_AUTO, api_stats, CTLFLAG_RD | CTLFLAG_LOCKED, 334 &net_api_stats, net_api_stats, ""); 335 336 #if DEBUG 337 int dlil_verbose = 1; 338 #else 339 int dlil_verbose = 0; 340 #endif /* DEBUG */ 341 342 SYSCTL_INT(_net_link_generic_system, OID_AUTO, dlil_verbose, 343 CTLFLAG_RW | CTLFLAG_LOCKED, &dlil_verbose, 0, "Log DLIL error messages"); 344 345 uint32_t net_wake_pkt_debug = 0; 346 SYSCTL_UINT(_net_link_generic_system, OID_AUTO, wake_pkt_debug, 347 CTLFLAG_RW | CTLFLAG_LOCKED, &net_wake_pkt_debug, 0, ""); 348 349 #if IFNET_INPUT_SANITY_CHK 350 uint32_t dlil_input_sanity_check = 0; 351 SYSCTL_UINT(_net_link_generic_system, OID_AUTO, dlil_input_sanity_check, 352 CTLFLAG_RW | CTLFLAG_LOCKED, &dlil_input_sanity_check, 0, 353 "Turn on sanity checking in DLIL input"); 354 #endif /* IFNET_INPUT_SANITY_CHK */ 355 356 357 #if (DEVELOPMENT || DEBUG) 358 359 static int sysctl_get_kao_frames SYSCTL_HANDLER_ARGS; 360 SYSCTL_NODE(_net_link_generic_system, OID_AUTO, get_kao_frames, 361 CTLFLAG_RD | CTLFLAG_LOCKED, sysctl_get_kao_frames, ""); 362 363 SYSCTL_PROC(_net_link_generic_system, OID_AUTO, if_attach_nx, 364 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, 365 0, 0, &if_attach_nx_sysctl, "IU", "attach nexus"); 366 367 #endif /* DEVELOPMENT || DEBUG */ 368 369 SYSCTL_PROC(_net_link_generic_system, OID_AUTO, enable_netagent, 370 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, 371 0, 0, &if_enable_fsw_transport_netagent_sysctl, "IU", 372 "enable flowswitch netagent"); 373 374 #define DEFAULT_IF_LINK_HEURISTIC \ 375 (IF_LINK_HEURISTICS_CELLULAR | IF_LINK_HEURISTICS_LINK_CONGESTED) 376 uint32_t if_link_heuristics_flags = DEFAULT_IF_LINK_HEURISTIC; 377 SYSCTL_UINT(_net_link_generic_system, OID_AUTO, link_heuristics_flags, 378 CTLFLAG_RW | CTLFLAG_LOCKED, &if_link_heuristics_flags, DEFAULT_IF_LINK_HEURISTIC, ""); 379 380 int if_link_heuristics_lqm_max = 0; 381 SYSCTL_INT(_net_link_generic_system, OID_AUTO, link_heuristics_lqm_max, 382 CTLFLAG_RW | CTLFLAG_LOCKED, &if_link_heuristics_lqm_max, 0, "Max value to enable link heuristics"); 383 384 uint32_t if_link_heuristics_delay = IF_LINK_HEURISTICS_DELAY_MSECS; 385 SYSCTL_UINT(_net_link_generic_system, OID_AUTO, link_heuristics_delay, 386 CTLFLAG_RW | CTLFLAG_LOCKED, &if_link_heuristics_delay, IF_LINK_HEURISTICS_DELAY_MSECS, ""); 387 388 389 #if TEST_INPUT_THREAD_TERMINATION 390 static int 391 sysctl_input_thread_termination_spin SYSCTL_HANDLER_ARGS 392 { 393 #pragma unused(arg1, arg2) 394 uint32_t i; 395 int err; 396 397 i = if_input_thread_termination_spin; 398 399 err = sysctl_handle_int(oidp, &i, 0, req); 400 if (err != 0 || req->newptr == USER_ADDR_NULL) { 401 return err; 402 } 403 404 if (net_rxpoll == 0) { 405 return ENXIO; 406 } 407 408 if_input_thread_termination_spin = i; 409 return err; 410 } 411 #endif /* TEST_INPUT_THREAD_TERMINATION */ 412 413 static int 414 sysctl_rxpoll SYSCTL_HANDLER_ARGS 415 { 416 #pragma unused(arg1, arg2) 417 uint32_t i; 418 int err; 419 420 i = if_rxpoll; 421 422 err = sysctl_handle_int(oidp, &i, 0, req); 423 if (err != 0 || req->newptr == USER_ADDR_NULL) { 424 return err; 425 } 426 427 if (net_rxpoll == 0) { 428 return ENXIO; 429 } 430 431 if_rxpoll = i; 432 return err; 433 } 434 435 static int 436 sysctl_rxpoll_mode_holdtime SYSCTL_HANDLER_ARGS 437 { 438 #pragma unused(arg1, arg2) 439 uint64_t q; 440 int err; 441 442 q = if_rxpoll_mode_holdtime; 443 444 err = sysctl_handle_quad(oidp, &q, 0, req); 445 if (err != 0 || req->newptr == USER_ADDR_NULL) { 446 return err; 447 } 448 449 if (q < IF_RXPOLL_MODE_HOLDTIME_MIN) { 450 q = IF_RXPOLL_MODE_HOLDTIME_MIN; 451 } 452 453 if_rxpoll_mode_holdtime = q; 454 455 return err; 456 } 457 458 static int 459 sysctl_rxpoll_sample_holdtime SYSCTL_HANDLER_ARGS 460 { 461 #pragma unused(arg1, arg2) 462 uint64_t q; 463 int err; 464 465 q = if_rxpoll_sample_holdtime; 466 467 err = sysctl_handle_quad(oidp, &q, 0, req); 468 if (err != 0 || req->newptr == USER_ADDR_NULL) { 469 return err; 470 } 471 472 if (q < IF_RXPOLL_SAMPLETIME_MIN) { 473 q = IF_RXPOLL_SAMPLETIME_MIN; 474 } 475 476 if_rxpoll_sample_holdtime = q; 477 478 return err; 479 } 480 481 static int 482 sysctl_rxpoll_interval_time SYSCTL_HANDLER_ARGS 483 { 484 #pragma unused(arg1, arg2) 485 uint64_t q; 486 int err; 487 488 q = if_rxpoll_interval_time; 489 490 err = sysctl_handle_quad(oidp, &q, 0, req); 491 if (err != 0 || req->newptr == USER_ADDR_NULL) { 492 return err; 493 } 494 495 if (q < IF_RXPOLL_INTERVALTIME_MIN) { 496 q = IF_RXPOLL_INTERVALTIME_MIN; 497 } 498 499 if_rxpoll_interval_time = q; 500 501 return err; 502 } 503 504 static int 505 sysctl_rxpoll_wlowat SYSCTL_HANDLER_ARGS 506 { 507 #pragma unused(arg1, arg2) 508 uint32_t i; 509 int err; 510 511 i = if_sysctl_rxpoll_wlowat; 512 513 err = sysctl_handle_int(oidp, &i, 0, req); 514 if (err != 0 || req->newptr == USER_ADDR_NULL) { 515 return err; 516 } 517 518 if (i == 0 || i >= if_sysctl_rxpoll_whiwat) { 519 return EINVAL; 520 } 521 522 if_sysctl_rxpoll_wlowat = i; 523 return err; 524 } 525 526 static int 527 sysctl_rxpoll_whiwat SYSCTL_HANDLER_ARGS 528 { 529 #pragma unused(arg1, arg2) 530 uint32_t i; 531 int err; 532 533 i = if_sysctl_rxpoll_whiwat; 534 535 err = sysctl_handle_int(oidp, &i, 0, req); 536 if (err != 0 || req->newptr == USER_ADDR_NULL) { 537 return err; 538 } 539 540 if (i <= if_sysctl_rxpoll_wlowat) { 541 return EINVAL; 542 } 543 544 if_sysctl_rxpoll_whiwat = i; 545 return err; 546 } 547 548 static int 549 sysctl_sndq_maxlen SYSCTL_HANDLER_ARGS 550 { 551 #pragma unused(arg1, arg2) 552 int i, err; 553 554 i = if_sndq_maxlen; 555 556 err = sysctl_handle_int(oidp, &i, 0, req); 557 if (err != 0 || req->newptr == USER_ADDR_NULL) { 558 return err; 559 } 560 561 if (i < IF_SNDQ_MINLEN) { 562 i = IF_SNDQ_MINLEN; 563 } 564 565 if_sndq_maxlen = i; 566 return err; 567 } 568 569 static int 570 sysctl_rcvq_maxlen SYSCTL_HANDLER_ARGS 571 { 572 #pragma unused(arg1, arg2) 573 int i, err; 574 575 i = if_rcvq_maxlen; 576 577 err = sysctl_handle_int(oidp, &i, 0, req); 578 if (err != 0 || req->newptr == USER_ADDR_NULL) { 579 return err; 580 } 581 582 if (i < IF_RCVQ_MINLEN) { 583 i = IF_RCVQ_MINLEN; 584 } 585 586 if_rcvq_maxlen = i; 587 return err; 588 } 589 590 static int 591 sysctl_rcvq_burst_limit SYSCTL_HANDLER_ARGS 592 { 593 #pragma unused(arg1, arg2) 594 int i, err; 595 596 i = if_rcvq_burst_limit; 597 598 err = sysctl_handle_int(oidp, &i, 0, req); 599 if (err != 0 || req->newptr == USER_ADDR_NULL) { 600 return err; 601 } 602 603 /* 604 * Safeguard the burst limit to "sane" values on customer builds. 605 */ 606 #if !(DEVELOPMENT || DEBUG) 607 if (i < IF_RCVQ_BURST_LIMIT_MIN) { 608 i = IF_RCVQ_BURST_LIMIT_MIN; 609 } 610 611 if (IF_RCVQ_BURST_LIMIT_MAX < i) { 612 i = IF_RCVQ_BURST_LIMIT_MAX; 613 } 614 #endif 615 616 if_rcvq_burst_limit = i; 617 return err; 618 } 619 620 static int 621 sysctl_rcvq_trim_pct SYSCTL_HANDLER_ARGS 622 { 623 #pragma unused(arg1, arg2) 624 int i, err; 625 626 i = if_rcvq_burst_limit; 627 628 err = sysctl_handle_int(oidp, &i, 0, req); 629 if (err != 0 || req->newptr == USER_ADDR_NULL) { 630 return err; 631 } 632 633 if (IF_RCVQ_TRIM_PCT_MAX < i) { 634 i = IF_RCVQ_TRIM_PCT_MAX; 635 } 636 637 if (i < IF_RCVQ_TRIM_PCT_MIN) { 638 i = IF_RCVQ_TRIM_PCT_MIN; 639 } 640 641 if_rcvq_trim_pct = i; 642 return err; 643 } 644 645 static int 646 sysctl_hwcksum_dbg_mode SYSCTL_HANDLER_ARGS 647 { 648 #pragma unused(arg1, arg2) 649 uint32_t i; 650 int err; 651 652 i = hwcksum_dbg_mode; 653 654 err = sysctl_handle_int(oidp, &i, 0, req); 655 if (err != 0 || req->newptr == USER_ADDR_NULL) { 656 return err; 657 } 658 659 if (hwcksum_dbg == 0) { 660 return ENODEV; 661 } 662 663 if ((i & ~HWCKSUM_DBG_MASK) != 0) { 664 return EINVAL; 665 } 666 667 hwcksum_dbg_mode = (i & HWCKSUM_DBG_MASK); 668 669 return err; 670 } 671 672 static int 673 sysctl_hwcksum_dbg_partial_rxoff_forced SYSCTL_HANDLER_ARGS 674 { 675 #pragma unused(arg1, arg2) 676 u_int32_t i; 677 int err; 678 679 i = hwcksum_dbg_partial_rxoff_forced; 680 681 err = sysctl_handle_int(oidp, &i, 0, req); 682 if (err != 0 || req->newptr == USER_ADDR_NULL) { 683 return err; 684 } 685 686 if (!(hwcksum_dbg_mode & HWCKSUM_DBG_PARTIAL_FORCED)) { 687 return ENODEV; 688 } 689 690 hwcksum_dbg_partial_rxoff_forced = i; 691 692 return err; 693 } 694 695 static int 696 sysctl_hwcksum_dbg_partial_rxoff_adj SYSCTL_HANDLER_ARGS 697 { 698 #pragma unused(arg1, arg2) 699 u_int32_t i; 700 int err; 701 702 i = hwcksum_dbg_partial_rxoff_adj; 703 704 err = sysctl_handle_int(oidp, &i, 0, req); 705 if (err != 0 || req->newptr == USER_ADDR_NULL) { 706 return err; 707 } 708 709 if (!(hwcksum_dbg_mode & HWCKSUM_DBG_PARTIAL_RXOFF_ADJ)) { 710 return ENODEV; 711 } 712 713 hwcksum_dbg_partial_rxoff_adj = i; 714 715 return err; 716 } 717 718 static int 719 sysctl_tx_chain_len_stats SYSCTL_HANDLER_ARGS 720 { 721 #pragma unused(oidp, arg1, arg2) 722 int err; 723 724 if (req->oldptr == USER_ADDR_NULL) { 725 } 726 if (req->newptr != USER_ADDR_NULL) { 727 return EPERM; 728 } 729 err = SYSCTL_OUT(req, &tx_chain_len_stats, 730 sizeof(struct chain_len_stats)); 731 732 return err; 733 } 734 735 #if (DEVELOPMENT || DEBUG) 736 /* 737 * The sysctl variable name contains the input parameters of 738 * ifnet_get_keepalive_offload_frames() 739 * ifp (interface index): name[0] 740 * frames_array_count: name[1] 741 * frame_data_offset: name[2] 742 * The return length gives used_frames_count 743 */ 744 static int 745 sysctl_get_kao_frames SYSCTL_HANDLER_ARGS 746 { 747 #pragma unused(oidp) 748 DECLARE_SYSCTL_HANDLER_ARG_ARRAY(int, 3, name, namelen); 749 int idx; 750 ifnet_t ifp = NULL; 751 u_int32_t frames_array_count; 752 size_t frame_data_offset; 753 u_int32_t used_frames_count; 754 struct ifnet_keepalive_offload_frame *frames_array = NULL; 755 int error = 0; 756 u_int32_t i; 757 758 /* 759 * Only root can get look at other people TCP frames 760 */ 761 error = proc_suser(current_proc()); 762 if (error != 0) { 763 goto done; 764 } 765 /* 766 * Validate the input parameters 767 */ 768 if (req->newptr != USER_ADDR_NULL) { 769 error = EPERM; 770 goto done; 771 } 772 if (req->oldptr == USER_ADDR_NULL) { 773 error = EINVAL; 774 goto done; 775 } 776 if (req->oldlen == 0) { 777 error = EINVAL; 778 goto done; 779 } 780 idx = name[0]; 781 frames_array_count = name[1]; 782 frame_data_offset = name[2]; 783 784 /* Make sure the passed buffer is large enough */ 785 if (frames_array_count * sizeof(struct ifnet_keepalive_offload_frame) > 786 req->oldlen) { 787 error = ENOMEM; 788 goto done; 789 } 790 791 ifnet_head_lock_shared(); 792 if (!IF_INDEX_IN_RANGE(idx)) { 793 ifnet_head_done(); 794 error = ENOENT; 795 goto done; 796 } 797 ifp = ifindex2ifnet[idx]; 798 ifnet_head_done(); 799 800 frames_array = (struct ifnet_keepalive_offload_frame *)kalloc_data( 801 frames_array_count * sizeof(struct ifnet_keepalive_offload_frame), 802 Z_WAITOK); 803 if (frames_array == NULL) { 804 error = ENOMEM; 805 goto done; 806 } 807 808 error = ifnet_get_keepalive_offload_frames(ifp, frames_array, 809 frames_array_count, frame_data_offset, &used_frames_count); 810 if (error != 0) { 811 DLIL_PRINTF("%s: ifnet_get_keepalive_offload_frames error %d\n", 812 __func__, error); 813 goto done; 814 } 815 816 for (i = 0; i < used_frames_count; i++) { 817 error = SYSCTL_OUT(req, frames_array + i, 818 sizeof(struct ifnet_keepalive_offload_frame)); 819 if (error != 0) { 820 goto done; 821 } 822 } 823 done: 824 if (frames_array != NULL) { 825 kfree_data(frames_array, frames_array_count * 826 sizeof(struct ifnet_keepalive_offload_frame)); 827 } 828 return error; 829 } 830 831 static int 832 if_attach_nx_sysctl SYSCTL_HANDLER_ARGS 833 { 834 #pragma unused(oidp, arg1, arg2) 835 unsigned int new_value; 836 int changed; 837 int error = sysctl_io_number(req, if_attach_nx, sizeof(if_attach_nx), 838 &new_value, &changed); 839 if (error) { 840 return error; 841 } 842 if (changed) { 843 if ((new_value & IF_ATTACH_NX_FSW_TRANSPORT_NETAGENT) != 844 (if_attach_nx & IF_ATTACH_NX_FSW_TRANSPORT_NETAGENT)) { 845 return ENOTSUP; 846 } 847 if_attach_nx = new_value; 848 } 849 return 0; 850 } 851 852 #endif /* DEVELOPMENT || DEBUG */ 853 854 static int 855 if_enable_fsw_transport_netagent_sysctl SYSCTL_HANDLER_ARGS 856 { 857 #pragma unused(oidp, arg1, arg2) 858 unsigned int new_value; 859 int changed; 860 int error; 861 862 error = sysctl_io_number(req, if_enable_fsw_transport_netagent, 863 sizeof(if_enable_fsw_transport_netagent), 864 &new_value, &changed); 865 if (error == 0 && changed != 0) { 866 if (new_value != 0 && new_value != 1) { 867 /* only allow 0 or 1 */ 868 error = EINVAL; 869 } else if ((if_attach_nx & IF_ATTACH_NX_FSW_TRANSPORT_NETAGENT) != 0) { 870 /* netagent can be enabled/disabled */ 871 if_enable_fsw_transport_netagent = new_value; 872 if (new_value == 0) { 873 kern_nexus_deregister_netagents(); 874 } else { 875 kern_nexus_register_netagents(); 876 } 877 } else { 878 /* netagent can't be enabled */ 879 error = ENOTSUP; 880 } 881 } 882 return error; 883 } 884