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 375 376 #if TEST_INPUT_THREAD_TERMINATION 377 static int 378 sysctl_input_thread_termination_spin SYSCTL_HANDLER_ARGS 379 { 380 #pragma unused(arg1, arg2) 381 uint32_t i; 382 int err; 383 384 i = if_input_thread_termination_spin; 385 386 err = sysctl_handle_int(oidp, &i, 0, req); 387 if (err != 0 || req->newptr == USER_ADDR_NULL) { 388 return err; 389 } 390 391 if (net_rxpoll == 0) { 392 return ENXIO; 393 } 394 395 if_input_thread_termination_spin = i; 396 return err; 397 } 398 #endif /* TEST_INPUT_THREAD_TERMINATION */ 399 400 static int 401 sysctl_rxpoll SYSCTL_HANDLER_ARGS 402 { 403 #pragma unused(arg1, arg2) 404 uint32_t i; 405 int err; 406 407 i = if_rxpoll; 408 409 err = sysctl_handle_int(oidp, &i, 0, req); 410 if (err != 0 || req->newptr == USER_ADDR_NULL) { 411 return err; 412 } 413 414 if (net_rxpoll == 0) { 415 return ENXIO; 416 } 417 418 if_rxpoll = i; 419 return err; 420 } 421 422 static int 423 sysctl_rxpoll_mode_holdtime SYSCTL_HANDLER_ARGS 424 { 425 #pragma unused(arg1, arg2) 426 uint64_t q; 427 int err; 428 429 q = if_rxpoll_mode_holdtime; 430 431 err = sysctl_handle_quad(oidp, &q, 0, req); 432 if (err != 0 || req->newptr == USER_ADDR_NULL) { 433 return err; 434 } 435 436 if (q < IF_RXPOLL_MODE_HOLDTIME_MIN) { 437 q = IF_RXPOLL_MODE_HOLDTIME_MIN; 438 } 439 440 if_rxpoll_mode_holdtime = q; 441 442 return err; 443 } 444 445 static int 446 sysctl_rxpoll_sample_holdtime SYSCTL_HANDLER_ARGS 447 { 448 #pragma unused(arg1, arg2) 449 uint64_t q; 450 int err; 451 452 q = if_rxpoll_sample_holdtime; 453 454 err = sysctl_handle_quad(oidp, &q, 0, req); 455 if (err != 0 || req->newptr == USER_ADDR_NULL) { 456 return err; 457 } 458 459 if (q < IF_RXPOLL_SAMPLETIME_MIN) { 460 q = IF_RXPOLL_SAMPLETIME_MIN; 461 } 462 463 if_rxpoll_sample_holdtime = q; 464 465 return err; 466 } 467 468 static int 469 sysctl_rxpoll_interval_time SYSCTL_HANDLER_ARGS 470 { 471 #pragma unused(arg1, arg2) 472 uint64_t q; 473 int err; 474 475 q = if_rxpoll_interval_time; 476 477 err = sysctl_handle_quad(oidp, &q, 0, req); 478 if (err != 0 || req->newptr == USER_ADDR_NULL) { 479 return err; 480 } 481 482 if (q < IF_RXPOLL_INTERVALTIME_MIN) { 483 q = IF_RXPOLL_INTERVALTIME_MIN; 484 } 485 486 if_rxpoll_interval_time = q; 487 488 return err; 489 } 490 491 static int 492 sysctl_rxpoll_wlowat SYSCTL_HANDLER_ARGS 493 { 494 #pragma unused(arg1, arg2) 495 uint32_t i; 496 int err; 497 498 i = if_sysctl_rxpoll_wlowat; 499 500 err = sysctl_handle_int(oidp, &i, 0, req); 501 if (err != 0 || req->newptr == USER_ADDR_NULL) { 502 return err; 503 } 504 505 if (i == 0 || i >= if_sysctl_rxpoll_whiwat) { 506 return EINVAL; 507 } 508 509 if_sysctl_rxpoll_wlowat = i; 510 return err; 511 } 512 513 static int 514 sysctl_rxpoll_whiwat SYSCTL_HANDLER_ARGS 515 { 516 #pragma unused(arg1, arg2) 517 uint32_t i; 518 int err; 519 520 i = if_sysctl_rxpoll_whiwat; 521 522 err = sysctl_handle_int(oidp, &i, 0, req); 523 if (err != 0 || req->newptr == USER_ADDR_NULL) { 524 return err; 525 } 526 527 if (i <= if_sysctl_rxpoll_wlowat) { 528 return EINVAL; 529 } 530 531 if_sysctl_rxpoll_whiwat = i; 532 return err; 533 } 534 535 static int 536 sysctl_sndq_maxlen SYSCTL_HANDLER_ARGS 537 { 538 #pragma unused(arg1, arg2) 539 int i, err; 540 541 i = if_sndq_maxlen; 542 543 err = sysctl_handle_int(oidp, &i, 0, req); 544 if (err != 0 || req->newptr == USER_ADDR_NULL) { 545 return err; 546 } 547 548 if (i < IF_SNDQ_MINLEN) { 549 i = IF_SNDQ_MINLEN; 550 } 551 552 if_sndq_maxlen = i; 553 return err; 554 } 555 556 static int 557 sysctl_rcvq_maxlen SYSCTL_HANDLER_ARGS 558 { 559 #pragma unused(arg1, arg2) 560 int i, err; 561 562 i = if_rcvq_maxlen; 563 564 err = sysctl_handle_int(oidp, &i, 0, req); 565 if (err != 0 || req->newptr == USER_ADDR_NULL) { 566 return err; 567 } 568 569 if (i < IF_RCVQ_MINLEN) { 570 i = IF_RCVQ_MINLEN; 571 } 572 573 if_rcvq_maxlen = i; 574 return err; 575 } 576 577 static int 578 sysctl_rcvq_burst_limit SYSCTL_HANDLER_ARGS 579 { 580 #pragma unused(arg1, arg2) 581 int i, err; 582 583 i = if_rcvq_burst_limit; 584 585 err = sysctl_handle_int(oidp, &i, 0, req); 586 if (err != 0 || req->newptr == USER_ADDR_NULL) { 587 return err; 588 } 589 590 /* 591 * Safeguard the burst limit to "sane" values on customer builds. 592 */ 593 #if !(DEVELOPMENT || DEBUG) 594 if (i < IF_RCVQ_BURST_LIMIT_MIN) { 595 i = IF_RCVQ_BURST_LIMIT_MIN; 596 } 597 598 if (IF_RCVQ_BURST_LIMIT_MAX < i) { 599 i = IF_RCVQ_BURST_LIMIT_MAX; 600 } 601 #endif 602 603 if_rcvq_burst_limit = i; 604 return err; 605 } 606 607 static int 608 sysctl_rcvq_trim_pct SYSCTL_HANDLER_ARGS 609 { 610 #pragma unused(arg1, arg2) 611 int i, err; 612 613 i = if_rcvq_burst_limit; 614 615 err = sysctl_handle_int(oidp, &i, 0, req); 616 if (err != 0 || req->newptr == USER_ADDR_NULL) { 617 return err; 618 } 619 620 if (IF_RCVQ_TRIM_PCT_MAX < i) { 621 i = IF_RCVQ_TRIM_PCT_MAX; 622 } 623 624 if (i < IF_RCVQ_TRIM_PCT_MIN) { 625 i = IF_RCVQ_TRIM_PCT_MIN; 626 } 627 628 if_rcvq_trim_pct = i; 629 return err; 630 } 631 632 static int 633 sysctl_hwcksum_dbg_mode SYSCTL_HANDLER_ARGS 634 { 635 #pragma unused(arg1, arg2) 636 uint32_t i; 637 int err; 638 639 i = hwcksum_dbg_mode; 640 641 err = sysctl_handle_int(oidp, &i, 0, req); 642 if (err != 0 || req->newptr == USER_ADDR_NULL) { 643 return err; 644 } 645 646 if (hwcksum_dbg == 0) { 647 return ENODEV; 648 } 649 650 if ((i & ~HWCKSUM_DBG_MASK) != 0) { 651 return EINVAL; 652 } 653 654 hwcksum_dbg_mode = (i & HWCKSUM_DBG_MASK); 655 656 return err; 657 } 658 659 static int 660 sysctl_hwcksum_dbg_partial_rxoff_forced SYSCTL_HANDLER_ARGS 661 { 662 #pragma unused(arg1, arg2) 663 u_int32_t i; 664 int err; 665 666 i = hwcksum_dbg_partial_rxoff_forced; 667 668 err = sysctl_handle_int(oidp, &i, 0, req); 669 if (err != 0 || req->newptr == USER_ADDR_NULL) { 670 return err; 671 } 672 673 if (!(hwcksum_dbg_mode & HWCKSUM_DBG_PARTIAL_FORCED)) { 674 return ENODEV; 675 } 676 677 hwcksum_dbg_partial_rxoff_forced = i; 678 679 return err; 680 } 681 682 static int 683 sysctl_hwcksum_dbg_partial_rxoff_adj SYSCTL_HANDLER_ARGS 684 { 685 #pragma unused(arg1, arg2) 686 u_int32_t i; 687 int err; 688 689 i = hwcksum_dbg_partial_rxoff_adj; 690 691 err = sysctl_handle_int(oidp, &i, 0, req); 692 if (err != 0 || req->newptr == USER_ADDR_NULL) { 693 return err; 694 } 695 696 if (!(hwcksum_dbg_mode & HWCKSUM_DBG_PARTIAL_RXOFF_ADJ)) { 697 return ENODEV; 698 } 699 700 hwcksum_dbg_partial_rxoff_adj = i; 701 702 return err; 703 } 704 705 static int 706 sysctl_tx_chain_len_stats SYSCTL_HANDLER_ARGS 707 { 708 #pragma unused(oidp, arg1, arg2) 709 int err; 710 711 if (req->oldptr == USER_ADDR_NULL) { 712 } 713 if (req->newptr != USER_ADDR_NULL) { 714 return EPERM; 715 } 716 err = SYSCTL_OUT(req, &tx_chain_len_stats, 717 sizeof(struct chain_len_stats)); 718 719 return err; 720 } 721 722 #if (DEVELOPMENT || DEBUG) 723 /* 724 * The sysctl variable name contains the input parameters of 725 * ifnet_get_keepalive_offload_frames() 726 * ifp (interface index): name[0] 727 * frames_array_count: name[1] 728 * frame_data_offset: name[2] 729 * The return length gives used_frames_count 730 */ 731 static int 732 sysctl_get_kao_frames SYSCTL_HANDLER_ARGS 733 { 734 #pragma unused(oidp) 735 DECLARE_SYSCTL_HANDLER_ARG_ARRAY(int, 3, name, namelen); 736 int idx; 737 ifnet_t ifp = NULL; 738 u_int32_t frames_array_count; 739 size_t frame_data_offset; 740 u_int32_t used_frames_count; 741 struct ifnet_keepalive_offload_frame *frames_array = NULL; 742 int error = 0; 743 u_int32_t i; 744 745 /* 746 * Only root can get look at other people TCP frames 747 */ 748 error = proc_suser(current_proc()); 749 if (error != 0) { 750 goto done; 751 } 752 /* 753 * Validate the input parameters 754 */ 755 if (req->newptr != USER_ADDR_NULL) { 756 error = EPERM; 757 goto done; 758 } 759 if (req->oldptr == USER_ADDR_NULL) { 760 error = EINVAL; 761 goto done; 762 } 763 if (req->oldlen == 0) { 764 error = EINVAL; 765 goto done; 766 } 767 idx = name[0]; 768 frames_array_count = name[1]; 769 frame_data_offset = name[2]; 770 771 /* Make sure the passed buffer is large enough */ 772 if (frames_array_count * sizeof(struct ifnet_keepalive_offload_frame) > 773 req->oldlen) { 774 error = ENOMEM; 775 goto done; 776 } 777 778 ifnet_head_lock_shared(); 779 if (!IF_INDEX_IN_RANGE(idx)) { 780 ifnet_head_done(); 781 error = ENOENT; 782 goto done; 783 } 784 ifp = ifindex2ifnet[idx]; 785 ifnet_head_done(); 786 787 frames_array = (struct ifnet_keepalive_offload_frame *)kalloc_data( 788 frames_array_count * sizeof(struct ifnet_keepalive_offload_frame), 789 Z_WAITOK); 790 if (frames_array == NULL) { 791 error = ENOMEM; 792 goto done; 793 } 794 795 error = ifnet_get_keepalive_offload_frames(ifp, frames_array, 796 frames_array_count, frame_data_offset, &used_frames_count); 797 if (error != 0) { 798 DLIL_PRINTF("%s: ifnet_get_keepalive_offload_frames error %d\n", 799 __func__, error); 800 goto done; 801 } 802 803 for (i = 0; i < used_frames_count; i++) { 804 error = SYSCTL_OUT(req, frames_array + i, 805 sizeof(struct ifnet_keepalive_offload_frame)); 806 if (error != 0) { 807 goto done; 808 } 809 } 810 done: 811 if (frames_array != NULL) { 812 kfree_data(frames_array, frames_array_count * 813 sizeof(struct ifnet_keepalive_offload_frame)); 814 } 815 return error; 816 } 817 818 static int 819 if_attach_nx_sysctl SYSCTL_HANDLER_ARGS 820 { 821 #pragma unused(oidp, arg1, arg2) 822 unsigned int new_value; 823 int changed; 824 int error = sysctl_io_number(req, if_attach_nx, sizeof(if_attach_nx), 825 &new_value, &changed); 826 if (error) { 827 return error; 828 } 829 if (changed) { 830 if ((new_value & IF_ATTACH_NX_FSW_TRANSPORT_NETAGENT) != 831 (if_attach_nx & IF_ATTACH_NX_FSW_TRANSPORT_NETAGENT)) { 832 return ENOTSUP; 833 } 834 if_attach_nx = new_value; 835 } 836 return 0; 837 } 838 839 #endif /* DEVELOPMENT || DEBUG */ 840 841 static int 842 if_enable_fsw_transport_netagent_sysctl SYSCTL_HANDLER_ARGS 843 { 844 #pragma unused(oidp, arg1, arg2) 845 unsigned int new_value; 846 int changed; 847 int error; 848 849 error = sysctl_io_number(req, if_enable_fsw_transport_netagent, 850 sizeof(if_enable_fsw_transport_netagent), 851 &new_value, &changed); 852 if (error == 0 && changed != 0) { 853 if (new_value != 0 && new_value != 1) { 854 /* only allow 0 or 1 */ 855 error = EINVAL; 856 } else if ((if_attach_nx & IF_ATTACH_NX_FSW_TRANSPORT_NETAGENT) != 0) { 857 /* netagent can be enabled/disabled */ 858 if_enable_fsw_transport_netagent = new_value; 859 if (new_value == 0) { 860 kern_nexus_deregister_netagents(); 861 } else { 862 kern_nexus_register_netagents(); 863 } 864 } else { 865 /* netagent can't be enabled */ 866 error = ENOTSUP; 867 } 868 } 869 return error; 870 } 871