1/* 2 * Copyright (c) 1998-2008 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * The contents of this file constitute Original Code as defined in and 7 * are subject to the Apple Public Source License Version 1.1 (the 8 * "License"). You may not use this file except in compliance with the 9 * License. Please obtain a copy of the License at 10 * http://www.apple.com/publicsource and read it before using this file. 11 * 12 * This Original Code and all software distributed under the License are 13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER 14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the 17 * License for the specific language governing rights and limitations 18 * under the License. 19 * 20 * @APPLE_LICENSE_HEADER_END@ 21 */ 22/* 23 * IONetworkInterface.cpp 24 * 25 * HISTORY 26 * 8-Jan-1999 Joe Liu (jliu) created. 27 * 28 */ 29 30extern "C" { 31#include <sys/param.h> 32#include <sys/systm.h> 33#include <sys/mbuf.h> 34#include <sys/socket.h> 35#include <sys/sockio.h> 36#include <net/bpf.h> 37#include <net/if.h> 38#include <net/if_media.h> 39#include <net/dlil.h> 40#include <net/if_dl.h> 41#include <net/kpi_interface.h> 42#include <sys/kern_event.h> 43 44#define _IP_VHL 45 46#include <netinet/ip.h> 47#include <netinet/ip_icmp.h> 48} 49 50#include <IOKit/assert.h> 51#include <IOKit/IOLib.h> 52#include <IOKit/IOBSD.h> 53#include <IOKit/network/IONetworkInterface.h> 54#include <IOKit/network/IONetworkController.h> 55#include "IONetworkUserClient.h" 56#include "IONetworkStack.h" 57#include "IONetworkTypesPrivate.h" 58#include "IONetworkControllerPrivate.h" 59#include "IONetworkDebug.h" 60#include "IOMbufQueue.h" 61 62#include <TargetConditionals.h> 63 64//------------------------------------------------------------------------------ 65 66#define super IOService 67 68OSDefineMetaClassAndAbstractStructors( IONetworkInterface, IOService ) 69OSMetaClassDefineReservedUsed( IONetworkInterface, 5); 70OSMetaClassDefineReservedUsed( IONetworkInterface, 6); 71OSMetaClassDefineReservedUsed( IONetworkInterface, 7); 72OSMetaClassDefineReservedUsed( IONetworkInterface, 8); 73OSMetaClassDefineReservedUsed( IONetworkInterface, 9); 74OSMetaClassDefineReservedUsed( IONetworkInterface, 10); 75OSMetaClassDefineReservedUnused( IONetworkInterface, 11); 76OSMetaClassDefineReservedUnused( IONetworkInterface, 12); 77OSMetaClassDefineReservedUnused( IONetworkInterface, 13); 78OSMetaClassDefineReservedUnused( IONetworkInterface, 14); 79OSMetaClassDefineReservedUnused( IONetworkInterface, 15); 80 81//------------------------------------------------------------------------------ 82// Macros 83 84#define IFNET_TO_THIS(x) ((IONetworkInterface *) ifnet_softc(ifp)) 85 86#define WAITING_FOR_DETACH(n) ((n)->_clientVar[1]) 87 88#define _unit _reserved->unit 89#define _type _reserved->type 90#define _mtu _reserved->mtu 91#define _flags _reserved->flags 92#define _eflags _reserved->eflags 93#define _addrlen _reserved->addrlen 94#define _hdrlen _reserved->hdrlen 95#define _loggingLevel _reserved->loggingLevel 96#define _outputQueueModel _reserved->outputQueueModel 97#define _inputDeltas _reserved->inputDeltas 98#define _driverStats _reserved->driverStats 99#define _lastDriverStats _reserved->lastDriverStats 100#define _publicLock _reserved->publicLock 101#define _remote_NMI_pattern _reserved->remote_NMI_pattern 102#define _remote_NMI_len _reserved->remote_NMI_len 103#define _controller _reserved->controller 104#define _configFlags _reserved->configFlags 105#define _txRingSize _reserved->txRingSize 106#define _txPullOptions _reserved->txPullOptions 107#define _txQueueSize _reserved->txQueueSize 108#define _txSchedulingModel _reserved->txSchedulingModel 109#define _txThreadState _reserved->txThreadState 110#define _txThreadFlags _reserved->txThreadFlags 111#define _txThreadSignal _reserved->txThreadSignal 112#define _txThreadSignalLast _reserved->txThreadSignalLast 113#define _txStartThread _reserved->txStartThread 114#define _txStartAction _reserved->txStartAction 115#define _txWorkLoop _reserved->txWorkLoop 116#define _rxRingSize _reserved->rxRingSize 117#define _rxPollOptions _reserved->rxPollOptions 118#define _rxPollModel _reserved->rxPollModel 119#define _rxPollAction _reserved->rxPollAction 120#define _rxCtlAction _reserved->rxCtlAction 121#define _rxPollEmpty _reserved->rxPollEmpty 122#define _rxPollTotal _reserved->rxPollTotal 123#define _peqHandler _reserved->peqHandler 124#define _peqTarget _reserved->peqTarget 125#define _peqRefcon _reserved->peqRefcon 126#define _subType _reserved->subType 127 128#define kRemoteNMI "remote_nmi" 129#define REMOTE_NMI_PATTERN_LEN 32 130 131// _txThreadState 132#define kTxThreadStateInit 0x00000001 // initial state 133#define kTxThreadStateStop 0x00000100 // temporarily disable 134#define kTxThreadStateDetach 0x00000200 // permanently disable 135#define kTxThreadStateHalted 0x00000800 // stop confirmation 136#define kTxThreadStatePurge 0x00001000 // purge new packets 137 138// _txThreadFlags 139#define kTxThreadWakeupEnable 0x00000001 // enable ifnet_start call 140#define kTxThreadWakeupSignal 0x00000002 // driver signaled 141#define kTxThreadWakeupMask 0x00000003 // wakeup bits 142 143enum { 144 kConfigFrozen = 0x01, 145 kConfigTxPull = 0x02, 146 kConfigRxPoll = 0x04, 147 kConfigDataRates = 0x08, 148 kConfigPreEnqueue = 0x10 149}; 150 151//------------------------------------------------------------------------------ 152// Initialize an IONetworkInterface instance. 153// 154// Returns true if initialized successfully, false otherwise. 155 156bool IONetworkInterface::init( IONetworkController * controller ) 157{ 158 IONetworkData * nd; 159#if TARGET_OS_EMBEDDED 160 OSString * networkType; 161#endif 162 163 // Propagate the init() call to our superclass. 164 165 if ( super::init() == false ) 166 goto fail; 167 168 // A non-null value at this point means the subclass is pre-kpi 169 // and allocated its ifnet/arpcom itself. 170 // We can't work with such a sublcass but at least we can fail gracefully. 171 172 if (getIfnet()) 173 { 174 IOLog("\33[00m\33[31m%s: IONetworkingFamily interface KPIs do not support IONetworkInterface subclasses that use ifnets\n\33[00m", getName()); 175 goto fail; 176 } 177 178 // The controller object provided must be valid. 179 180 if ( OSDynamicCast(IONetworkController, controller) == 0 ) 181 goto fail; 182 183 _driver = controller; 184 _driver->retain(); 185 186 // Allocate memory for the ExpansionData structure. 187 188 _reserved = IONew( ExpansionData, 1 ); 189 if ( _reserved == 0 ) 190 goto fail; 191 192 // Initialize the fields in the ExpansionData structure. 193 194 bzero(_reserved, sizeof(ExpansionData)); 195 196 _privateLock = IOLockAlloc(); 197 if ( _privateLock == 0) 198 goto fail; 199 200 _publicLock = IORecursiveLockAlloc(); 201 if ( _publicLock == 0 ) 202 goto fail; 203 204 _controller = controller; 205 _rxPollModel = IFNET_MODEL_INPUT_POLL_OFF; 206 207 _inputPushQueue = IONew(IOMbufQueue, 1); 208 bzero(_inputPushQueue, sizeof(*_inputPushQueue)); 209 210 // Set initial queue state before attaching to network stack. 211 _txThreadState = kTxThreadStateInit | kTxThreadStateHalted; 212 213 // Create an OSNumber to store interface state bits. 214 215 _stateBits = OSNumber::withNumber((UInt64) 0, 32); 216 if ( _stateBits == 0 ) 217 goto fail; 218 setProperty( kIOInterfaceState, _stateBits ); 219 220 // Create an OSSet to store client objects. Initial capacity 221 // (which can grow) is set at 2 clients. 222 223 _clientSet = OSSet::withCapacity(2); 224 if ( _clientSet == 0 ) 225 goto fail; 226 227 // Dictionary to store network data. 228 229 if ( (_dataDict = OSDictionary::withCapacity(5)) == 0 ) 230 goto fail; 231 232 nd = IONetworkData::withExternalBuffer( 233 kIONetworkStatsKey, 234 sizeof(IONetworkStats), 235 &_driverStats); 236 if ( nd ) 237 { 238 addNetworkData(nd); 239 nd->release(); 240 } 241 242 // Register default output handler (not used for pull transmit model) 243 244 if (!registerOutputHandler(controller, controller->getOutputHandler())) 245 goto fail; 246 247 // Set the kIOInterfaceNamePrefix and kIOPrimaryInterface properties. 248 // These may be used by an user space agent as hints when assigning a 249 // BSD name for the interface. 250 251 setProperty( kIOInterfaceNamePrefix, getNamePrefix() ); 252 253#if TARGET_OS_EMBEDDED 254 networkType = OSDynamicCast(OSString, controller->getProperty( "IONetworkRootType" )); 255 if (networkType) 256 setProperty( "IONetworkRootType", networkType ); 257#endif /* TARGET_OS_EMBEDDED */ 258 259 if (IOService *provider = controller->getProvider()) 260 { 261 bool gotLocation = false; 262 OSData * locationAsData; 263 OSData * locationAsCstr; 264 OSString * locationAsString; 265 266 setProperty(kIOBuiltin, (bool)(provider->getProperty("built-in"))); 267 268 if ((locationAsData = OSDynamicCast(OSData, provider->getProperty("location")))) 269 { 270 // the data may be null terminated...but to be on the safe side, 271 // let's assume it's not, and add a null... 272 // create a copy that we can convert to C string 273 if ((locationAsCstr = OSData::withData(locationAsData))) 274 { 275 locationAsCstr->appendByte(0, 1); 276 // now create the OSString 277 if ((locationAsString = OSString::withCString( 278 (const char *) locationAsCstr->getBytesNoCopy()))) 279 { 280 gotLocation = true; 281 setProperty(kIOLocation, locationAsString); 282 locationAsString->release(); //setProperty took a ref 283 } 284 locationAsCstr->release(); 285 } 286 } 287 if (!gotLocation) 288 setProperty(kIOLocation, ""); 289 } 290 291 DLOG("IONetworkInterface::init(%p, %s)\n", this, controller->getName()); 292 return true; 293 294fail: 295 LOG("IONetworkInterface::init(%p, %s) failed\n", this, controller->getName()); 296 return false; 297} 298 299//------------------------------------------------------------------------------ 300// Destroy the interface. Release all allocated resources. 301 302void IONetworkInterface::free( void ) 303{ 304 DLOG("IONetworkInterface::free(%p)\n", this); 305 306 if (_driver) 307 { 308 _driver->release(); 309 _driver = 0; 310 } 311 312 if ( _clientSet ) 313 { 314 // Should not have any clients. 315 assert(_clientSet->getCount() == 0); 316 _clientSet->release(); 317 _clientSet = 0; 318 } 319 320 if ( _dataDict ) 321 { 322 _dataDict->release(); 323 _dataDict = 0; 324 } 325 326 if ( _stateBits ) 327 { 328 _stateBits->release(); 329 _stateBits = 0; 330 } 331 332 if ( _inputPushQueue ) 333 { 334 clearInputQueue(); 335 IODelete(_inputPushQueue, IOMbufQueue, 1); 336 _inputPushQueue = 0; 337 } 338 339 if ( _privateLock ) 340 { 341 IOLockFree(_privateLock); 342 _privateLock = 0; 343 } 344 345 if (_backingIfnet) 346 { 347 ifnet_release(_backingIfnet); 348 _backingIfnet = 0; 349 } 350 351 // Free resources referenced through fields in the ExpansionData 352 // structure, and also the structure itself. 353 354 if ( _reserved ) 355 { 356 if ( _publicLock ) 357 { 358 IORecursiveLockFree(_publicLock); 359 _publicLock = 0; 360 } 361 362 if (_remote_NMI_pattern) { 363 IOFree(_remote_NMI_pattern, _remote_NMI_len); 364 } 365 366 if (_txWorkLoop) 367 _txWorkLoop->release(); 368 369 memset(_reserved, 0, sizeof(ExpansionData)); 370 IODelete(_reserved, ExpansionData, 1); 371 _reserved = 0; 372 } 373 374 super::free(); 375} 376 377//------------------------------------------------------------------------------ 378// Returns true if the receiver of this method is the system's primary 379// network interface. 380 381bool IONetworkInterface::isPrimaryInterface() const 382{ 383 IOService * provider = _driver; 384 bool isPrimary = false; 385 386 if ( provider ) provider = provider->getProvider(); 387 388 // Look for the built-in property in the ethernet entry. 389 390 if ( provider && provider->getProperty("built-in") && getUnitNumber() == 0) 391 { 392 isPrimary = true; 393 } 394 395 return isPrimary; 396} 397 398//------------------------------------------------------------------------------ 399 400IONetworkController * IONetworkInterface::getController( void ) const 401{ 402 return _controller; 403} 404 405//------------------------------------------------------------------------------ 406// Get the value that should be set in the hwassist field in the ifnet 407// structure. Currently, this field is solely used for advertising the 408// hardware checksumming support. 409 410static UInt32 getIfnetHardwareAssistValue( 411 IONetworkController * driver ) 412{ 413 UInt32 input; 414 UInt32 output; 415 UInt32 hwassist = 0; 416 UInt32 driverFeatures = driver->getFeatures(); 417 418 do { 419 if ( driver->getChecksumSupport( 420 &input, 421 IONetworkController::kChecksumFamilyTCPIP, 422 false ) != kIOReturnSuccess ) break; 423 424 if ( driver->getChecksumSupport( 425 &output, 426 IONetworkController::kChecksumFamilyTCPIP, 427 true ) != kIOReturnSuccess ) break; 428 429 if ( input & output & IONetworkController::kChecksumIP ) 430 { 431 hwassist |= IFNET_CSUM_IP; 432 } 433 434 if ( ( input & ( IONetworkController::kChecksumTCP | 435 IONetworkController::kChecksumTCPNoPseudoHeader ) ) 436 && ( output & ( IONetworkController::kChecksumTCP ) ) ) 437 { 438 hwassist |= IFNET_CSUM_TCP; 439 } 440 441 if ( ( input & ( IONetworkController::kChecksumUDP | 442 IONetworkController::kChecksumUDPNoPseudoHeader ) ) 443 && ( output & ( IONetworkController::kChecksumUDP ) ) ) 444 { 445 hwassist |= IFNET_CSUM_UDP; 446 } 447 448 if ( input & output & IONetworkController::kChecksumTCPSum16 ) 449 { 450 hwassist |= ( IFNET_CSUM_SUM16 | IFNET_CSUM_TCP | IFNET_CSUM_UDP ); 451 } 452 453 if ( input & output & IONetworkController::kChecksumTCPIPv6 ) 454 { 455 hwassist |= IFNET_CSUM_TCPIPV6; 456 } 457 if ( input & output & IONetworkController::kChecksumUDPIPv6 ) 458 { 459 hwassist |= IFNET_CSUM_UDPIPV6; 460 } 461 } 462 while ( false ); 463 464 if( driverFeatures & kIONetworkFeatureHardwareVlan) 465 hwassist |= IFNET_VLAN_TAGGING; 466 467 if( driverFeatures & kIONetworkFeatureSoftwareVlan) 468 hwassist |= IFNET_VLAN_MTU; 469 470 if( driverFeatures & kIONetworkFeatureMultiPages) 471 hwassist |= IFNET_MULTIPAGES; 472 473 if( driverFeatures & kIONetworkFeatureTSOIPv4) 474 hwassist |= IFNET_TSO_IPV4; 475 476 if( driverFeatures & kIONetworkFeatureTSOIPv6) 477 hwassist |= IFNET_TSO_IPV6; 478 479 if (driverFeatures & kIONetworkFeatureTransmitCompletionStatus) 480 hwassist |= IFNET_TX_STATUS; 481 482 return hwassist; 483} 484 485//------------------------------------------------------------------------------ 486// Initialize the ifnet structure. 487 488bool IONetworkInterface::initIfnet( struct ifnet * ifp ) 489{ 490 return false; // deprecated - replaced by initIfnetParams() 491} 492 493OSMetaClassDefineReservedUsed(IONetworkInterface, 4); 494 495bool IONetworkInterface::initIfnetParams( struct ifnet_init_params *params ) 496{ 497 // Register our 'shim' functions. These function pointers 498 // points to static member functions inside this class. 499 params->name = (char *) getNamePrefix(); 500 params->type = _type; 501 params->unit = _unit; 502 params->output = if_output; 503 params->ioctl = if_ioctl; 504 params->set_bpf_tap = if_set_bpf_tap; 505 params->detach = if_detach; 506 params->softc = this; 507 508 return true; 509} 510 511//------------------------------------------------------------------------------ 512// Take/release the interface lock. 513 514void IONetworkInterface::lock() 515{ 516 IORecursiveLockLock(_publicLock); 517} 518 519void IONetworkInterface::unlock() 520{ 521 IORecursiveLockUnlock(_publicLock); 522} 523 524//------------------------------------------------------------------------------ 525// Inspect the controller after it has been opened. 526 527bool IONetworkInterface::controllerDidOpen( IONetworkController * controller ) 528{ 529 return true; // by default, always accept the controller open. 530} 531 532//------------------------------------------------------------------------------ 533// Perform cleanup before the controller is closed. 534 535void IONetworkInterface::controllerWillClose( IONetworkController * controller ) 536{ 537} 538 539//------------------------------------------------------------------------------ 540// Handle a client open on the interface (IONetworkStack or user client) 541 542bool IONetworkInterface::handleOpen( IOService * client, 543 IOOptionBits options, 544 void * argument ) 545{ 546 bool accept = false; 547 bool controllerOpen = false; 548 549 do { 550 // Was this object already registered as our client? 551 552 if ( _clientSet->containsObject(client) ) 553 { 554 DLOG("%s: rejected open from existing client %s\n", 555 getName(), client->getName()); 556 accept = true; 557 break; 558 } 559 560 // If the interface has not received a client open, which also 561 // implies that the interface has not yet opened the controller, 562 // then open the controller upon receiving the first open from 563 // a client. If the controller open fails, the client open will 564 // be rejected. 565 566 if (( getInterfaceState() & kIONetworkInterfaceOpenedState ) == 0) 567 { 568 if (!_driver || 569 ((controllerOpen = _driver->open(this)) == false) || 570 (controllerDidOpen(_driver) == false)) 571 break; 572 } 573 574 // Allow subclasses to intercept. 575 576 if ( handleClientOpen(client, options, argument) == false ) 577 break; 578 579 // Add the new client object to our client set. 580 581 if ( _clientSet->setObject(client) == false ) 582 { 583 handleClientClose(client, 0); 584 break; 585 } 586 587 accept = true; 588 } 589 while (false); 590 591 // If provider was opened above, but an error has caused us to refuse 592 // the client open, then close our provider. 593 594 if ( controllerOpen ) 595 { 596 if (accept) 597 { 598 setInterfaceState( kIONetworkInterfaceOpenedState ); 599 _driver->registerInterestedDriver( this ); 600 } 601 else 602 { 603 controllerWillClose(_driver); 604 _driver->close(this); 605 } 606 } 607 608 return accept; 609} 610 611//------------------------------------------------------------------------------ 612// Handle a client close on the interface. 613 614void IONetworkInterface::handleClose( IOService * client, IOOptionBits options ) 615{ 616 if ( _clientSet->containsObject(client) ) 617 { 618 // Call handleClientClose() for subclass to handle the client close. 619 620 handleClientClose( client, options ); 621 622 // Close our provider on last client close. 623 624 if ( _clientSet->getCount() == 1 ) 625 { 626 _driver->deRegisterInterestedDriver( this ); 627 controllerWillClose( _driver ); 628 _driver->close( this ); 629 setInterfaceState( 0, kIONetworkInterfaceOpenedState ); 630 631 // Closed by IONetworkStack after detaching interface, 632 // drop the driver retain from init(). 633 634 if (!isRegistered()) 635 { 636 _driver->release(); 637 _driver = 0; 638 } 639 } 640 _clientSet->removeObject(client); 641 } 642} 643 644//------------------------------------------------------------------------------ 645// Query whether a client has an open on the interface. 646 647bool IONetworkInterface::handleIsOpen( const IOService * client ) const 648{ 649 if (client) 650 return _clientSet->containsObject(client); 651 else 652 return (_clientSet->getCount() > 0); 653} 654 655//------------------------------------------------------------------------------ 656// Handle a client open on the interface. 657 658bool IONetworkInterface::handleClientOpen(IOService * client, 659 IOOptionBits options, 660 void * argument) 661{ 662 return true; 663} 664 665//------------------------------------------------------------------------------ 666// Handle a client close on the interface. 667 668void IONetworkInterface::handleClientClose(IOService * client, 669 IOOptionBits options) 670{ 671} 672 673//------------------------------------------------------------------------------ 674// Register the output packet handler. 675 676bool IONetworkInterface::registerOutputHandler(OSObject * target, 677 IOOutputAction action) 678{ 679 IOLockLock(_privateLock); 680 681 // Sanity check the arguments. 682 683 if ( (getInterfaceState() & kIONetworkInterfaceOpenedState) || 684 !target || !action ) 685 { 686 IOLockUnlock(_privateLock); 687 return false; 688 } 689 690 _outTarget = target; 691 _outAction = action; 692 693 IOLockUnlock(_privateLock); 694 695 return true; 696} 697 698//------------------------------------------------------------------------------ 699// Feed packets to the input/output BPF packet filter taps. 700 701OSMetaClassDefineReservedUsed(IONetworkInterface, 2); 702 703void IONetworkInterface::feedPacketInputTap(mbuf_t m) 704{ 705 // PR3662433 we're not protected from this getting changed out from under us 706 // so use a local ptr and double check for NULL to avoid the race 707 bpf_packet_func inFilter = _inputFilterFunc; 708 if (inFilter) 709 inFilter(_backingIfnet, m); 710} 711 712OSMetaClassDefineReservedUsed(IONetworkInterface, 3); 713 714void IONetworkInterface::feedPacketOutputTap(mbuf_t m) 715{ 716 // see comment in feedPacketInputTap 717 bpf_packet_func outFilter = _outputFilterFunc; 718 if (outFilter) 719 outFilter(_backingIfnet, m); 720} 721 722//------------------------------------------------------------------------------ 723 724#define ABS(a) ((a) < 0 ? -(a) : (a)) 725 726void IONetworkInterface::pushInputQueue( IOMbufQueue * queue ) 727{ 728 uint32_t temp; 729 int delta; 730 731 _inputDeltas.packets_in = queue->count; 732 _inputDeltas.bytes_in = queue->bytes; 733 734 // Report our packet count rather than rely on the driver stats. 735 // ifnet_input_extended() requires the count to be accurate. 736 737 temp = _driverStats.inputErrors; 738 delta = temp - _lastDriverStats.inputErrors; 739 _inputDeltas.errors_in = ABS(delta); 740 _lastDriverStats.inputErrors = temp; 741 742 temp = _driverStats.collisions; 743 delta = temp - _lastDriverStats.collisions; 744 _inputDeltas.collisions = ABS(delta); 745 _lastDriverStats.collisions = temp; 746 747 ifnet_input_extended(_backingIfnet, queue->head, queue->tail, &_inputDeltas); 748 IOMbufQueueInit(queue); 749} 750 751void IONetworkInterface::pushInputPacket( mbuf_t packet, uint32_t length ) 752{ 753 uint32_t temp; 754 int delta; 755 756 _inputDeltas.packets_in = 1; 757 _inputDeltas.bytes_in = length; 758 759 // Report our packet count rather than rely on the driver stats. 760 // ifnet_input_extended() requires the count to be accurate. 761 762 temp = _driverStats.inputErrors; 763 delta = temp - _lastDriverStats.inputErrors; 764 _inputDeltas.errors_in = ABS(delta); 765 _lastDriverStats.inputErrors = temp; 766 767 temp = _driverStats.collisions; 768 delta = temp - _lastDriverStats.collisions; 769 _inputDeltas.collisions = ABS(delta); 770 _lastDriverStats.collisions = temp; 771 772 ifnet_input_extended(_backingIfnet, packet, packet, &_inputDeltas); 773} 774 775UInt32 IONetworkInterface::flushInputQueue( void ) 776{ 777 UInt32 count = _inputPushQueue->count; 778 779 if (count) 780 { 781 //DLOG("push pkt cnt %u\n", count); 782 pushInputQueue(_inputPushQueue); 783 } 784 785 return count; 786} 787 788UInt32 IONetworkInterface::clearInputQueue( void ) 789{ 790 UInt32 count = _inputPushQueue->count; 791 792 if (count) 793 mbuf_freem_list(_inputPushQueue->head); 794 795 IOMbufQueueInit(_inputPushQueue); 796 return count; 797} 798 799inline static const char *get_icmp_data(mbuf_t *pkt, int hdrlen, int datalen) 800{ 801 struct ip *ip; 802 struct icmp *icmp; 803 int hlen, icmplen; 804 805 icmplen = sizeof(*icmp) + sizeof(struct timeval); 806 807 /* make sure hdrlen is sane with respect to mbuf */ 808 if (mbuf_len(*pkt) < (sizeof(*ip) + hdrlen)) 809 goto error; 810 811 /* only work for IPv4 packets */ 812 ip = (struct ip *) ((char *) mbuf_data(*pkt) + hdrlen); 813 if (IP_VHL_V(ip->ip_vhl) != IPVERSION) 814 goto error; 815 816 hlen = IP_VHL_HL(ip->ip_vhl) << 2; 817 818 /* make sure header and data is contiguous */ 819 if (mbuf_pullup(pkt, hlen + icmplen) != 0) 820 goto error; 821 822 /* refresh the pointer and hlen in case buffer was shifted */ 823 ip = (struct ip *) ((char *) mbuf_data(*pkt) + hdrlen); 824 hlen = IP_VHL_HL(ip->ip_vhl) << 2; 825 826 if (ip->ip_p != IPPROTO_ICMP) 827 goto error; 828 829 if (ip->ip_len < (icmplen + datalen)) 830 goto error; 831 832 icmp = (struct icmp *) (((char *) mbuf_data(*pkt) + hdrlen) + hlen); 833 if (icmp->icmp_type != ICMP_ECHO) 834 goto error; 835 836 return (const char *) (((char *) mbuf_data(*pkt) + hdrlen) + icmplen); 837 838error: 839 return NULL; 840} 841 842UInt32 IONetworkInterface::inputPacket( mbuf_t packet, 843 UInt32 length, 844 IOOptionBits options, 845 void * param ) 846{ 847 const UInt32 hdrlen = _hdrlen; 848 UInt32 count; 849 void * mdata; 850 851 assert(packet); 852 assert(_backingIfnet); 853 if (!packet || !_backingIfnet) 854 return 0; 855 856 assert((mbuf_flags(packet) & MBUF_PKTHDR)); 857 assert((mbuf_nextpkt(packet) == 0)); 858 859 mbuf_pkthdr_setrcvif(packet, _backingIfnet); 860 861 if (length) 862 { 863 // Driver wants interface to set the mbuf length. 864 if (mbuf_next(packet) == 0) 865 { 866 mbuf_pkthdr_setlen(packet, length); 867 mbuf_setlen(packet, length); 868 } 869 else 870 { 871 // rare case of single packet but multiple mbufs. 872 mbuf_t m = packet; 873 uint32_t remain = length; 874 mbuf_pkthdr_setlen(packet, remain); 875 do { 876 if (remain < (UInt32) mbuf_len(m)) 877 mbuf_setlen(m, remain); 878 remain -= mbuf_len(m); 879 } while ((m = mbuf_next(m))); 880 assert(remain == 0); 881 } 882 } 883 else 884 { 885 length = mbuf_pkthdr_len(packet); 886 } 887 888 // check for special debugger packet 889 if (_remote_NMI_len) { 890 const char *data = get_icmp_data(&packet, hdrlen, _remote_NMI_len); 891 892 if (data && (memcmp(data, _remote_NMI_pattern, _remote_NMI_len) == 0)) { 893 IOKernelDebugger::signalDebugger(); 894 } 895 } 896 897 // input BPF tap 898 if (_inputFilterFunc) 899 feedPacketInputTap(packet); 900 901 // frame header at start of mbuf data 902 mdata = mbuf_data(packet); 903 mbuf_pkthdr_setheader(packet, mdata); 904 905 // packet length does not include the frame header 906 mbuf_pkthdr_setlen(packet, length - hdrlen); 907 908 // adjust the mbuf data and length to skip over the frame header 909 mbuf_setdata(packet, (char *)mdata + hdrlen, mbuf_len(packet) - hdrlen); 910 911 if ( options & kInputOptionQueuePacket ) 912 { 913 IOMbufQueueTailAdd(_inputPushQueue, packet, length); 914 count = 0; 915 } 916 else 917 { 918 if (!IOMbufQueueIsEmpty(_inputPushQueue)) 919 { 920 IOMbufQueueTailAdd(_inputPushQueue, packet, length); 921 count = _inputPushQueue->count; 922 pushInputQueue(_inputPushQueue); 923 } 924 else 925 { 926 pushInputPacket(packet, length); 927 count = 1; 928 } 929 } 930 931 return count; 932} 933 934//------------------------------------------------------------------------------ 935// Deliver an event to the network layer. 936 937bool IONetworkInterface::inputEvent(UInt32 type, void * data) 938{ 939 bool success = true; 940 941 struct { 942 kern_event_msg header; 943 uint32_t unit; 944 char if_name[IFNAMSIZ]; 945 } event; 946 947 const IONetworkLinkEventData * linkData; 948 949 switch (type) 950 { 951 // Deliver an IOKit defined event. 952 953 case kIONetworkEventTypeLinkUp: 954 case kIONetworkEventTypeLinkDown: 955 case kIONetworkEventTypeLinkSpeedChange: 956 // Send an event only if DLIL has a reference to this 957 // interface. 958 linkData = (const IONetworkLinkEventData *) data; 959 if (!_backingIfnet || !linkData) 960 break; 961 962 // Use link speed to report bandwidth for legacy drivers 963 if ((_configFlags & kConfigDataRates) == 0) 964 { 965 if_bandwidths_t bw; 966 967 bw.max_bw = linkData->linkSpeed; 968 bw.eff_bw = linkData->linkSpeed; 969 ifnet_set_bandwidths(_backingIfnet, &bw, &bw); 970 } 971 972 if ((type == kIONetworkEventTypeLinkUp) || 973 (type == kIONetworkEventTypeLinkDown)) 974 { 975 bzero(&event, sizeof(event)); 976 event.header.total_size = sizeof(event); 977 event.header.vendor_code = KEV_VENDOR_APPLE; 978 event.header.kev_class = KEV_NETWORK_CLASS; 979 event.header.kev_subclass = KEV_DL_SUBCLASS; 980 event.header.event_code = (type == kIONetworkEventTypeLinkUp) ? 981 KEV_DL_LINK_ON : KEV_DL_LINK_OFF; 982 event.header.event_data[0] = ifnet_family(_backingIfnet); 983 event.unit = ifnet_unit(_backingIfnet); 984 strncpy(&event.if_name[0], ifnet_name(_backingIfnet), IFNAMSIZ); 985 986 ifnet_event(_backingIfnet, &event.header); 987 } 988 break; 989 990 // Deliver a raw kernel event to DLIL. 991 // The data argument must point to a kern_event_msg structure. 992 993 case kIONetworkEventTypeDLIL: 994 ifnet_event(_backingIfnet, (struct kern_event_msg *) data); 995 break; 996 997 case kIONetworkEventWakeOnLANSupportChanged: 998 break; 999 1000 default: 1001 IOLog("IONetworkInterface: unknown event type %x\n", (uint32_t) type); 1002 success = false; 1003 break; 1004 } 1005 1006 return success; 1007} 1008 1009//------------------------------------------------------------------------------ 1010// SIOCSIFMTU (set interface MTU) ioctl handler. 1011 1012SInt32 IONetworkInterface::syncSIOCSIFMTU(IONetworkController * ctr, 1013 struct ifreq * ifr) 1014{ 1015 SInt32 error; 1016 UInt32 newMTU = ifr->ifr_mtu; 1017 1018 // If change is not necessary, return success without getting the 1019 // controller involved. 1020 1021 if ( getMaxTransferUnit() == newMTU ) 1022 return 0; 1023 1024 // Request the controller to switch MTU size. 1025 1026 error = errnoFromReturn( ctr->setMaxPacketSize(newMTU) ); 1027 1028 if ( error == 0 ) 1029 { 1030 // Controller reports success. Update the interface MTU size 1031 // property. 1032 1033 setMaxTransferUnit(newMTU); 1034 } 1035 1036 return error; 1037} 1038 1039//------------------------------------------------------------------------------ 1040// SIOCSIFMEDIA (SET interface media) ioctl handler. 1041 1042SInt32 IONetworkInterface::syncSIOCSIFMEDIA(IONetworkController * ctr, 1043 struct ifreq * ifr) 1044{ 1045 OSDictionary * mediumDict; 1046 IONetworkMedium * medium; 1047 SInt32 error; 1048 1049 mediumDict = ctr->copyMediumDictionary(); // creates a copy 1050 if ( mediumDict == 0 ) 1051 { 1052 // unable to allocate memory, or no medium dictionary. 1053 return EOPNOTSUPP; 1054 } 1055 1056 do { 1057 // Look for an exact match on the media type. 1058 1059 medium = IONetworkMedium::getMediumWithType( 1060 mediumDict, 1061 ifr->ifr_media ); 1062 if ( medium ) break; 1063 1064 // Try a partial match. ifconfig tool sets the media type and media 1065 // options separately. When media options are changed, the options 1066 // bits are set or cleared based on the current media selection. 1067 1068 OSSymbol * selMediumName = (OSSymbol *) 1069 ctr->copyProperty( kIOSelectedMedium ); 1070 if ( selMediumName ) 1071 { 1072 UInt32 modMediumBits; 1073 IONetworkMedium * selMedium = (IONetworkMedium *) 1074 mediumDict->getObject( selMediumName ); 1075 1076 if ( selMedium && 1077 (modMediumBits = selMedium->getType() ^ ifr->ifr_media) ) 1078 { 1079 medium = IONetworkMedium::getMediumWithType( 1080 mediumDict, 1081 ifr->ifr_media, 1082 ~( IFM_TMASK | IFM_NMASK | modMediumBits)); 1083 } 1084 1085 selMediumName->release(); 1086 } 1087 if ( medium ) break; 1088 1089 // Still no match, look for a medium that matches the network type 1090 // and sub-type. 1091 1092 medium = IONetworkMedium::getMediumWithType( 1093 mediumDict, 1094 ifr->ifr_media, 1095 ~( IFM_TMASK | IFM_NMASK )); 1096 } while ( false ); 1097 1098 // It may be possible for the controller to update the medium 1099 // dictionary and perhaps delete the medium entry that we have 1100 // selected from our copy of the stale dictionary. This is 1101 // harmless since IONetworkController will filter out invalid 1102 // selections before calling the driver. 1103 1104 if ( medium ) 1105 error = errnoFromReturn( 1106 ctr->selectMediumWithName(medium->getName()) ); 1107 else 1108 error = EINVAL; 1109 1110 mediumDict->release(); 1111 1112 return error; 1113} 1114 1115//------------------------------------------------------------------------------ 1116// SIOCGIFMEDIA (GET interface media) ioctl handler. 1117 1118SInt32 IONetworkInterface::syncSIOCGIFMEDIA(IONetworkController * ctr, 1119 struct ifreq * ifr, 1120 unsigned long cmd) 1121{ 1122 OSDictionary * mediumDict = 0; 1123 UInt mediumCount = 0; 1124 UInt maxCount; 1125 OSCollectionIterator * iter = 0; 1126 UInt32 * typeList; 1127 UInt typeListSize; 1128 OSSymbol * keyObject; 1129 SInt32 error = 0; 1130 struct ifmediareq * ifmr = (struct ifmediareq *) ifr; 1131 1132 if (ifmr->ifm_count < 0) 1133 return EINVAL; 1134 1135 do { 1136 mediumDict = ctr->copyMediumDictionary(); // creates a copy 1137 if (mediumDict == 0) 1138 { 1139 error = EOPNOTSUPP; 1140 break; // unable to allocate memory, or no medium dictionary. 1141 } 1142 1143 if ((mediumCount = mediumDict->getCount()) == 0) 1144 { 1145 error = EOPNOTSUPP; 1146 break; // no medium in the medium dictionary 1147 } 1148 1149 // Maximum number of medium types that the caller will accept. 1150 // 1151 maxCount = ifmr->ifm_count; 1152 if (maxCount == 0) 1153 break; // caller is only probing for support and media count. 1154 1155 if (maxCount > mediumCount) 1156 { 1157 maxCount = mediumCount; 1158 } 1159 else if (maxCount < mediumCount) 1160 { 1161 // user buffer is too small to hold all medium entries. 1162 error = E2BIG; 1163 1164 // Proceed with partial copy on E2BIG. This follows the 1165 // SIOCGIFMEDIA handling practice in bsd/net/if_media.c. 1166 // 1167 // break; 1168 } 1169 1170 // Create an iterator to loop through the medium entries in the 1171 // dictionary. 1172 // 1173 iter = OSCollectionIterator::withCollection(mediumDict); 1174 if (!iter) 1175 { 1176 error = ENOMEM; 1177 break; 1178 } 1179 1180 // Allocate memory for the copyout buffer. 1181 // 1182 typeListSize = maxCount * sizeof(UInt32); 1183 typeList = (UInt32 *) IOMalloc(typeListSize); 1184 if (!typeList) 1185 { 1186 error = ENOMEM; 1187 break; 1188 } 1189 bzero(typeList, typeListSize); 1190 1191 // Iterate through the medium dictionary and copy the type of 1192 // each medium entry to typeList[]. 1193 // 1194 mediumCount = 0; 1195 while ( (keyObject = (OSSymbol *) iter->getNextObject()) && 1196 (mediumCount < maxCount) ) 1197 { 1198 IONetworkMedium * medium = (IONetworkMedium *) 1199 mediumDict->getObject(keyObject); 1200 if (!medium) 1201 continue; // should not happen! 1202 1203 typeList[mediumCount++] = medium->getType(); 1204 } 1205 1206 if (mediumCount) 1207 { 1208 user_addr_t srcaddr; 1209 1210 // here's where the difference in ioctls needs to be accounted for. 1211 srcaddr = (cmd == SIOCGIFMEDIA64) ? 1212 ((struct ifmediareq64 *)ifmr)->ifmu_ulist : 1213 CAST_USER_ADDR_T(((struct ifmediareq32 *)ifmr)->ifmu_ulist); 1214 if (srcaddr != USER_ADDR_NULL) { 1215 error = copyout((caddr_t) typeList, srcaddr, typeListSize); 1216 } 1217 } 1218 1219 IOFree(typeList, typeListSize); 1220 } 1221 while (0); 1222 1223 ifmr->ifm_active = ifmr->ifm_current = IFM_NONE; 1224 ifmr->ifm_status = 0; 1225 ifmr->ifm_count = mediumCount; 1226 1227 // Get a copy of the controller's property table and read the 1228 // link status, current, and active medium. 1229 1230 OSDictionary * pTable = ctr->dictionaryWithProperties(); 1231 if (pTable) 1232 { 1233 OSNumber * linkStatus = (OSNumber *) 1234 pTable->getObject(kIOLinkStatus); 1235 if (linkStatus) 1236 ifmr->ifm_status = linkStatus->unsigned32BitValue(); 1237 1238 if (mediumDict) 1239 { 1240 IONetworkMedium * medium; 1241 OSSymbol * mediumName; 1242 1243 if ((mediumName = (OSSymbol *) pTable->getObject(kIOSelectedMedium)) 1244 && (medium = (IONetworkMedium *) 1245 mediumDict->getObject(mediumName))) 1246 { 1247 ifmr->ifm_current = medium->getType(); 1248 } 1249 1250 if ((mediumName = (OSSymbol *) pTable->getObject(kIOActiveMedium)) 1251 && (medium = (IONetworkMedium *) 1252 mediumDict->getObject(mediumName))) 1253 { 1254 ifmr->ifm_active = medium->getType(); 1255 } 1256 } 1257 pTable->release(); 1258 } 1259 1260 if (iter) 1261 iter->release(); 1262 1263 if (mediumDict) 1264 mediumDict->release(); 1265 1266 return error; 1267} 1268 1269//------------------------------------------------------------------------------ 1270// Handle ioctl commands sent to the network interface. 1271 1272SInt32 IONetworkInterface::performCommand(IONetworkController * ctr, 1273 unsigned long cmd, 1274 void * arg0, 1275 void * arg1) 1276{ 1277 struct ifreq * ifr = (struct ifreq *) arg1; 1278 SInt32 ret = EOPNOTSUPP; 1279 1280 if ( (ifr == 0) || (ctr == 0) ) 1281 return EINVAL; 1282 1283 switch ( cmd ) 1284 { 1285 // Get interface MTU. 1286 1287 case SIOCGIFMTU: 1288 ifr->ifr_mtu = getMaxTransferUnit(); 1289 ret = 0; // no error 1290 break; 1291 1292 // Get interface media type and status. 1293 1294 case SIOCGIFMEDIA32: 1295 case SIOCGIFMEDIA64: 1296 ret = syncSIOCGIFMEDIA(ctr, ifr, cmd); 1297 break; 1298 1299 case SIOCSIFMTU: 1300 case SIOCSIFMEDIA: 1301 case SIOCSIFLLADDR: 1302 ret = (int) ctr->executeCommand( 1303 this, /* client */ 1304 (IONetworkController::Action) 1305 &IONetworkInterface::performGatedCommand, 1306 this, /* target */ 1307 ctr, /* param0 */ 1308 (void *) cmd, /* param1 */ 1309 arg0, /* param2 */ 1310 arg1 ); /* param3 */ 1311 break; 1312 1313 default: 1314 // DLOG(%s: command not handled (%08lx), getName(), cmd); 1315 break; 1316 } 1317 1318 return ret; 1319} 1320 1321//------------------------------------------------------------------------------ 1322// Perform an ioctl command on the controller's workloop context. 1323 1324int IONetworkInterface::performGatedCommand(void * target, 1325 void * arg1_ctr, 1326 void * arg2_cmd, 1327 void * arg3_0, 1328 void * arg4_1) 1329{ 1330 IONetworkInterface * self = (IONetworkInterface *) target; 1331 IONetworkController * ctr = (IONetworkController *) arg1_ctr; 1332 struct ifreq * ifr = (struct ifreq *) arg4_1; 1333 SInt32 ret = EOPNOTSUPP; 1334 1335 // Refuse to issue I/O to the controller if it is in a power state 1336 // that renders it "unusable". 1337 1338 if ( self->getInterfaceState() & kIONetworkInterfaceDisabledState ) 1339 return EPWROFF; 1340 1341 switch ( (uintptr_t) arg2_cmd ) 1342 { 1343 // Set interface MTU. 1344 1345 case SIOCSIFMTU: 1346 ret = self->syncSIOCSIFMTU(ctr, ifr); 1347 break; 1348 1349 // Set interface (controller) media type. 1350 1351 case SIOCSIFMEDIA: 1352 ret = self->syncSIOCSIFMEDIA(ctr, ifr); 1353 break; 1354 1355 // Set link layer address. 1356 1357 case SIOCSIFLLADDR: 1358 ret = ctr->errnoFromReturn( 1359 ctr->setHardwareAddress( ifr->ifr_addr.sa_data, 1360 ifr->ifr_addr.sa_len ) ); 1361 break; 1362 } 1363 1364 return ret; 1365} 1366 1367//------------------------------------------------------------------------------ 1368// if_ioctl() handler - Calls performCommand() when we receive an ioctl 1369// from DLIL. 1370 1371errno_t 1372IONetworkInterface::if_ioctl( ifnet_t ifp, unsigned long cmd, void * data ) 1373{ 1374 IONetworkInterface * self = IFNET_TO_THIS(ifp); 1375 IONetworkController * driver; 1376 errno_t err; 1377 1378 if (!self || self->isInactive()) 1379 { 1380 return EOPNOTSUPP; 1381 } 1382 1383 driver = self->_driver; 1384 if (!driver) 1385 { 1386 return EINVAL; 1387 } 1388 1389 assert(ifp == self->_backingIfnet); 1390 1391 err = self->performCommand( driver, cmd, (void *) ifp, data ); 1392 return err; 1393} 1394 1395//------------------------------------------------------------------------------ 1396// if_output() handler. 1397// 1398// Handle a call from the network stack to transmit the given mbuf. 1399// For now, we can assume that the mbuf is singular, and never chained. 1400 1401int IONetworkInterface::if_output( ifnet_t ifp, mbuf_t m ) 1402{ 1403 UInt32 noraceTemp; 1404 int delta; 1405 u_int32_t outPackets, outErrors; 1406 1407 IONetworkInterface * self = IFNET_TO_THIS(ifp); 1408 1409 assert(ifp == self->_backingIfnet); 1410 1411 if ( m == 0 ) 1412 { 1413 DLOG("%s: NULL output mbuf\n", self->getName()); 1414 return EINVAL; 1415 } 1416 1417 if ( (mbuf_flags(m) & MBUF_PKTHDR) == 0 ) 1418 { 1419 DLOG("%s: MBUF_PKTHDR bit not set\n", self->getName()); 1420 mbuf_freem(m); 1421 return EINVAL; 1422 } 1423 1424 // Increment output related statistics. 1425 // update the stats that the driver maintains 1426 noraceTemp = self->_driverStats.outputErrors; 1427 delta = noraceTemp - self->_lastDriverStats.outputErrors; 1428 outErrors = ABS(delta); 1429 self->_lastDriverStats.outputErrors = noraceTemp; 1430 1431 noraceTemp = self->_driverStats.outputPackets; 1432 delta = noraceTemp - self->_lastDriverStats.outputPackets; 1433 outPackets = ABS(delta); 1434 self->_lastDriverStats.outputPackets = noraceTemp; 1435 1436 // update the stats in the interface 1437 ifnet_stat_increment_out(self->getIfnet(), outPackets, mbuf_pkthdr_len(m), outErrors); 1438 1439 // Feed the output filter tap. 1440 if(self->_outputFilterFunc) 1441 self->feedPacketOutputTap(m); 1442 1443 // Forward the packet to the registered output packet handler. 1444 return ((self->_outTarget)->*(self->_outAction))(m, 0); 1445} 1446 1447//------------------------------------------------------------------------------ 1448// if_set_bpf_tap() handler. Handles request from the DLIL to enable or 1449// disable the input/output filter taps. 1450 1451errno_t IONetworkInterface::if_set_bpf_tap( 1452 ifnet_t ifp, 1453 bpf_tap_mode mode, 1454 bpf_packet_func func ) 1455{ 1456 IONetworkInterface * self = IFNET_TO_THIS(ifp); 1457 bool changed = false; 1458 1459 assert(ifp == self->_backingIfnet); 1460 if (self->isInactive()) 1461 { 1462 return 0; 1463 } 1464 1465 IOLockLock(self->_privateLock); 1466 1467 switch ( mode ) 1468 { 1469 case BPF_TAP_DISABLE: 1470 changed = (self->_inputFilterFunc != 0); 1471 self->_inputFilterFunc = self->_outputFilterFunc = 0; 1472 break; 1473 1474 case BPF_TAP_INPUT: 1475 assert(func); 1476 changed = (self->_inputFilterFunc == 0); 1477 self->_inputFilterFunc = func; 1478 break; 1479 1480 case BPF_TAP_OUTPUT: 1481 assert(func); 1482 self->_outputFilterFunc = func; 1483 break; 1484 1485 case BPF_TAP_INPUT_OUTPUT: 1486 assert(func); 1487 changed = (self->_inputFilterFunc == 0); 1488 self->_inputFilterFunc = self->_outputFilterFunc = func; 1489 break; 1490 1491 default: 1492 DLOG("%s: Unknown BPF tap mode %d\n", self->getName(), mode); 1493 break; 1494 } 1495 1496 IOLockUnlock(self->_privateLock); 1497 1498 if (changed) 1499 self->notifyDriver(kIONetworkNotificationBPFTapStateChange, 0); 1500 1501 return 0; 1502} 1503 1504//------------------------------------------------------------------------------ 1505 1506void IONetworkInterface::if_detach( ifnet_t ifp ) 1507{ 1508 IONetworkInterface * self = IFNET_TO_THIS(ifp); 1509 1510 assert(WAITING_FOR_DETACH(self) == 1); 1511 self->retain(); 1512 IOLockLock(self->_privateLock); 1513 WAITING_FOR_DETACH(self) = 0; 1514 thread_wakeup((void *) self); 1515 IOLockUnlock(self->_privateLock); 1516 self->release(); 1517} 1518 1519//------------------------------------------------------------------------------ 1520// ifnet field (and property table) getter/setter. 1521 1522#define IO_IFNET_GET(func, type, field, kpi) \ 1523type IONetworkInterface::func(void) const \ 1524{ \ 1525 type val = (_backingIfnet != NULL) ? \ 1526 kpi(_backingIfnet) : _##field; \ 1527 return val; \ 1528} 1529 1530#define IO_IFNET_SET(func, type, field, kpi) \ 1531bool IONetworkInterface::func(type value) \ 1532{ \ 1533 if (_backingIfnet) \ 1534 kpi(_backingIfnet, value); \ 1535 else \ 1536 _##field = value; \ 1537 return true; \ 1538} 1539 1540#define IO_IFNET_RMW(func, type, field, kpi) \ 1541bool IONetworkInterface::func(type set, type clear) \ 1542{ \ 1543 if (_backingIfnet) \ 1544 kpi(_backingIfnet, set, set | clear); \ 1545 else \ 1546 _##field = (_##field & ~clear) | set; \ 1547 return true; \ 1548} 1549 1550//------------------------------------------------------------------------------ 1551// Interface type accessors (ifp->if_type). The list of interface types is 1552// defined in <bsd/net/if_types.h>. 1553 1554bool IONetworkInterface::setInterfaceType(UInt8 type) 1555{ 1556 // once attached to dlil, we can't change the interface type 1557 if (_backingIfnet) 1558 return false; 1559 else 1560 _type = type; 1561 return true; 1562} 1563 1564UInt8 IONetworkInterface::getInterfaceType(void) const 1565{ 1566 return _type; 1567} 1568 1569IO_IFNET_SET(setMaxTransferUnit, UInt32, mtu, ifnet_set_mtu) 1570IO_IFNET_GET(getMaxTransferUnit, UInt32, mtu, ifnet_mtu) 1571 1572IO_IFNET_RMW(setFlags, UInt16, flags, ifnet_set_flags) 1573IO_IFNET_GET(getFlags, UInt16, flags, ifnet_flags) 1574 1575bool IONetworkInterface::setExtraFlags( UInt32 set, UInt32 clear ) 1576{ 1577 _eflags = (_eflags & ~clear) | set; 1578 return true; 1579} 1580 1581IO_IFNET_GET(getExtraFlags, UInt32, eflags, ifnet_eflags) 1582 1583IO_IFNET_SET(setMediaAddressLength, UInt8, addrlen, ifnet_set_addrlen) 1584IO_IFNET_GET(getMediaAddressLength, UInt8, addrlen, ifnet_addrlen) 1585 1586IO_IFNET_SET(setMediaHeaderLength, UInt8, hdrlen, ifnet_set_hdrlen) 1587IO_IFNET_GET(getMediaHeaderLength, UInt8, hdrlen, ifnet_hdrlen) 1588 1589IO_IFNET_GET(getUnitNumber, UInt16, unit, ifnet_unit) 1590 1591bool IONetworkInterface::setUnitNumber( UInt16 value ) 1592{ 1593 // once we've attached to dlil, unit can't be changed 1594 if (_backingIfnet) 1595 return false; 1596 1597 if (setProperty( kIOInterfaceUnit, value, 32 )) 1598 { 1599 char name[128]; 1600 1601 _unit = value; 1602 setProperty( kIOPrimaryInterface, isPrimaryInterface() ); 1603 snprintf(name, sizeof(name), "%s%u", getNamePrefix(), _unit); 1604 setName(name); 1605 return true; 1606 } 1607 else 1608 return false; 1609} 1610 1611bool IONetworkInterface::setInterfaceSubType( uint32_t subType ) 1612{ 1613 // once attached to dlil, we can't change the interface sub-type 1614 if (_backingIfnet) 1615 return false; 1616 else 1617 _subType = subType; 1618 return true; 1619} 1620 1621//------------------------------------------------------------------------------ 1622// Return true if the interface has been registered with the network layer, 1623// false otherwise. 1624 1625bool IONetworkInterface::isRegistered() const 1626{ 1627 return (bool)(getInterfaceState() & kIONetworkInterfaceRegisteredState); 1628} 1629 1630//------------------------------------------------------------------------------ 1631// serialize 1632 1633bool IONetworkInterface::serializeProperties( OSSerialize * s ) const 1634{ 1635 IONetworkInterface * self = (IONetworkInterface *) this; 1636 1637 self->setProperty( kIOInterfaceType, getInterfaceType(), 8 ); 1638 self->setProperty( kIOMaxTransferUnit, getMaxTransferUnit(), 32 ); 1639 self->setProperty( kIOInterfaceFlags, getFlags(), 16 ); 1640 self->setProperty( kIOInterfaceExtraFlags, getExtraFlags(), 32 ); 1641 self->setProperty( kIOMediaAddressLength, getMediaAddressLength(), 8 ); 1642 self->setProperty( kIOMediaHeaderLength, getMediaHeaderLength(), 8 ); 1643 1644 return super::serializeProperties( s ); 1645} 1646 1647//------------------------------------------------------------------------------ 1648// Return the interface state flags. 1649 1650UInt32 IONetworkInterface::getInterfaceState() const 1651{ 1652 return _stateBits->unsigned32BitValue(); 1653} 1654 1655//------------------------------------------------------------------------------ 1656// Set (or clear) the interface state flags. 1657 1658UInt32 IONetworkInterface::setInterfaceState( UInt32 set, 1659 UInt32 clear ) 1660{ 1661 UInt32 val; 1662 1663 assert( _stateBits ); 1664 1665 IOLockLock(_privateLock); 1666 1667 val = ( _stateBits->unsigned32BitValue() | set ) & ~clear; 1668 _stateBits->setValue( val ); 1669 1670 IOLockUnlock(_privateLock); 1671 1672 return val; 1673} 1674 1675//------------------------------------------------------------------------------ 1676// Perform a lookup of the dictionary kept by the interface, 1677// and return an entry that matches the specified string key. 1678// 1679// key: Search for an IONetworkData entry with this key. 1680// 1681// Returns the matching entry, or 0 if no match was found. 1682 1683IONetworkData * IONetworkInterface::getNetworkData(const OSSymbol * key) const 1684{ 1685 return OSDynamicCast(IONetworkData, _dataDict->getObject(key)); 1686} 1687 1688IONetworkData * IONetworkInterface::getNetworkData(const char * key) const 1689{ 1690 return OSDynamicCast(IONetworkData, _dataDict->getObject(key)); 1691} 1692 1693//------------------------------------------------------------------------------ 1694// A private function to copy the data dictionary to the property table. 1695 1696bool IONetworkInterface::_syncNetworkDataDict() 1697{ 1698 OSDictionary * aCopy = OSDictionary::withDictionary(_dataDict); 1699 bool ret = false; 1700 1701 if (aCopy) { 1702 ret = setProperty(kIONetworkData, aCopy); 1703 aCopy->release(); 1704 } 1705 1706 return ret; 1707} 1708 1709//------------------------------------------------------------------------------ 1710// Remove an entry from the IONetworkData dictionary managed by the interface. 1711// The removed object is released. 1712 1713bool IONetworkInterface::removeNetworkData(const OSSymbol * aKey) 1714{ 1715 bool ret; 1716 1717 IOLockLock(_privateLock); 1718 _dataDict->removeObject(aKey); 1719 ret = _syncNetworkDataDict(); 1720 IOLockUnlock(_privateLock); 1721 return ret; 1722} 1723 1724bool IONetworkInterface::removeNetworkData(const char * aKey) 1725{ 1726 bool ret; 1727 1728 IOLockLock(_privateLock); 1729 _dataDict->removeObject(aKey); 1730 ret = _syncNetworkDataDict(); 1731 IOLockUnlock(_privateLock); 1732 return ret; 1733} 1734 1735//------------------------------------------------------------------------------ 1736// Add an IONetworkData object to a dictionary managed by the interface. 1737 1738bool IONetworkInterface::addNetworkData(IONetworkData * aData) 1739{ 1740 bool ret = false; 1741 1742 if (OSDynamicCast(IONetworkData, aData) == 0) 1743 return false; 1744 1745 IOLockLock(_privateLock); 1746 if (_dataDict->setObject(aData->getKey(), aData)) 1747 ret = _syncNetworkDataDict(); 1748 IOLockUnlock(_privateLock); 1749 return ret; 1750} 1751 1752//------------------------------------------------------------------------------ 1753// Create a new IOUserClient to handle client requests. The default 1754// implementation will create an IONetworkUserClient instance if 1755// the type given is kIONetworkUserClientTypeID. 1756 1757IOReturn IONetworkInterface::newUserClient(task_t owningTask, 1758 void * /*security_id*/, 1759 UInt32 type, 1760 IOUserClient ** handler) 1761{ 1762 IOReturn err = kIOReturnSuccess; 1763 IONetworkUserClient * client; 1764 1765 if (type != kIONetworkUserClientTypeID) 1766 return kIOReturnBadArgument; 1767 1768 client = IONetworkUserClient::withTask(owningTask); 1769 1770 if (!client || !client->attach(this) || !client->start(this)) 1771 { 1772 if (client) 1773 { 1774 client->detach(this); 1775 client->release(); 1776 client = 0; 1777 } 1778 err = kIOReturnNoMemory; 1779 } 1780 1781 *handler = client; 1782 1783 return err; 1784} 1785 1786//------------------------------------------------------------------------------ 1787// Power change notices are posted by the controller's policy-maker to 1788// inform the interface that the controller is changing power states. 1789// There are two notifications for each state change, delivered prior 1790// to the state change, and after the state change has occurred. 1791 1792struct IONetworkPowerChangeNotice { 1793 IOService * policyMaker; 1794 IOPMPowerFlags powerFlags; 1795 uint32_t stateNumber; 1796 uint32_t phase; 1797}; 1798 1799enum { 1800 kPhasePowerStateWillChange = 0x01, 1801 kPhasePowerStateDidChange = 0x02 1802}; 1803 1804//------------------------------------------------------------------------------ 1805// Handle controller's power state transitions. 1806 1807IOReturn 1808IONetworkInterface::controllerWillChangePowerState( 1809 IONetworkController * controller, 1810 IOPMPowerFlags flags, 1811 UInt32 stateNumber, 1812 IOService * policyMaker ) 1813{ 1814 if ( ( flags & IOPMDeviceUsable ) == 0 ) 1815 { 1816 setInterfaceState( kIONetworkInterfaceDisabledState ); 1817 } 1818 return kIOReturnSuccess; 1819} 1820 1821IOReturn 1822IONetworkInterface::controllerDidChangePowerState( 1823 IONetworkController * controller, 1824 IOPMPowerFlags flags, 1825 UInt32 stateNumber, 1826 IOService * policyMaker ) 1827{ 1828 if ( flags & IOPMDeviceUsable ) 1829 { 1830 setInterfaceState( 0, kIONetworkInterfaceDisabledState ); 1831 } 1832 return kIOReturnSuccess; 1833} 1834 1835//------------------------------------------------------------------------------ 1836// Static member functions called by power-management notification handlers. 1837// Act as stub functions that will simply forward the call to virtual member 1838// functions. 1839 1840void 1841IONetworkInterface::powerChangeHandler( void * target, 1842 void * param0, 1843 void * param1 ) 1844{ 1845 IONetworkInterface * self = (IONetworkInterface *) target; 1846 IONetworkPowerChangeNotice * notice; 1847 1848 assert( self ); 1849 if (!self->_driver) 1850 return; 1851 1852 if ( param1 == 0 ) 1853 { 1854 // Issue a call to this same function synchronized with the 1855 // work loop thread. 1856 1857 self->_driver->executeCommand( 1858 /* client */ self, 1859 /* action */ (IONetworkController::Action) &powerChangeHandler, 1860 /* target */ self, 1861 /* param0 */ param0, 1862 /* param1 */ (void *) true ); 1863 1864 return; 1865 } 1866 1867 notice = (IONetworkPowerChangeNotice *) param0; 1868 assert( notice ); 1869 1870 DLOG("%s: power change flags:%08x state:%d from:%p phase:%d\n", 1871 self->getName(), (uint32_t) notice->powerFlags, 1872 notice->stateNumber, notice->policyMaker, notice->phase ); 1873 1874 if ( notice->phase == kPhasePowerStateWillChange ) 1875 { 1876 self->controllerWillChangePowerState( 1877 self->_driver, 1878 notice->powerFlags, 1879 notice->stateNumber, 1880 notice->policyMaker ); 1881 } 1882 else if ( notice->phase == kPhasePowerStateDidChange ) 1883 { 1884 self->controllerDidChangePowerState( 1885 self->_driver, 1886 notice->powerFlags, 1887 notice->stateNumber, 1888 notice->policyMaker ); 1889 } 1890} 1891 1892//------------------------------------------------------------------------------ 1893// Handle notitifications triggered by controller's power state change. 1894 1895IOReturn 1896IONetworkInterface::powerStateWillChangeTo( IOPMPowerFlags powerFlags, 1897 unsigned long stateNumber, 1898 IOService * policyMaker ) 1899{ 1900 IONetworkPowerChangeNotice notice; 1901 1902 notice.policyMaker = policyMaker; 1903 notice.powerFlags = powerFlags; 1904 notice.stateNumber = stateNumber; 1905 notice.phase = kPhasePowerStateWillChange; 1906 1907 powerChangeHandler( (void *) this, (void *) ¬ice, 1908 /* param1: inside gate */ (void *) false ); 1909 return kIOPMAckImplied; 1910} 1911 1912IOReturn 1913IONetworkInterface::powerStateDidChangeTo( IOPMPowerFlags powerFlags, 1914 unsigned long stateNumber, 1915 IOService * policyMaker ) 1916{ 1917 IONetworkPowerChangeNotice notice; 1918 1919 notice.policyMaker = policyMaker; 1920 notice.powerFlags = powerFlags; 1921 notice.stateNumber = stateNumber; 1922 notice.phase = kPhasePowerStateDidChange; 1923 1924 powerChangeHandler( (void *) this, (void *) ¬ice, 1925 /* param1: inside gate */ (void *) false ); 1926 return kIOPMAckImplied; 1927} 1928 1929//------------------------------------------------------------------------------ 1930 1931IOReturn IONetworkInterface::message( UInt32 type, IOService * provider, 1932 void * argument ) 1933{ 1934 if (kMessageControllerWillShutdown == type) 1935 { 1936 // Handle system shutdown or restarts. Handle this by performing the 1937 // same work when driver is transitioning to an unusable power state. 1938 1939 DLOG("%s: kMessageControllerWillShutdown\n", getName()); 1940 haltOutputThread( kTxThreadStateDetach ); 1941 powerStateWillChangeTo( 0, 0, NULL ); 1942 return kIOReturnSuccess; 1943 } 1944 1945 return super::message( type, provider, argument ); 1946} 1947 1948//------------------------------------------------------------------------------ 1949// Termination 1950 1951bool IONetworkInterface::requestTerminate( 1952 IOService * provider, 1953 IOOptionBits options ) 1954{ 1955#if EVALUATE_FOR_LATER_REMOVAL 1956 // Early indication that provider started termination 1957 if (provider == _driver) 1958 { 1959 // Stop transmit thread before a later disable by the 1960 // driver on work loop context, which can deadlock. 1961 1962 DLOG("%s::requestTerminate(%s)\n", 1963 getName(), provider->getName()); 1964 haltOutputThread( kTxThreadStateDetach ); 1965 } 1966#endif 1967 1968 return super::requestTerminate(provider, options); 1969} 1970 1971bool IONetworkInterface::willTerminate( IOService * provider, 1972 IOOptionBits options ) 1973{ 1974 DLOG("%s::%s(%s, 0x%x)\n", getName(), __FUNCTION__, 1975 provider->getName(), (uint32_t) options); 1976 1977 setInterfaceState( kIONetworkInterfaceDisabledState ); 1978 return super::willTerminate( provider, options ); 1979} 1980 1981//------------------------------------------------------------------------------ 1982// Inlined functions pulled from header file to ensure 1983// binary compatibility with drivers built with gcc2.95. 1984 1985IONetworkData * IONetworkInterface::getParameter(const char * aKey) const 1986{ return getNetworkData(aKey); } 1987 1988bool IONetworkInterface::setExtendedFlags(UInt32 flags, UInt32 clear) 1989{ return true; } 1990 1991//------------------------------------------------------------------------------ 1992 1993ifnet_t IONetworkInterface::getIfnet( void ) const 1994{ 1995 return _backingIfnet; 1996} 1997 1998OSMetaClassDefineReservedUsed(IONetworkInterface, 0); 1999 2000IOReturn IONetworkInterface::attachToDataLinkLayer( IOOptionBits options, 2001 void * parameter ) 2002{ 2003 ifnet_init_params params; 2004 ifnet_init_eparams eparams; 2005 struct sockaddr_dl * ll_addr = 0; 2006 char buffer[2 * sizeof(struct sockaddr_dl)]; 2007 errno_t error; 2008 OSObject * prop; 2009 IOReturn result = kIOReturnInternalError; 2010 2011 if (!_driver) 2012 { 2013 LOG("%s: BSD attach failed, no driver\n", getName()); 2014 goto fail; 2015 } 2016 2017 memset(¶ms, 0, sizeof(params)); 2018 if (!initIfnetParams(¶ms)) 2019 { 2020 LOG("%s: initIfnetParams failed\n", getName()); 2021 goto fail; 2022 } 2023 2024 memset(&eparams, 0, sizeof(eparams)); 2025 2026 IOLockLock(_privateLock); 2027 _configFlags |= kConfigFrozen; 2028 2029 // Pass ifnet_init_params to subclass which is then converted to 2030 // the new ifnet_init_eparams. All this to avoid burning another 2031 // vtable pad slot, and subclasses don't need to change. 2032 2033 eparams.ver = IFNET_INIT_CURRENT_VERSION; 2034 eparams.len = sizeof(eparams); 2035 2036 eparams.uniqueid = params.uniqueid; 2037 eparams.uniqueid_len = params.uniqueid_len; 2038 eparams.name = params.name; 2039 eparams.unit = params.unit; 2040 eparams.family = params.family; 2041 eparams.type = params.type; 2042 eparams.subfamily = _subType; 2043 2044 eparams.demux = params.demux; 2045 eparams.add_proto = params.add_proto; 2046 eparams.del_proto = params.del_proto; 2047 eparams.check_multi = params.check_multi; 2048 eparams.framer = params.framer; 2049 eparams.softc = params.softc; 2050 eparams.ioctl = params.ioctl; 2051 eparams.set_bpf_tap = params.set_bpf_tap; 2052 eparams.detach = params.detach; 2053 eparams.event = params.event; 2054 eparams.broadcast_addr = params.broadcast_addr; 2055 eparams.broadcast_len = params.broadcast_len; 2056 2057 if (!(_configFlags & kConfigRxPoll) && 2058 !(_configFlags & kConfigTxPull)) 2059 { 2060 eparams.flags = IFNET_INIT_LEGACY; 2061 } 2062 2063 if (_configFlags & kConfigRxPoll) 2064 { 2065 eparams.flags = IFNET_INIT_INPUT_POLL; 2066 eparams.input_ctl = if_input_ctl; 2067 eparams.input_poll = (_rxPollOptions & kIONetworkWorkLoopSynchronous) ? 2068 if_input_poll_gated : if_input_poll; 2069 2070 // cache the driver's inputPacketPoll action 2071 _rxPollAction = (void *) OSMemberFunctionCast( 2072 IONetworkController::Action, 2073 _driver, &IONetworkController::pollInputPackets); 2074 2075 _rxCtlAction = (void *) OSMemberFunctionCast( 2076 IONetworkController::Action, 2077 this, &IONetworkInterface::actionInputCtl); 2078 2079 DLOG("%s: supports input polling\n", getName()); 2080 } 2081 2082 if (_configFlags & kConfigTxPull) 2083 { 2084 eparams.sndq_maxlen = _txQueueSize; 2085 if (_txQueueSize) 2086 DLOG("%s: sndq_maxlen = %u\n", getName(), _txQueueSize); 2087 2088 eparams.output_sched_model = _txSchedulingModel; 2089 2090 if (_txPullOptions & kIONetworkWorkLoopSynchronous) 2091 { 2092 eparams.start = if_start_gated; 2093 2094 // retain work loop for transmitThreadStop() 2095 _txWorkLoop = _driver->getWorkLoop(); 2096 if (!_txWorkLoop) 2097 { 2098 IOLockUnlock(_privateLock); 2099 goto fail; 2100 } 2101 _txWorkLoop->retain(); 2102 2103 _txStartAction = (void *) OSMemberFunctionCast( 2104 IONetworkController::Action, 2105 this, &IONetworkInterface::drainOutputQueue); 2106 } 2107 else 2108 { 2109 eparams.start = if_start; 2110 } 2111 2112 if (_configFlags & kConfigPreEnqueue) 2113 { 2114 eparams.pre_enqueue = if_output_pre_enqueue; 2115 } 2116 2117 DLOG("%s: supports %stransmit pull, pre_enqueue %d\n", 2118 getName(), _txWorkLoop ? "gated " : "", (eparams.pre_enqueue != 0)); 2119 } 2120 else 2121 { 2122 eparams.output = params.output; 2123 } 2124 2125 eparams.output_ctl = if_output_ctl; 2126 2127 // u_int64_t output_bw 2128 // u_int64_t input_bw 2129 2130 IOLockUnlock(_privateLock); 2131 2132 error = ifnet_allocate_extended(&eparams, &_backingIfnet); 2133 if (error) 2134 { 2135 LOG("%s: ifnet_allocate_extended error %d\n", getName(), error); 2136 goto fail; 2137 } 2138 2139 error = ifnet_set_offload(_backingIfnet, 2140 getIfnetHardwareAssistValue(_driver)); 2141 if (error) 2142 LOG("%s: ifnet_set_offload error %d\n", getName(), error); 2143 2144 prop = _driver->copyProperty(kIOMACAddress); 2145 if (prop) 2146 { 2147 OSData * macAddr = OSDynamicCast(OSData, prop); 2148 uint32_t len; 2149 2150 memset(buffer, 0, sizeof(buffer)); 2151 len = sizeof(buffer) - offsetof(struct sockaddr_dl, sdl_data); 2152 2153 if (macAddr && macAddr->getLength() && (macAddr->getLength() <= len)) 2154 { 2155 len = macAddr->getLength(); 2156 ll_addr = (struct sockaddr_dl *) buffer; 2157 bcopy(macAddr->getBytesNoCopy(), ll_addr->sdl_data, len); 2158 ll_addr->sdl_len = offsetof(struct sockaddr_dl, sdl_data) + len; 2159 ll_addr->sdl_family = AF_LINK; 2160 ll_addr->sdl_alen = len; 2161 } 2162 prop->release(); 2163 2164 if (!ll_addr) 2165 { 2166 LOG("%s: BSD attach failed, bad MAC address\n", getName()); 2167 goto fail; 2168 } 2169 } 2170 2171 ifnet_set_mtu(_backingIfnet, _mtu); 2172 ifnet_set_flags(_backingIfnet, _flags, 0xffff); 2173 ifnet_set_addrlen(_backingIfnet, _addrlen); 2174 ifnet_set_hdrlen(_backingIfnet, _hdrlen); 2175 if (_configFlags & kConfigRxPoll) 2176 ifnet_set_rcvq_maxlen(_backingIfnet, _rxRingSize); 2177 2178 error = ifnet_attach(_backingIfnet, ll_addr); 2179 if (!error) 2180 result = kIOReturnSuccess; 2181 else 2182 LOG("%s: ifnet_attach error %d\n", getName(), error); 2183 2184fail: 2185 if ((result != kIOReturnSuccess) && _backingIfnet) 2186 { 2187 // attach failed, clean up 2188 ifnet_release(_backingIfnet); 2189 _backingIfnet = NULL; 2190 } 2191 2192 return result; 2193} 2194 2195//------------------------------------------------------------------------------ 2196 2197OSMetaClassDefineReservedUsed(IONetworkInterface, 1); 2198 2199void IONetworkInterface::detachFromDataLinkLayer( 2200 IOOptionBits options, void * parameter ) 2201{ 2202 // Running on thread call context 2203 // Permanently halt the transmit thread before ifnet detach 2204 DLOG("%s: detachFromDataLinkLayer\n", getName()); 2205 haltOutputThread( kTxThreadStateDetach ); 2206 2207 WAITING_FOR_DETACH(this) = true; 2208 2209 // this will lead to another thread calling if_detach() 2210 ifnet_detach(_backingIfnet); 2211 2212 // protect against if_detach() running before we block 2213 IOLockLock(_privateLock); 2214 while (WAITING_FOR_DETACH(this)) // if false, if_detach is done 2215 { 2216 IOLockSleep(_privateLock, this, THREAD_UNINT); 2217 } 2218 IOLockUnlock(_privateLock); 2219} 2220 2221//------------------------------------------------------------------------------ 2222 2223void IONetworkInterface::debuggerRegistered( void ) 2224{ 2225 char buffer[REMOTE_NMI_PATTERN_LEN + 2]; 2226 unsigned int i; 2227 2228 if (_remote_NMI_len) 2229 return; 2230 2231 memset(buffer, 0, sizeof(buffer)); 2232 if (!PE_parse_boot_argn(kRemoteNMI, buffer, sizeof(buffer))) 2233 return; 2234 2235 for (i = 0; i < (REMOTE_NMI_PATTERN_LEN >> 1); i++) { 2236 unsigned int val; 2237 2238 if (sscanf(buffer + (i << 1), "%02X", &val) != 1) 2239 break; 2240 2241 buffer[i] = val; 2242 } 2243 2244 _remote_NMI_pattern = (char *) IOMalloc(sizeof(char) * i + 1); 2245 if (!_remote_NMI_pattern) 2246 return; 2247 2248 _remote_NMI_pattern[i] = '\0'; 2249 memcpy(_remote_NMI_pattern, buffer, i); 2250 _remote_NMI_len = i; 2251} 2252 2253//------------------------------------------------------------------------------ 2254 2255void IONetworkInterface::reportDataTransferRates( 2256 uint64_t outputRateMax, 2257 uint64_t inputRateMax, 2258 uint64_t outputRateEffective, 2259 uint64_t inputRateEffective ) 2260{ 2261 if_bandwidths_t bw_out, bw_in; 2262 2263 if ((_configFlags & kConfigDataRates) == 0) 2264 { 2265 IOLockLock(_privateLock); 2266 _configFlags |= kConfigDataRates; 2267 IOLockUnlock(_privateLock); 2268 } 2269 2270 if (!outputRateEffective) 2271 outputRateEffective = outputRateMax; 2272 if (!inputRateEffective) 2273 inputRateEffective = inputRateMax; 2274 2275 bw_out.max_bw = outputRateMax; 2276 bw_out.eff_bw = outputRateEffective; 2277 bw_in.max_bw = inputRateMax; 2278 bw_in.eff_bw = inputRateEffective; 2279 2280 if (_backingIfnet) 2281 ifnet_set_bandwidths(_backingIfnet, &bw_out, &bw_in); 2282} 2283 2284//------------------------------------------------------------------------------ 2285// Driver-pull output model 2286//------------------------------------------------------------------------------ 2287 2288IOReturn IONetworkInterface::configureOutputPullModel( 2289 uint32_t driverQueueSize, 2290 IOOptionBits options, 2291 uint32_t outputQueueSize, 2292 uint32_t outputSchedulingModel ) 2293{ 2294 IOReturn ret = kIOReturnError; 2295 2296 IOLockLock(_privateLock); 2297 if ((_configFlags & kConfigFrozen) == 0) 2298 { 2299 _txRingSize = driverQueueSize; 2300 _txPullOptions = options; 2301 _txQueueSize = outputQueueSize; 2302 _txSchedulingModel = outputSchedulingModel; 2303 _configFlags |= kConfigTxPull; 2304 ret = kIOReturnSuccess; 2305 } 2306 IOLockUnlock(_privateLock); 2307 2308 return ret; 2309} 2310 2311IOReturn IONetworkInterface::installOutputPreEnqueueHandler( 2312 OutputPreEnqueueHandler handler, 2313 void * target, 2314 void * refCon ) 2315{ 2316 IOReturn ret = kIOReturnError; 2317 2318 if (!handler) 2319 return kIOReturnBadArgument; 2320 2321 IOLockLock(_privateLock); 2322 if ((_configFlags & kConfigFrozen) == 0) 2323 { 2324 _peqHandler = handler; 2325 _peqTarget = target; 2326 _peqRefcon = refCon; 2327 _configFlags |= kConfigPreEnqueue; 2328 ret = kIOReturnSuccess; 2329 } 2330 IOLockUnlock(_privateLock); 2331 2332 return ret; 2333} 2334 2335errno_t IONetworkInterface::if_output_pre_enqueue( ifnet_t ifp, mbuf_t packet ) 2336{ 2337 IONetworkInterface * me = IFNET_TO_THIS(ifp); 2338 errno_t ret; 2339 2340 assert(ifp == me->_backingIfnet); 2341 assert(me->_peqHandler); 2342 2343 ret = me->_peqHandler(me->_peqTarget, me->_peqRefcon, packet); 2344 return ret; 2345} 2346 2347int IONetworkInterface::if_start_precheck( ifnet_t ifp ) 2348{ 2349 int halted = 0; 2350 2351 if (__builtin_expect((_txThreadState != 0), 0)) 2352 { 2353 IOLockLock(_privateLock); 2354 if (_txThreadState & kTxThreadStateInit) 2355 { 2356 // The initial if_start call 2357 assert(_txStartThread == 0); 2358 _txStartThread = current_thread(); 2359 _txThreadState &= ~kTxThreadStateInit; 2360 } 2361 if (_txThreadState & (kTxThreadStateStop | kTxThreadStateDetach)) 2362 { 2363 // Disable request or interface detached from DLIL 2364 _txThreadState &= ~kTxThreadStateStop; 2365 _txThreadState |= kTxThreadStateHalted; 2366 thread_wakeup(&_txThreadState); 2367 } 2368 if (_txThreadState & kTxThreadStateHalted) 2369 { 2370 halted = true; 2371 } 2372 IOLockUnlock(_privateLock); 2373 2374 if (halted) 2375 { 2376 // Thread will be halted before we drop our open/retain 2377 // on the controller. 2378 if (_txThreadState & kTxThreadStatePurge) 2379 ifnet_purge(ifp); 2380 } 2381 } 2382 2383 return halted; 2384} 2385 2386void IONetworkInterface::if_start( ifnet_t ifp ) 2387{ 2388 IONetworkInterface * me = IFNET_TO_THIS(ifp); 2389 IONetworkController * driver; 2390 2391 assert(ifp == me->_backingIfnet); 2392 if (me->if_start_precheck(ifp)) 2393 return; 2394 2395 driver = me->_driver; 2396 assert(driver); 2397 if (__builtin_expect(!driver, 0)) 2398 { 2399 IOLockLock(me->_privateLock); 2400 me->_txThreadState |= kTxThreadStateHalted; 2401 IOLockUnlock(me->_privateLock); 2402 return; 2403 } 2404 2405 me->drainOutputQueue(ifp, driver); 2406} 2407 2408void IONetworkInterface::if_start_gated( ifnet_t ifp ) 2409{ 2410 IONetworkInterface * me = IFNET_TO_THIS(ifp); 2411 IONetworkController * driver; 2412 2413 assert(ifp == me->_backingIfnet); 2414 if (me->if_start_precheck(ifp)) 2415 return; 2416 2417 driver = me->_driver; 2418 assert(driver); 2419 if (__builtin_expect(!driver, 0)) 2420 { 2421 IOLockLock(me->_privateLock); 2422 me->_txThreadState |= kTxThreadStateHalted; 2423 IOLockUnlock(me->_privateLock); 2424 return; 2425 } 2426 2427 driver->executeCommand( 2428 /* client */ me, 2429 /* action */ (IONetworkController::Action) me->_txStartAction, 2430 /* target */ me, 2431 /* param0 */ ifp, 2432 /* param1 */ driver, 2433 /* param2 */ 0, 2434 /* param3 */ 0 ); 2435} 2436 2437//------------------------------------------------------------------------------ 2438 2439errno_t IONetworkInterface::enqueueOutputPacket( mbuf_t packet, IOOptionBits options ) 2440{ 2441 return ifnet_enqueue(_backingIfnet, packet); 2442} 2443 2444//------------------------------------------------------------------------------ 2445 2446void IONetworkInterface::drainOutputQueue( 2447 ifnet_t ifp, 2448 IONetworkController * driver ) 2449{ 2450 uint32_t count; 2451 IOReturn status; 2452 2453 while (true) 2454 { 2455 // check for queue empty 2456 if (ifnet_get_sndq_len(ifp, &count) || !count) 2457 break; 2458 2459 _txThreadFlags = 0; 2460 status = driver->outputStart(this, 0); 2461 2462 if (kIOReturnSuccess != status) 2463 { 2464 if (kIOReturnNoResources == status) 2465 { 2466 // Try again on next packet enqueue, or when driver 2467 // calls outputThreadSignal(). 2468 // Retry transmit if preempted by outputThreadSignal() 2469 2470 if (OSCompareAndSwap(0, kTxThreadWakeupEnable, &_txThreadFlags)) 2471 break; 2472 } 2473 else 2474 { 2475 // Driver error, or dequeue failed 2476 break; 2477 } 2478 } 2479 } 2480} 2481 2482//------------------------------------------------------------------------------ 2483 2484IOReturn IONetworkInterface::dequeueOutputPackets( 2485 uint32_t maxCount, 2486 mbuf_t * packetHead, 2487 mbuf_t * packetTail, 2488 uint32_t * packetCount, 2489 uint64_t * packetBytes ) 2490{ 2491 uint32_t txByteCount, temp, txPackets = 0, txErrors = 0; 2492 int delta; 2493 errno_t error; 2494 2495 if (!maxCount || !packetHead) 2496 return kIOReturnBadArgument; 2497 2498 if (_txThreadState & (kTxThreadStateInit | kTxThreadStateDetach)) 2499 { 2500 goto no_frames; 2501 } 2502 2503 assert(_backingIfnet); 2504 2505 if (maxCount == 1) 2506 { 2507 error = ifnet_dequeue(_backingIfnet, packetHead); 2508 if (!error) 2509 { 2510 if (packetTail) 2511 *packetTail = *packetHead; 2512 if (packetCount) 2513 *packetCount = 1; 2514 txByteCount = mbuf_pkthdr_len(*packetHead); 2515 } 2516 } 2517 else 2518 { 2519 error = ifnet_dequeue_multi( 2520 _backingIfnet, maxCount, 2521 packetHead, packetTail, packetCount, &txByteCount); 2522 } 2523 if (error) 2524 goto no_frames; 2525 2526 // feed output tap 2527 if (_outputFilterFunc) 2528 { 2529 mbuf_t m, n; 2530 2531 m = *packetHead; 2532 assert(m); 2533 assert((mbuf_flags(m) & MBUF_PKTHDR)); 2534 2535 for (n = m; n != 0; n = mbuf_nextpkt(n)) 2536 feedPacketOutputTap(n); 2537 } 2538 2539 if (_txThreadSignal != _txThreadSignalLast) 2540 { 2541 // Update the stats that the driver maintains 2542 temp = _driverStats.outputErrors; 2543 delta = temp - _lastDriverStats.outputErrors; 2544 if (delta) 2545 { 2546 txErrors = ABS(delta); 2547 _lastDriverStats.outputErrors = temp; 2548 } 2549 2550 temp = _driverStats.outputPackets; 2551 delta = temp - _lastDriverStats.outputPackets; 2552 txPackets = ABS(delta); 2553 _lastDriverStats.outputPackets = temp; 2554 _txThreadSignalLast = _txThreadSignal; 2555 } 2556 2557 // update interface output byte count 2558 ifnet_stat_increment_out(_backingIfnet, txPackets, txByteCount, txErrors); 2559 if (packetBytes) 2560 *packetBytes = txByteCount; 2561 2562 return kIOReturnSuccess; 2563 2564no_frames: 2565 *packetHead = 0; 2566 if (packetTail) 2567 packetTail = 0; 2568 if (packetCount) 2569 packetCount = 0; 2570 if (packetBytes) 2571 packetBytes = 0; 2572 return kIOReturnNoFrames; 2573} 2574 2575IOReturn IONetworkInterface::dequeueOutputPacketsWithServiceClass( 2576 uint32_t maxCount, 2577 IOMbufServiceClass serviceClass, 2578 mbuf_t * packetHead, 2579 mbuf_t * packetTail, 2580 uint32_t * packetCount, 2581 uint64_t * packetBytes ) 2582{ 2583 uint32_t txByteCount, temp, txPackets = 0, txErrors = 0; 2584 int delta; 2585 mbuf_svc_class_t mbufSC; 2586 errno_t error; 2587 2588 if (!maxCount || !packetHead) 2589 return kIOReturnBadArgument; 2590 2591 if (_txThreadState & (kTxThreadStateInit | kTxThreadStateDetach)) 2592 { 2593 goto no_frames; 2594 } 2595 2596 assert(_backingIfnet); 2597 2598 // convert from I/O Kit SC to mbuf SC 2599 switch (serviceClass) 2600 { 2601 case kIOMbufServiceClassBE: mbufSC = MBUF_SC_BE; break; 2602 case kIOMbufServiceClassBKSYS: mbufSC = MBUF_SC_BK_SYS; break; 2603 case kIOMbufServiceClassBK: mbufSC = MBUF_SC_BK; break; 2604 case kIOMbufServiceClassRD: mbufSC = MBUF_SC_RD; break; 2605 case kIOMbufServiceClassOAM: mbufSC = MBUF_SC_OAM; break; 2606 case kIOMbufServiceClassAV: mbufSC = MBUF_SC_AV; break; 2607 case kIOMbufServiceClassRV: mbufSC = MBUF_SC_RV; break; 2608 case kIOMbufServiceClassVI: mbufSC = MBUF_SC_VI; break; 2609 case kIOMbufServiceClassVO: mbufSC = MBUF_SC_VO; break; 2610 case kIOMbufServiceClassCTL: mbufSC = MBUF_SC_CTL; break; 2611 default: 2612 return kIOReturnBadArgument; 2613 } 2614 2615 if (maxCount == 1) 2616 { 2617 error = ifnet_dequeue_service_class( 2618 _backingIfnet, mbufSC, packetHead); 2619 if (!error) 2620 { 2621 if (packetTail) 2622 *packetTail = *packetHead; 2623 if (packetCount) 2624 *packetCount = 1; 2625 txByteCount = mbuf_pkthdr_len(*packetHead); 2626 } 2627 } 2628 else 2629 { 2630 error = ifnet_dequeue_service_class_multi( 2631 _backingIfnet, mbufSC, maxCount, 2632 packetHead, packetTail, packetCount, &txByteCount); 2633 } 2634 if (error) 2635 goto no_frames; 2636 2637 // feed output tap 2638 if (_outputFilterFunc) 2639 { 2640 mbuf_t m, n; 2641 2642 m = *packetHead; 2643 assert(m); 2644 assert((mbuf_flags(m) & MBUF_PKTHDR)); 2645 2646 for (n = m; n != 0; n = mbuf_nextpkt(n)) 2647 feedPacketOutputTap(n); 2648 } 2649 2650 if (_txThreadSignal != _txThreadSignalLast) 2651 { 2652 // Update the stats that the driver maintains 2653 temp = _driverStats.outputErrors; 2654 delta = temp - _lastDriverStats.outputErrors; 2655 if (delta) 2656 { 2657 txErrors = ABS(delta); 2658 _lastDriverStats.outputErrors = temp; 2659 } 2660 2661 temp = _driverStats.outputPackets; 2662 delta = temp - _lastDriverStats.outputPackets; 2663 txPackets = ABS(delta); 2664 _lastDriverStats.outputPackets = temp; 2665 _txThreadSignalLast = _txThreadSignal; 2666 } 2667 2668 // update interface output byte count 2669 ifnet_stat_increment_out(_backingIfnet, txPackets, txByteCount, txErrors); 2670 if (packetBytes) 2671 *packetBytes = txByteCount; 2672 2673 return kIOReturnSuccess; 2674 2675no_frames: 2676 *packetHead = 0; 2677 if (packetTail) 2678 packetTail = 0; 2679 if (packetCount) 2680 packetCount = 0; 2681 if (packetBytes) 2682 packetBytes = 0; 2683 return kIOReturnNoFrames; 2684} 2685 2686//------------------------------------------------------------------------------ 2687 2688void IONetworkInterface::signalOutputThread( IOOptionBits options ) 2689{ 2690 // Unconditionally signal completion, to trigger drain loop retry 2691 UInt32 old = OSBitOrAtomic(kTxThreadWakeupSignal, &_txThreadFlags); 2692 2693 // Interface detached from network stack 2694 if (_txThreadState & (kTxThreadStateInit | kTxThreadStateDetach)) 2695 { 2696 return; 2697 } 2698 2699 // Only wake if_start thread if drain loop left wakeup enabled 2700 if ((old & kTxThreadWakeupMask) == kTxThreadWakeupEnable) 2701 { 2702 assert(_backingIfnet); 2703 ifnet_start(_backingIfnet); 2704 } 2705 2706 _txThreadSignal++; 2707} 2708 2709//------------------------------------------------------------------------------ 2710 2711IOReturn IONetworkInterface::startOutputThread( IOOptionBits options ) 2712{ 2713 const uint32_t mask = (kTxThreadStateHalted | kTxThreadStateStop); 2714 IOReturn error = kIOReturnUnsupported; 2715 bool purge = false; 2716 2717 DLOG("%s: %s(0x%x)\n", 2718 getName(), __FUNCTION__, _txThreadState); 2719 2720 IOLockLock(_privateLock); 2721 if (_txThreadState & kTxThreadStateDetach) 2722 { 2723 error = kIOReturnNotAttached; 2724 } 2725 else 2726 { 2727 error = kIOReturnSuccess; 2728 purge = ((_txThreadState & kTxThreadStatePurge) != 0); 2729 _txThreadState &= ~kTxThreadStatePurge; 2730 2731 if (_txThreadState & mask) 2732 { 2733 _txThreadState &= ~mask; 2734 2735 // No need to kick if_start thread if it hasn't called us yet. 2736 // This safety check covers the time before ifnet_attach. 2737 2738 if ((_txThreadState & kTxThreadStateInit) == 0) 2739 { 2740 assert(_backingIfnet); 2741 if (purge) 2742 ifnet_purge(_backingIfnet); 2743 ifnet_start(_backingIfnet); 2744 } 2745 } 2746 } 2747 IOLockUnlock(_privateLock); 2748 2749 return error; 2750} 2751 2752//------------------------------------------------------------------------------ 2753 2754IOReturn IONetworkInterface::haltOutputThread( uint32_t stateBit ) 2755{ 2756 AbsoluteTime deadline; 2757 uint32_t count = 0; 2758 const uint32_t timeout = 100; 2759 IOReturn error = kIOReturnSuccess; 2760 2761 DLOG("%s: %s(0x%x, 0x%x)\n", 2762 getName(), __FUNCTION__, _txThreadState, stateBit); 2763 2764 IOLockLock(_privateLock); 2765 2766 do { 2767 // Prevent queue enable while we drop the lock 2768 _txThreadState |= (stateBit & kTxThreadStateDetach); 2769 _txThreadState &= ~kTxThreadStatePurge; 2770 2771 // Already halted, thread may have terminated 2772 if (_txThreadState & kTxThreadStateHalted) 2773 break; 2774 2775 if (!_txStartThread) 2776 { 2777 // Before the initial if_start call. Can update state directly 2778 // since this thread holds the lock that blocks if_start. 2779 _txThreadState |= kTxThreadStateHalted; 2780 break; 2781 } 2782 2783 // if_start thread cannot call us without ifnet attach 2784 assert(_backingIfnet); 2785 2786 if (current_thread() == _txStartThread) 2787 { 2788 // Driver called stop from if_start context 2789 _txThreadState |= kTxThreadStateHalted; 2790 break; 2791 } 2792 2793 if (_txWorkLoop && _txWorkLoop->inGate()) 2794 { 2795 // stopped from gated context 2796 _txThreadState |= kTxThreadStateHalted; 2797 break; 2798 } 2799 2800 // Wait for halt confirmation from if_start thread 2801 while ((_txThreadState & kTxThreadStateHalted) == 0) 2802 { 2803 if (count) 2804 { 2805 LOG("%s: %s(0x%x, 0x%x) retry %u\n", 2806 getName(), __FUNCTION__, _txThreadState, stateBit, count); 2807 if (count >= timeout) 2808 { 2809 error = kIOReturnTimeout; 2810 break; 2811 } 2812 } 2813 2814 _txThreadState |= stateBit; 2815 clock_interval_to_deadline(100, kMillisecondScale, &deadline); 2816 ifnet_start(_backingIfnet); 2817 IOLockSleepDeadline(_privateLock, &_txThreadState, 2818 deadline, THREAD_UNINT); 2819 count++; 2820 } 2821 } while (false); 2822 2823 IOLockUnlock(_privateLock); 2824 2825 DLOG("%s: %s(0x%x, 0x%x) done after %u try\n", 2826 getName(), __FUNCTION__, _txThreadState, stateBit, count); 2827 2828 return error; 2829} 2830 2831IOReturn IONetworkInterface::stopOutputThread( IOOptionBits options ) 2832{ 2833 return haltOutputThread( kTxThreadStateStop ); 2834} 2835 2836//------------------------------------------------------------------------------ 2837 2838void IONetworkInterface::flushOutputQueue( IOOptionBits options ) 2839{ 2840 DLOG("%s: %s(0x%x)\n", 2841 getName(), __FUNCTION__, _txThreadState); 2842 2843 IOLockLock(_privateLock); 2844 // synchronized with interface detach 2845 if (_backingIfnet && ((_txThreadState & kTxThreadStateDetach) == 0)) 2846 { 2847 // Drop new packets if output thread stopped 2848 if (_txThreadState & kTxThreadStateHalted) 2849 _txThreadState |= kTxThreadStatePurge; 2850 2851 ifnet_purge(_backingIfnet); 2852 } 2853 IOLockUnlock(_privateLock); 2854} 2855 2856//------------------------------------------------------------------------------ 2857 2858IOReturn IONetworkInterface::reportTransmitCompletionStatus( 2859 mbuf_t packet, 2860 IOReturn status, 2861 uint32_t param1 __unused, 2862 uint32_t param2 __unused, 2863 IOOptionBits options __unused ) 2864{ 2865 errno_t error = ifnet_tx_compl_status(getIfnet(), packet, status); 2866 return (error) ? kIOReturnError : kIOReturnSuccess; 2867} 2868 2869//------------------------------------------------------------------------------ 2870// Stack-poll input model 2871//------------------------------------------------------------------------------ 2872 2873IOReturn IONetworkInterface::configureInputPacketPolling( 2874 uint32_t driverQueueSize, 2875 IOOptionBits options ) 2876{ 2877 IOReturn ret = kIOReturnError; 2878 2879 IOLockLock(_privateLock); 2880 if ((_configFlags & kConfigFrozen) == 0) 2881 { 2882 _rxRingSize = driverQueueSize; 2883 _rxPollOptions = options; 2884 _configFlags |= kConfigRxPoll; 2885 ret = kIOReturnSuccess; 2886 } 2887 IOLockUnlock(_privateLock); 2888 return ret; 2889} 2890 2891void IONetworkInterface::if_input_poll( 2892 ifnet_t ifp, 2893 uint32_t flags, 2894 uint32_t max_count, 2895 mbuf_t * first_packet, 2896 mbuf_t * last_packet, 2897 uint32_t * cnt, 2898 uint32_t * len ) 2899{ 2900 IONetworkInterface * me = IFNET_TO_THIS(ifp); 2901 IONetworkController * driver; 2902 IOMbufQueue queue; 2903 2904 assert(ifp == me->_backingIfnet); 2905 assert(max_count != 0); 2906 2907 driver = me->_driver; 2908 assert(driver); 2909 if (__builtin_expect(!driver, 0)) 2910 { 2911 return; 2912 } 2913 2914 me->_rxPollTotal++; 2915 2916 IOMbufQueueInit(&queue); 2917 2918 driver->pollInputPackets(me, max_count, &queue, 0); 2919 2920 if (!IOMbufQueueIsEmpty(&queue)) 2921 { 2922 *first_packet = queue.head; 2923 *last_packet = queue.tail; 2924 *cnt = queue.count; 2925 *len = queue.bytes; 2926 } 2927 else 2928 { 2929 me->_rxPollEmpty++; 2930 *first_packet = 0; 2931 *last_packet = 0; 2932 *cnt = 0; 2933 *len = 0; 2934 } 2935} 2936 2937void IONetworkInterface::if_input_poll_gated( 2938 ifnet_t ifp, 2939 uint32_t flags, 2940 uint32_t max_count, 2941 mbuf_t * first_packet, 2942 mbuf_t * last_packet, 2943 uint32_t * cnt, 2944 uint32_t * len ) 2945{ 2946 IONetworkInterface * me = IFNET_TO_THIS(ifp); 2947 IONetworkController * driver; 2948 IOMbufQueue queue; 2949 2950 assert(ifp == me->_backingIfnet); 2951 assert(max_count != 0); 2952 2953 driver = me->_driver; 2954 assert(driver); 2955 if (__builtin_expect(!driver, 0)) 2956 { 2957 return; 2958 } 2959 2960 me->_rxPollTotal++; 2961 2962 IOMbufQueueInit(&queue); 2963 2964 driver->executeCommand( 2965 /* client */ me, 2966 /* action */ (IONetworkController::Action) me->_rxPollAction, 2967 /* target */ driver, 2968 /* param0 */ me, 2969 /* param1 */ (void *)(uintptr_t) max_count, 2970 /* param2 */ &queue, 2971 /* param3 */ 0 ); 2972 2973 if (!IOMbufQueueIsEmpty(&queue)) 2974 { 2975 *first_packet = queue.head; 2976 *last_packet = queue.tail; 2977 *cnt = queue.count; 2978 *len = queue.bytes; 2979 } 2980 else 2981 { 2982 me->_rxPollEmpty++; 2983 *first_packet = 0; 2984 *last_packet = 0; 2985 *cnt = 0; 2986 *len = 0; 2987 } 2988} 2989 2990IOReturn IONetworkInterface::setPacketPollingParameters( 2991 const IONetworkPacketPollingParameters * params, 2992 IOOptionBits options ) 2993{ 2994 struct ifnet_poll_params ifParams; 2995 errno_t error; 2996 2997 if (!params) 2998 return kIOReturnBadArgument; 2999 if (!_backingIfnet) 3000 return kIOReturnNotAttached; 3001 3002 bzero(&ifParams, sizeof(ifParams)); 3003 ifParams.flags = options; 3004 ifParams.packets_limit = params->maxPacketCount; 3005 ifParams.packets_lowat = params->lowThresholdPackets; 3006 ifParams.packets_hiwat = params->highThresholdPackets; 3007 ifParams.bytes_lowat = params->lowThresholdBytes; 3008 ifParams.bytes_hiwat = params->highThresholdBytes; 3009 ifParams.interval_time = params->pollIntervalTime; 3010 3011 error = ifnet_set_poll_params(_backingIfnet, &ifParams); 3012 return errnoToIOReturn(error); 3013} 3014 3015//------------------------------------------------------------------------------ 3016 3017IOReturn IONetworkInterface::enqueueInputPacket( 3018 mbuf_t packet, 3019 IOMbufQueue * queue, 3020 IOOptionBits options ) 3021{ 3022 const uint32_t hdrlen = _hdrlen; 3023 void * mdata; 3024 uint32_t length; 3025 3026 assert(packet); 3027 assert(_backingIfnet); 3028 3029 if (!packet) 3030 return kIOReturnBadArgument; 3031 3032 if (!_backingIfnet) 3033 { 3034 mbuf_freem(packet); 3035 return kIOReturnNotAttached; 3036 } 3037 3038 if (!queue) 3039 { 3040 // use the push model queue 3041 queue = _inputPushQueue; 3042 } 3043 3044 assert((mbuf_flags(packet) & MBUF_PKTHDR)); 3045 assert((mbuf_nextpkt(packet) == 0)); 3046 3047 mbuf_pkthdr_setrcvif(packet, _backingIfnet); 3048 3049 length = mbuf_pkthdr_len(packet); 3050 assert(length != 0); 3051 3052 // check for special debugger packet 3053 if (_remote_NMI_len) { 3054 const char *data = get_icmp_data(&packet, hdrlen, _remote_NMI_len); 3055 3056 if (data && (memcmp(data, _remote_NMI_pattern, _remote_NMI_len) == 0)) { 3057 IOKernelDebugger::signalDebugger(); 3058 } 3059 } 3060 3061 // input BPF tap 3062 if (_inputFilterFunc) 3063 feedPacketInputTap(packet); 3064 3065 // frame header at start of mbuf data 3066 mdata = mbuf_data(packet); 3067 mbuf_pkthdr_setheader(packet, mdata); 3068 3069 // packet header length does not include the frame header 3070 mbuf_pkthdr_setlen(packet, length - hdrlen); 3071 3072 // adjust the mbuf data and length to exclude the frame header 3073 mbuf_setdata(packet, (char *)mdata + hdrlen, mbuf_len(packet) - hdrlen); 3074 3075 IOMbufQueueTailAdd(queue, packet, length); 3076 return kIOReturnSuccess; 3077} 3078 3079//------------------------------------------------------------------------------ 3080 3081errno_t IONetworkInterface::if_input_ctl( ifnet_t ifp, 3082 ifnet_ctl_cmd_t cmd, 3083 u_int32_t arglen, 3084 void * arg ) 3085{ 3086 IONetworkInterface * me = IFNET_TO_THIS(ifp); 3087 IONetworkController * driver; 3088 3089 assert(ifp == me->_backingIfnet); 3090 3091 driver = me->_driver; 3092 assert(driver); 3093 if (!driver) 3094 { 3095 return 0; 3096 } 3097 3098 driver->executeCommand( 3099 /* client */ me, 3100 /* action */ (IONetworkController::Action) me->_rxCtlAction, 3101 /* target */ me, 3102 /* param0 */ driver, 3103 /* param1 */ (void *)(uintptr_t) cmd, 3104 /* param2 */ (void *)(uintptr_t) arglen, 3105 /* param3 */ arg ); 3106 3107 return 0; 3108} 3109 3110void IONetworkInterface::actionInputCtl( IONetworkController * driver, 3111 ifnet_ctl_cmd_t cmd, 3112 uint32_t arglen, 3113 void * arg ) 3114{ 3115 ifnet_model_params * params = (ifnet_model_params *) arg; 3116 3117 switch (cmd) 3118 { 3119 case IFNET_CTL_SET_INPUT_MODEL: 3120 if (arglen != sizeof(ifnet_model_params)) 3121 { 3122 LOG("%s: SET_INPUT_MODEL bad params size %u != %u\n", 3123 getName(), arglen, (uint32_t) sizeof(ifnet_model_params)); 3124 } 3125 else if ((params->model != IFNET_MODEL_INPUT_POLL_OFF) && 3126 (params->model != IFNET_MODEL_INPUT_POLL_ON)) 3127 { 3128 LOG("%s: SET_INPUT_MODEL unknown model 0x%x\n", 3129 getName(), params->model); 3130 } 3131 else if (params->model != _rxPollModel) 3132 { 3133 // IFNET_MODEL_INPUT_POLL_OFF 3134 // IFNET_MODEL_INPUT_POLL_ON 3135 _rxPollModel = params->model; 3136 DLOG("%s: SET_INPUT_MODEL 0x%x\n", getName(), _rxPollModel); 3137 DLOG("%s: poll cnt %llu, empty %llu\n", getName(), 3138 _rxPollTotal, _rxPollEmpty); 3139 _rxPollEmpty = 0; 3140 _rxPollTotal = 0; 3141 3142 driver->setInputPacketPollingEnable( 3143 this, _rxPollModel == IFNET_MODEL_INPUT_POLL_ON ); 3144 } 3145 break; 3146 3147 case IFNET_CTL_GET_INPUT_MODEL: 3148 if (arglen != sizeof(ifnet_model_params)) 3149 { 3150 LOG("%s: GET_INPUT_MODEL bad params size %u != %u\n", 3151 getName(), arglen, (uint32_t) sizeof(ifnet_model_params)); 3152 } 3153 else 3154 { 3155 params->model = _rxPollModel; 3156 } 3157 break; 3158 3159 default: 3160 DLOG("%s: if_input_ctl unknown cmd 0x%x\n", getName(), cmd); 3161 } 3162} 3163 3164//------------------------------------------------------------------------------ 3165 3166errno_t IONetworkInterface::if_output_ctl( ifnet_t ifp, 3167 ifnet_ctl_cmd_t cmd, 3168 u_int32_t arglen, 3169 void * arg ) 3170{ 3171 IONetworkInterface * me = IFNET_TO_THIS(ifp); 3172 IONetworkController * driver; 3173 errno_t error = ENOTSUP; 3174 bool changed = false; 3175 3176 assert(ifp == me->_backingIfnet); 3177 3178 driver = me->_driver; 3179 assert(driver); 3180 if (!driver) 3181 { 3182 return ENODEV; 3183 } 3184 3185 if (cmd == IFNET_CTL_SET_LOG) 3186 { 3187 if (arg && (arglen == sizeof(struct ifnet_log_params))) 3188 { 3189 const struct ifnet_log_params * lp = 3190 (const struct ifnet_log_params *) arg; 3191 3192 IONetworkInterfaceLoggingParameters params; 3193 3194 IOLockLock(me->_privateLock); 3195 3196 if (me->_loggingLevel != lp->level) 3197 changed = true; 3198 3199 me->_loggingLevel = lp->level; 3200 3201 IOLockUnlock(me->_privateLock); 3202 error = 0; 3203 3204 bzero(¶ms, sizeof(params)); 3205 params.level = lp->level; 3206 params.flags = lp->flags; 3207 params.category = lp->category; 3208 params.subCategory = lp->subcategory; 3209 me->notifyDriver(kIONetworkNotificationLoggingParametersChange, 3210 ¶ms); 3211 } 3212 else 3213 { 3214 error = EINVAL; 3215 } 3216 3217 if (changed) 3218 me->notifyDriver(kIONetworkNotificationLoggingLevelChange, 0); 3219 } 3220 else if (cmd == IFNET_CTL_NOTIFY_ADDRESS) 3221 { 3222 if (arg && (arglen == sizeof(struct ifnet_notify_address_params))) 3223 { 3224 const struct ifnet_notify_address_params * ap = 3225 (const struct ifnet_notify_address_params *) arg; 3226 3227 IONetworkInterfaceAddressChangeParameters params; 3228 3229 bzero(¶ms, sizeof(params)); 3230 params.addressFamily = ap->address_family; 3231 me->notifyDriver(kIONetworkNotificationInterfaceAddressChange, 3232 ¶ms); 3233 } 3234 else 3235 { 3236 error = EINVAL; 3237 } 3238 } 3239 3240 return error; 3241} 3242 3243//------------------------------------------------------------------------------ 3244 3245bool IONetworkInterface::isBPFTapEnabled( IOOptionBits options __unused ) const 3246{ 3247 bool enabled; 3248 3249 IOLockLock(_privateLock); 3250 enabled = (_inputFilterFunc != 0); 3251 IOLockUnlock(_privateLock); 3252 return enabled; 3253} 3254 3255int32_t IONetworkInterface::getLoggingLevel( IOOptionBits options __unused ) const 3256{ 3257 int32_t level; 3258 3259 IOLockLock(_privateLock); 3260 level = _loggingLevel; 3261 IOLockUnlock(_privateLock); 3262 return level; 3263} 3264 3265void IONetworkInterface::notifyDriver( uint32_t notifyType, void * data ) 3266{ 3267 if (_driver) 3268 _driver->networkInterfaceNotification(this, notifyType, data); 3269} 3270 3271//------------------------------------------------------------------------------ 3272 3273IOReturn IONetworkInterface::errnoToIOReturn( errno_t error ) 3274{ 3275 switch (error) 3276 { 3277 case 0: 3278 return kIOReturnSuccess; 3279 case EINVAL: 3280 return kIOReturnBadArgument; 3281 case ENOMEM: 3282 return kIOReturnNoMemory; 3283 case EPERM: 3284 return kIOReturnNotPermitted; 3285 case EACCES: 3286 return kIOReturnNotPrivileged; 3287 case ENOTSUP: 3288 return kIOReturnUnsupported; 3289 case EBUSY: 3290 return kIOReturnBusy; 3291 case ETIMEDOUT: 3292 return kIOReturnTimeout; 3293 default: 3294 return kIOReturnError; 3295 } 3296} 3297 3298IOReturn IONetworkInterface::reportDatapathIssue( 3299 IOReturn issue, 3300 void * data __unused, 3301 IOByteCount length __unused ) 3302{ 3303 errno_t error; 3304 3305 // SHA-1 hash of com.apple.iokit.IONetworkingFamily 3306 static const uint8_t modid[DLIL_MODIDLEN] = { 3307 0xe3, 0x26, 0x1e, 0x7d, 0xf2, 0x15, 0xf1, 0x3d, 0x9d, 0x9d, 3308 0xbc, 0x1f, 0x75, 0x4d, 0xa5, 0xa4, 0x1c, 0xac, 0x2a, 0xab }; 3309 3310 union { 3311 uint8_t errorData[ DLIL_MODARGLEN ]; 3312 IOReturn errorCode; 3313 } issueInfo; 3314 3315 bzero(&issueInfo, sizeof(issueInfo)); 3316 issueInfo.errorCode = issue; 3317 3318 error = ifnet_report_issues(getIfnet(), (uint8_t *) modid, issueInfo.errorData); 3319 3320 return errnoToIOReturn(error); 3321} 3322