Annotation of XNU/iokit/Families/IONetworking/IONetworkStack.cpp, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1998-2000 Apple Computer, 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:  * Copyright (c) 1999 Apple Computer, Inc.  All rights reserved. 
                     24:  *
                     25:  * IONetworkStack.cpp - An IOKit proxy for the BSD network stack.
                     26:  *
                     27:  * HISTORY
                     28:  *
                     29:  * IONetworkStack abstracts certain essential network stack services.
                     30:  * Those services include attaching/detaching network interfaces, and
                     31:  * interface naming. Note that although BSD network stack does not assign
                     32:  * interface names, it is the responsibility of this object to manage the
                     33:  * interface name space.
                     34:  *
                     35:  * IONetworkStack is a client of IONetworkInterface. This object uses the
                     36:  * standard IOKit matching mechanism to discover and attach to interface
                     37:  * objects. Each interface object is expected to have only a single
                     38:  * IONetworkStack client. Under IOKit, the stack object initiates the
                     39:  * action to attach to an interface. And subsequently, detaches from an
                     40:  * interface when signaled to do so.
                     41:  *
                     42:  * The packet flow bypasses this object for efficiency sake. The interface
                     43:  * object interact directly with the 'real' network stack to send and
                     44:  * receive packets.
                     45:  */
                     46: 
                     47: #include <IOKit/assert.h>
                     48: #include <IOKit/IOLib.h>
                     49: #include <IOKit/IOBSD.h>
                     50: #include <IOKit/IOMessage.h>
                     51: #include <IOKit/network/IONetworkInterface.h>
                     52: #include <IOKit/network/IONetworkController.h>
                     53: #include "IONetworkStack.h"
                     54: 
                     55: extern "C" {
                     56: #include <sys/param.h>
                     57: #include <sys/mbuf.h>
                     58: #include <sys/socket.h>
                     59: #include <net/bpf.h>
                     60: #include <net/if.h>
                     61: #include <netinet/if_ether.h>
                     62: }
                     63: 
                     64: #define super IOService
                     65: 
                     66: OSDefineMetaClassAndStructorsWithInit( IONetworkStack,
                     67:                                        IOService,
                     68:                                        IONetworkStack::initialize())
                     69: 
                     70: #ifdef  DEBUG
                     71: #define DLOG(fmt, args...)  IOLog(fmt, ## args)
                     72: #else
                     73: #define DLOG
                     74: #endif
                     75: 
                     76: // Maintain a linked list of network interfaces.
                     77: // Each time a new interface is added, an unit number is assigned,
                     78: // and an interface entry is added to the list. When the interface
                     79: // goes away, the entry is removed from the list and deallocated.
                     80: //
                     81: static queue_head_t         netifTable;
                     82: static IOLock *             netifTableLock;
                     83: 
                     84: typedef struct {
                     85:     IONetworkInterface *    netif;
                     86:     const char *            name;
                     87:     short                   unit;
                     88:     queue_chain_t           link;
                     89: } netifEntry;
                     90: 
                     91: #define BSD_IFNET_ENTRY     ((IONetworkInterface *) 0)
                     92: #define NETIF_LOCK          IOTakeLock(netifTableLock)
                     93: #define NETIF_UNLOCK        IOUnlock(netifTableLock)
                     94: 
                     95: #define LOCK                IOTakeLock(_lock);
                     96: #define UNLOCK              IOUnlock(_lock);
                     97: 
                     98: // --------------------------------------------------------------------------
                     99: //
                    100: // Add a new entry to the netifTable for the interface 'netif'.
                    101: // Return true if the entry was added successfully, otherwise
                    102: // returns false.
                    103: //
                    104: // The table lock must be held by the caller of this function.
                    105: //
                    106: static bool addNetworkInterfaceEntry(IONetworkInterface * netif,
                    107:                                      const char *         name,
                    108:                                      short                unit)
                    109: {
                    110:     if (!netif || !name || (unit < 0)) return false;
                    111: 
                    112:     netifEntry * entry = (netifEntry *) IOMalloc(sizeof(netifEntry));
                    113:     if (!entry)
                    114:         return false;
                    115:     bzero(entry, sizeof(*entry));
                    116: 
                    117:     entry->netif = netif;
                    118:     entry->unit  = unit;
                    119:     entry->name  = name;
                    120: 
                    121:     queue_enter(&netifTable, entry, netifEntry *, link);
                    122: 
                    123:     return true;
                    124: }
                    125: 
                    126: // --------------------------------------------------------------------------
                    127: //
                    128: // Release the table entry occupied by the 'netif' instance.
                    129: // Returns true if an entry was found and removed, otherwise
                    130: // return false.
                    131: //
                    132: static bool releaseNetworkInterfaceEntry(IONetworkInterface * netif)
                    133: {
                    134:     netifEntry * foundEntry = 0;
                    135: 
                    136:     if (!netif) return false;
                    137: 
                    138:     NETIF_LOCK;
                    139:     if (!queue_empty(&netifTable)) {
                    140:         netifEntry * entry;
                    141:         queue_iterate(&netifTable, entry, netifEntry *, link) {
                    142:             if (entry->netif == netif) {
                    143:                 foundEntry = entry;
                    144:                 break;
                    145:             }
                    146:         }
                    147:     }
                    148:     if (foundEntry) {
                    149:         queue_remove(&netifTable, foundEntry, netifEntry *, link);
                    150:         IOFree(foundEntry, sizeof(*foundEntry));
                    151:     }
                    152:     NETIF_UNLOCK;
                    153: 
                    154:     return (foundEntry ? true : false);
                    155: }
                    156: 
                    157: // --------------------------------------------------------------------------
                    158: //
                    159: // Initialize the table, and preload it with any existing BSD network
                    160: // interfaces.
                    161: //
                    162: static void initNetifTable()
                    163: {
                    164:     netifTableLock = IOLockAlloc();
                    165:     assert(netifTableLock);
                    166: 
                    167:     IOLockInitWithState(netifTableLock, kIOLockStateUnlocked);
                    168: 
                    169:     queue_init(&netifTable);
                    170: 
                    171:     // Insert entries for all existing 'BSD' network interfaces into the 
                    172:     // netifTable. Hopefully only lo0 will be found.
                    173:     //
                    174: #if 1   // FreeBSD 3.2
                    175:     for (struct ifnet * ifp = ifnet.tqh_first;
                    176:          ifp;
                    177:          ifp = ifp->if_link.tqe_next)
                    178:         addNetworkInterfaceEntry(BSD_IFNET_ENTRY, ifp->if_name, ifp->if_unit);
                    179: #else
                    180:     for (struct ifnet * ifp = ifnet; ifp; ifp = ifp->if_next)
                    181:         addNetworkInterfaceEntry(BSD_IFNET_ENTRY, ifp->if_name, ifp->if_unit);
                    182: #endif
                    183: }
                    184: 
                    185: // --------------------------------------------------------------------------
                    186: //
                    187: // Add a entry for the interface object 'netif', with name prefix 'name'.
                    188: // The chosen unit number is returned in 'unit'. Returns true on success.
                    189: //
                    190: static bool reserveNetworkInterfaceEntry(IONetworkInterface * netif,
                    191:                                          const char *         name,
                    192:                                          short *              unit)
                    193: {
                    194:     bool ret = true;
                    195:     bool addEntry = true;   // add new entry to list.
                    196:     bool error = false;
                    197: 
                    198:     if (!netif || !name || !unit || (*unit < 0)) return false;
                    199: 
                    200:     NETIF_LOCK;
                    201: 
                    202:     if (!queue_empty(&netifTable)) {
                    203:         bool rescan;
                    204:         netifEntry * entry;
                    205: 
                    206:         do {
                    207:             rescan = false;
                    208:             
                    209:             // Scan through the interface list and search for duplicates
                    210:             // and conflicts. If a conflict is found, increment the unit
                    211:             // number and rescan.
                    212:             //
                    213:             queue_iterate(&netifTable, entry, netifEntry *, link) {
                    214:                 if (entry->netif == netif) {    // can't have duplicates
                    215:                     addEntry = false;           // re-use existing entry
                    216:                     *unit = entry->unit;
                    217:                     break;
                    218:                 }
                    219:                 if ((entry->unit == *unit) && !strcmp(entry->name, name)) {
                    220:                     // name conflict detected.
                    221:                     if (++(*unit) > 0)
                    222:                         rescan = true;
                    223:                     else
                    224:                         error = true;
                    225:                     break;
                    226:                 }
                    227:             }
                    228:         } while (rescan);
                    229:     }
                    230: 
                    231:     if (error)
                    232:         ret = false;
                    233:     else if (addEntry)
                    234:         ret = addNetworkInterfaceEntry(netif, name, *unit);
                    235: 
                    236:     NETIF_UNLOCK;
                    237: 
                    238:     return ret;
                    239: }
                    240: 
                    241: // --------------------------------------------------------------------------
                    242: //
                    243: // IONetworkStack class initializer.
                    244: 
                    245: void IONetworkStack::initialize()
                    246: {
                    247:     initNetifTable();
                    248: }
                    249: 
                    250: // --------------------------------------------------------------------------
                    251: //
                    252: // init method.
                    253: 
                    254: bool IONetworkStack::init(OSDictionary * properties)
                    255: {
                    256:     _netif = 0;     // IONetworkInterface instance (provider).
                    257:     _ifp   = 0;     // ifnet struct for the interface.
                    258:     _lock  = 0;     // big serialization lock.
                    259:     _state = kIONetworkStackStateInit;  // default state.
                    260: 
                    261:     if (!super::init())
                    262:         return false;
                    263: 
                    264:     // Allocate a lock which will protect all accesses to this object.
                    265:     //
                    266:     _lock = IOLockAlloc();
                    267:     if (!_lock)
                    268:         return false;
                    269: 
                    270:     return true;
                    271: }
                    272: 
                    273: // --------------------------------------------------------------------------
                    274: //
                    275: // probe. the score forces the probe and start in IONetworkStack to occur
                    276: // before the notification from IONetworkInterface is sent. We need to delay
                    277: // that until the network stack object has assigned a BSD name to the
                    278: // interface.
                    279: 
                    280: IOService * IONetworkStack::probe(IOService * provider,
                    281:                                   SInt32 *    score)
                    282: {
                    283:     if (!super::probe(provider, score))
                    284:         return 0;
                    285: 
                    286:     // We are not picky about our provider, but it must be an
                    287:     // IONetworkInterface instance.
                    288:     //
                    289:     IONetworkInterface * netif = OSDynamicCast(IONetworkInterface, provider);
                    290:     if (!netif)
                    291:         return 0;
                    292: 
                    293:     *score = 32;    // must be larger than notification score.
                    294:     
                    295:     // Query interface for any requirements before qualifying the probe.
                    296:     // For now, there is nothing that needs to be done. Return 'this' to
                    297:     // indicate successful probe.
                    298: 
                    299:     return this;
                    300: }
                    301: 
                    302: // --------------------------------------------------------------------------
                    303: //
                    304: // start method. We have attached to our provider, now start ourselve up.
                    305: 
                    306: bool IONetworkStack::start(IOService * provider)
                    307: {
                    308:     IONetworkInterface * netif = OSDynamicCast(IONetworkInterface, provider);
                    309:     bool                 ret    = false;
                    310:     bool                 opened = false;
                    311: 
                    312:     if (!netif) return false;
                    313: 
                    314:     LOCK;
                    315: 
                    316:     do {
                    317:         // Catch illegal state transitions.
                    318:         //
                    319:         if (_state != kIONetworkStackStateInit)
                    320:             break;
                    321: 
                    322:         // Our provider must reveal its ifnet structure.
                    323:         //
                    324:         _netif = netif;
                    325:         _ifp   = _netif->getIfnet();
                    326:         if (!_ifp || (_netif != (IONetworkInterface *) _ifp->if_private))
                    327:             break;
                    328: 
                    329:         // Pass start() to our superclass.
                    330:         //
                    331:         if (!super::start(provider))
                    332:             break;
                    333: 
                    334:         // Open our provider.
                    335:         //
                    336:         if (!_netif->open(this))
                    337:             break;
                    338:         opened = true;
                    339: 
                    340:         // Assign a name for the interface. Must do this before the
                    341:         // if_attach() call. Remember to release the OSString object
                    342:         // obtained through this call.
                    343:         //
                    344:         OSString * ifname = _assignInterfaceName(_netif);
                    345:         if (!ifname) {
                    346:             releaseNetworkInterfaceEntry(_netif);
                    347:             break;
                    348:         }
                    349:         ifname->release();
                    350: 
                    351:         // When IONetworkStack gets probed, we assume that BSD is already
                    352:         // up and running. So it is safe to call BSD to attach the network 
                    353:         // interface.
                    354:         //
                    355:         // FIXME: This will only work with Ethernet interfaces. Switch to
                    356:         // new DLIL API once that is available.
                    357:         //
                    358:         _netif->lock();
                    359: 
                    360:         // Set the if_free() function pointer in the ifnet to point to our
                    361:         // detachCallBack() static function.
                    362:         //
                    363:         // _ifp->if_free  = detachCallBackHandler;
                    364:         // _netif->_stack = this;
                    365: 
                    366: #if 1   // FreeBSD 3.2
                    367:         bpfattach(_ifp, DLT_EN10MB,sizeof(struct ether_header));
                    368: #else
                    369:         bpfattach(&_ifp->if_bpf, _ifp, DLT_EN10MB,sizeof(struct ether_header));
                    370: #endif  
                    371: 
                    372:         ether_ifattach(_ifp); 
                    373:         
                    374:         _netif->unlock();
                    375: 
                    376:         // Network stack is now attached to the interface.
                    377:         //
                    378:         _state = kIONetworkStackStateAttached;
                    379: 
                    380:         ret = true;
                    381:     }
                    382:     while (0);
                    383: 
                    384:     if (!ret)
                    385:     {
                    386:         // start failed, undo any actions performed.
                    387:         //
                    388:         if (opened)
                    389:             _netif->close(this);
                    390:         
                    391:         _netif = 0;
                    392:         _ifp   = 0;
                    393:     }
                    394: 
                    395:     UNLOCK;
                    396: 
                    397:     return ret;
                    398: }
                    399: 
                    400: // --------------------------------------------------------------------------
                    401: //
                    402: // stop method.
                    403: 
                    404: void IONetworkStack::stop(IOService * provider)
                    405: {
                    406:     LOCK;
                    407: 
                    408:     // Catch an illegal stop.
                    409:     //
                    410:     assert((_state == kIONetworkStackStateInit) ||
                    411:            (_state == kIONetworkStackStateDetached));
                    412: 
                    413:     // Remove the interface from linked list.
                    414:     //
                    415:     if (_netif) {
                    416:         assert(_netif == (IONetworkInterface *) provider);
                    417:         releaseNetworkInterfaceEntry(_netif);
                    418:     }
                    419: 
                    420:     _netif = 0;
                    421:     _ifp   = 0;
                    422:     _state = kIONetworkStackStateInit;
                    423: 
                    424:     UNLOCK;
                    425:     
                    426:     super::stop(provider);
                    427: }
                    428: 
                    429: // --------------------------------------------------------------------------
                    430: //
                    431: // sendIfDetachRequest
                    432: //
                    433: // Handle a detach request from our provider and signal to the network stack 
                    434: // that the interface wishes to detach. The network stack will callback when 
                    435: // the interface is allowed to proceed with the detach. There is no hard
                    436: // limit on how soon the callback will occur.
                    437: //
                    438: // Returns true if the request was handled. Otherwise, returns false.
                    439: 
                    440: bool IONetworkStack::sendIfDetachRequest()
                    441: {
                    442:     bool ret = false;
                    443: 
                    444:     DLOG("IONetworkStack::sendIfDetachRequest() called state = %d\n", _state);
                    445: 
                    446:     LOCK;
                    447: 
                    448:     if (_state == kIONetworkStackStateAttached) {
                    449:     
                    450:         // Send a detach request to the network stack and wait for
                    451:         // a callback indicating detach operation complete.
                    452:         //
                    453:         // if_detach() is a new proposed DLIL call and does not exist yet.
                    454: 
                    455:         _state = kIONetworkStackStateDetaching;
                    456: 
                    457:         ret = true; // detach request handled.
                    458:     }
                    459:     
                    460:     UNLOCK;
                    461:     
                    462:     return ret;
                    463: }
                    464: 
                    465: // --------------------------------------------------------------------------
                    466: //
                    467: // ifDetachCallback method.
                    468: 
                    469: void IONetworkStack::ifDetachCallback()
                    470: {
                    471:     LOCK;
                    472:     
                    473:     if (_state == kIONetworkStackStateDetaching) {
                    474:         
                    475:         // We previously sent a detach request, the network stack is now
                    476:         // calling back to indicate detach completion.
                    477:         //
                    478:         assert(_netif && _ifp);
                    479: 
                    480:         // Close our provider.
                    481:         //
                    482:         _netif->close(this);
                    483:  
                    484:         // Detach is now complete.
                    485:         //
                    486:         _state = kIONetworkStackStateDetached;
                    487:     }
                    488:     else {
                    489:         DLOG("%s: Unexpected detach callback\n", getName());
                    490:     }
                    491: 
                    492:     UNLOCK;
                    493: }
                    494: 
                    495: // --------------------------------------------------------------------------
                    496: //
                    497: // This static member function is registered as the if_free() handler in
                    498: // the ifnet structure of our provider. The IONetworkStack instance is 
                    499: // discovered and its ifFreeCallback() method is called.
                    500: 
                    501: void IONetworkStack::ifDetachCallbackHandler(struct ifnet * ifp)
                    502: {
                    503:     IONetworkInterface *    netif;
                    504:     IONetworkStack *        stack;
                    505:     
                    506:     netif = OSDynamicCast(IONetworkInterface,
                    507:                           (IONetworkInterface *) ifp->if_private);
                    508:     assert(netif);
                    509: 
                    510:     netif->lockForArbitration();
                    511:     
                    512:     stack = (IONetworkStack *) netif->_client;
                    513:     if (stack)
                    514:         stack->ifDetachCallback();
                    515:     else
                    516:         DLOG("IONetworkStack: No target for ifDetachCallback\n");
                    517: 
                    518:     netif->unlockForArbitration();
                    519: }
                    520: 
                    521: // --------------------------------------------------------------------------
                    522: //
                    523: // Release allocated resources.
                    524: 
                    525: void IONetworkStack::free()
                    526: {
                    527:     assert(_state == kIONetworkStackStateInit);
                    528: 
                    529:     if (_lock)
                    530:         IOLockFree(_lock);
                    531: }
                    532: 
                    533: // --------------------------------------------------------------------------
                    534: //
                    535: // Facility provided by IOService for general purpose provider-to-client 
                    536: // notification. We catch the kIOMessageServiceIsTerminated message.
                    537: 
                    538: IOReturn IONetworkStack::message(UInt32 type, IOService * provider,
                    539:                                  void * argument = 0)
                    540: {
                    541:     // Our provider has gone into an inactive state, we should begin the
                    542:     // tear-down process by signalling the network stack to unregister
                    543:     // and detach the network interface.
                    544:     //
                    545:     // We do not look at the argument, which contains the options given
                    546:     // to the terminate() method.
                    547:     //
                    548:     if (type == kIOMessageServiceIsTerminated) {
                    549:         sendIfDetachRequest();
                    550:         return kIOReturnSuccess;
                    551:     }
                    552:     
                    553:     return kIOReturnUnsupported;
                    554: }
                    555: 
                    556: // --------------------------------------------------------------------------
                    557: //
                    558: // Assign a BSD friendly name to the network interface. The interface
                    559: // object has to assist in this process by returning its name prefix,
                    560: // i.e. "en". This routine will pick an unit number that does not
                    561: // conflict with any existing interface.
                    562: 
                    563: OSString * IONetworkStack::_assignInterfaceName(IONetworkInterface * netif)
                    564: {
                    565:     SInt16                  unit = 0;
                    566:     UInt32                  index = 0;
                    567:     const char *            namePrefix = netif->getNamePrefix();
                    568:     char                    nameBuf[40];
                    569:     OSString *              nameString;
                    570:     IONetworkController *   ctlr = OSDynamicCast(IONetworkController, 
                    571:                                                  netif->getProvider());
                    572: 
                    573:     if (!ctlr || !namePrefix || !*namePrefix)
                    574:         return 0;
                    575: 
                    576:     // First, we need to determine the initial interface unit number.
                    577:     // The current scheme needs a lot of work. Currently, motherboard
                    578:     // devices gets unit 0, while add-on PCI cards are assigned
                    579:     // unit 1 and up. Here, we need to determine whether this is an
                    580:     // onboard or a PCI network controller.
                    581:     //
                    582:     if (ctlr->getProvider()) {
                    583:             OSObject * propObject = ctlr->getProvider()->getProperty("built-in");
                    584:         
                    585:         if (!propObject) {
                    586:             propObject = ctlr->getProvider()->getProperty("AAPL,slot-name");
                    587:             if (propObject) {
                    588:                 unit = 1;   // PCI add-on card
                    589:                 
                    590:                 // If we have an index number, increment
                    591:                 // the unit by the index number.
                    592:                 // (for multiport PCI cards).
                    593:                 ctlr->doGetControllerIndex(this, &index);
                    594:                 unit += index;
                    595:             }       
                    596:         }
                    597:     }
                    598: 
                    599:     // "unit" is now the initial unit number requested by the interface.
                    600:     // If this unit number is already taken by an existing interface, we
                    601:     // will automatically increment the unit number until there are no 
                    602:     // conflicts. We don't want to confuse BSD with identical names.
                    603:     //
                    604:     // Now try to reserve the chosen name.
                    605:     //
                    606:     if (!reserveNetworkInterfaceEntry(netif, namePrefix, &unit))
                    607:         return 0;
                    608: 
                    609:     // Update the interface object with its assigned name.
                    610:     //
                    611:     sprintf(nameBuf, "%s%d", namePrefix, unit);
                    612:     nameString = OSString::withCString(nameBuf);
                    613:     if (nameString) {
                    614:         //
                    615:         // Now fill in the ifnet name fields.
                    616:         //      
                    617:         netif->setInterfaceNameInt(namePrefix);
                    618:         netif->setUnitNumberInt(unit);
                    619:         
                    620:         // Set the interface's kIOBSDName property.
                    621:         //
                    622:         netif->setProperty(kIOBSDName, nameString);
                    623:     }
                    624: 
                    625:     return nameString;
                    626: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.