Annotation of qemu/roms/ipxe/src/net/netdevice.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (C) 2006 Michael Brown <[email protected]>.
        !             3:  *
        !             4:  * This program is free software; you can redistribute it and/or
        !             5:  * modify it under the terms of the GNU General Public License as
        !             6:  * published by the Free Software Foundation; either version 2 of the
        !             7:  * License, or any later version.
        !             8:  *
        !             9:  * This program is distributed in the hope that it will be useful, but
        !            10:  * WITHOUT ANY WARRANTY; without even the implied warranty of
        !            11:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        !            12:  * General Public License for more details.
        !            13:  *
        !            14:  * You should have received a copy of the GNU General Public License
        !            15:  * along with this program; if not, write to the Free Software
        !            16:  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
        !            17:  */
        !            18: 
        !            19: FILE_LICENCE ( GPL2_OR_LATER );
        !            20: 
        !            21: #include <stdint.h>
        !            22: #include <stdlib.h>
        !            23: #include <stdio.h>
        !            24: #include <byteswap.h>
        !            25: #include <string.h>
        !            26: #include <errno.h>
        !            27: #include <config/general.h>
        !            28: #include <ipxe/if_ether.h>
        !            29: #include <ipxe/iobuf.h>
        !            30: #include <ipxe/tables.h>
        !            31: #include <ipxe/process.h>
        !            32: #include <ipxe/init.h>
        !            33: #include <ipxe/device.h>
        !            34: #include <ipxe/errortab.h>
        !            35: #include <ipxe/netdevice.h>
        !            36: 
        !            37: /** @file
        !            38:  *
        !            39:  * Network device management
        !            40:  *
        !            41:  */
        !            42: 
        !            43: /** List of network devices */
        !            44: struct list_head net_devices = LIST_HEAD_INIT ( net_devices );
        !            45: 
        !            46: /** List of open network devices, in reverse order of opening */
        !            47: static struct list_head open_net_devices = LIST_HEAD_INIT ( open_net_devices );
        !            48: 
        !            49: /** Default unknown link status code */
        !            50: #define EUNKNOWN_LINK_STATUS __einfo_error ( EINFO_EUNKNOWN_LINK_STATUS )
        !            51: #define EINFO_EUNKNOWN_LINK_STATUS \
        !            52:        __einfo_uniqify ( EINFO_EINPROGRESS, 0x01, "Unknown" )
        !            53: 
        !            54: /** Default link-down status code */
        !            55: #define ENOTCONN_LINK_DOWN __einfo_error ( EINFO_ENOTCONN_LINK_DOWN )
        !            56: #define EINFO_ENOTCONN_LINK_DOWN \
        !            57:        __einfo_uniqify ( EINFO_ENOTCONN, 0x01, "Down" )
        !            58: 
        !            59: /** Human-readable message for the default link statuses */
        !            60: struct errortab netdev_errors[] __errortab = {
        !            61:        __einfo_errortab ( EINFO_EUNKNOWN_LINK_STATUS ),
        !            62:        __einfo_errortab ( EINFO_ENOTCONN_LINK_DOWN ),
        !            63: };
        !            64: 
        !            65: /**
        !            66:  * Notify drivers of network device or link state change
        !            67:  *
        !            68:  * @v netdev           Network device
        !            69:  */
        !            70: static void netdev_notify ( struct net_device *netdev ) {
        !            71:        struct net_driver *driver;
        !            72: 
        !            73:        for_each_table_entry ( driver, NET_DRIVERS )
        !            74:                driver->notify ( netdev );
        !            75: }
        !            76: 
        !            77: /**
        !            78:  * Mark network device as having a specific link state
        !            79:  *
        !            80:  * @v netdev           Network device
        !            81:  * @v rc               Link status code
        !            82:  */
        !            83: void netdev_link_err ( struct net_device *netdev, int rc ) {
        !            84: 
        !            85:        /* Record link state */
        !            86:        netdev->link_rc = rc;
        !            87:        if ( netdev->link_rc == 0 ) {
        !            88:                DBGC ( netdev, "NETDEV %s link is up\n", netdev->name );
        !            89:        } else {
        !            90:                DBGC ( netdev, "NETDEV %s link is down: %s\n",
        !            91:                       netdev->name, strerror ( netdev->link_rc ) );
        !            92:        }
        !            93: 
        !            94:        /* Notify drivers of link state change */
        !            95:        netdev_notify ( netdev );
        !            96: }
        !            97: 
        !            98: /**
        !            99:  * Mark network device as having link down
        !           100:  *
        !           101:  * @v netdev           Network device
        !           102:  */
        !           103: void netdev_link_down ( struct net_device *netdev ) {
        !           104: 
        !           105:        /* Avoid clobbering a more detailed link status code, if one
        !           106:         * is already set.
        !           107:         */
        !           108:        if ( ( netdev->link_rc == 0 ) ||
        !           109:             ( netdev->link_rc == -EUNKNOWN_LINK_STATUS ) ) {
        !           110:                netdev_link_err ( netdev, -ENOTCONN_LINK_DOWN );
        !           111:        }
        !           112: }
        !           113: 
        !           114: /**
        !           115:  * Record network device statistic
        !           116:  *
        !           117:  * @v stats            Network device statistics
        !           118:  * @v rc               Status code
        !           119:  */
        !           120: static void netdev_record_stat ( struct net_device_stats *stats, int rc ) {
        !           121:        struct net_device_error *error;
        !           122:        struct net_device_error *least_common_error;
        !           123:        unsigned int i;
        !           124: 
        !           125:        /* If this is not an error, just update the good counter */
        !           126:        if ( rc == 0 ) {
        !           127:                stats->good++;
        !           128:                return;
        !           129:        }
        !           130: 
        !           131:        /* Update the bad counter */
        !           132:        stats->bad++;
        !           133: 
        !           134:        /* Locate the appropriate error record */
        !           135:        least_common_error = &stats->errors[0];
        !           136:        for ( i = 0 ; i < ( sizeof ( stats->errors ) /
        !           137:                            sizeof ( stats->errors[0] ) ) ; i++ ) {
        !           138:                error = &stats->errors[i];
        !           139:                /* Update matching record, if found */
        !           140:                if ( error->rc == rc ) {
        !           141:                        error->count++;
        !           142:                        return;
        !           143:                }
        !           144:                if ( error->count < least_common_error->count )
        !           145:                        least_common_error = error;
        !           146:        }
        !           147: 
        !           148:        /* Overwrite the least common error record */
        !           149:        least_common_error->rc = rc;
        !           150:        least_common_error->count = 1;
        !           151: }
        !           152: 
        !           153: /**
        !           154:  * Transmit raw packet via network device
        !           155:  *
        !           156:  * @v netdev           Network device
        !           157:  * @v iobuf            I/O buffer
        !           158:  * @ret rc             Return status code
        !           159:  *
        !           160:  * Transmits the packet via the specified network device.  This
        !           161:  * function takes ownership of the I/O buffer.
        !           162:  */
        !           163: int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf ) {
        !           164:        int rc;
        !           165: 
        !           166:        DBGC ( netdev, "NETDEV %s transmitting %p (%p+%zx)\n",
        !           167:               netdev->name, iobuf, iobuf->data, iob_len ( iobuf ) );
        !           168: 
        !           169:        /* Enqueue packet */
        !           170:        list_add_tail ( &iobuf->list, &netdev->tx_queue );
        !           171: 
        !           172:        /* Avoid calling transmit() on unopened network devices */
        !           173:        if ( ! netdev_is_open ( netdev ) ) {
        !           174:                rc = -ENETUNREACH;
        !           175:                goto err;
        !           176:        }
        !           177: 
        !           178:        /* Discard packet (for test purposes) if applicable */
        !           179:        if ( ( NETDEV_DISCARD_RATE > 0 ) &&
        !           180:             ( ( random() % NETDEV_DISCARD_RATE ) == 0 ) ) {
        !           181:                rc = -EAGAIN;
        !           182:                goto err;
        !           183:        }
        !           184: 
        !           185:        /* Transmit packet */
        !           186:        if ( ( rc = netdev->op->transmit ( netdev, iobuf ) ) != 0 )
        !           187:                goto err;
        !           188: 
        !           189:        return 0;
        !           190: 
        !           191:  err:
        !           192:        netdev_tx_complete_err ( netdev, iobuf, rc );
        !           193:        return rc;
        !           194: }
        !           195: 
        !           196: /**
        !           197:  * Complete network transmission
        !           198:  *
        !           199:  * @v netdev           Network device
        !           200:  * @v iobuf            I/O buffer
        !           201:  * @v rc               Packet status code
        !           202:  *
        !           203:  * The packet must currently be in the network device's TX queue.
        !           204:  */
        !           205: void netdev_tx_complete_err ( struct net_device *netdev,
        !           206:                              struct io_buffer *iobuf, int rc ) {
        !           207: 
        !           208:        /* Update statistics counter */
        !           209:        netdev_record_stat ( &netdev->tx_stats, rc );
        !           210:        if ( rc == 0 ) {
        !           211:                DBGC ( netdev, "NETDEV %s transmission %p complete\n",
        !           212:                       netdev->name, iobuf );
        !           213:        } else {
        !           214:                DBGC ( netdev, "NETDEV %s transmission %p failed: %s\n",
        !           215:                       netdev->name, iobuf, strerror ( rc ) );
        !           216:        }
        !           217: 
        !           218:        /* Catch data corruption as early as possible */
        !           219:        assert ( iobuf->list.next != NULL );
        !           220:        assert ( iobuf->list.prev != NULL );
        !           221: 
        !           222:        /* Dequeue and free I/O buffer */
        !           223:        list_del ( &iobuf->list );
        !           224:        free_iob ( iobuf );
        !           225: }
        !           226: 
        !           227: /**
        !           228:  * Complete network transmission
        !           229:  *
        !           230:  * @v netdev           Network device
        !           231:  * @v rc               Packet status code
        !           232:  *
        !           233:  * Completes the oldest outstanding packet in the TX queue.
        !           234:  */
        !           235: void netdev_tx_complete_next_err ( struct net_device *netdev, int rc ) {
        !           236:        struct io_buffer *iobuf;
        !           237: 
        !           238:        list_for_each_entry ( iobuf, &netdev->tx_queue, list ) {
        !           239:                netdev_tx_complete_err ( netdev, iobuf, rc );
        !           240:                return;
        !           241:        }
        !           242: }
        !           243: 
        !           244: /**
        !           245:  * Flush device's transmit queue
        !           246:  *
        !           247:  * @v netdev           Network device
        !           248:  */
        !           249: static void netdev_tx_flush ( struct net_device *netdev ) {
        !           250: 
        !           251:        /* Discard any packets in the TX queue */
        !           252:        while ( ! list_empty ( &netdev->tx_queue ) ) {
        !           253:                netdev_tx_complete_next_err ( netdev, -ECANCELED );
        !           254:        }
        !           255: }
        !           256: 
        !           257: /**
        !           258:  * Add packet to receive queue
        !           259:  *
        !           260:  * @v netdev           Network device
        !           261:  * @v iobuf            I/O buffer, or NULL
        !           262:  *
        !           263:  * The packet is added to the network device's RX queue.  This
        !           264:  * function takes ownership of the I/O buffer.
        !           265:  */
        !           266: void netdev_rx ( struct net_device *netdev, struct io_buffer *iobuf ) {
        !           267: 
        !           268:        DBGC ( netdev, "NETDEV %s received %p (%p+%zx)\n",
        !           269:               netdev->name, iobuf, iobuf->data, iob_len ( iobuf ) );
        !           270: 
        !           271:        /* Discard packet (for test purposes) if applicable */
        !           272:        if ( ( NETDEV_DISCARD_RATE > 0 ) &&
        !           273:             ( ( random() % NETDEV_DISCARD_RATE ) == 0 ) ) {
        !           274:                netdev_rx_err ( netdev, iobuf, -EAGAIN );
        !           275:                return;
        !           276:        }
        !           277: 
        !           278:        /* Enqueue packet */
        !           279:        list_add_tail ( &iobuf->list, &netdev->rx_queue );
        !           280: 
        !           281:        /* Update statistics counter */
        !           282:        netdev_record_stat ( &netdev->rx_stats, 0 );
        !           283: }
        !           284: 
        !           285: /**
        !           286:  * Discard received packet
        !           287:  *
        !           288:  * @v netdev           Network device
        !           289:  * @v iobuf            I/O buffer, or NULL
        !           290:  * @v rc               Packet status code
        !           291:  *
        !           292:  * The packet is discarded and an RX error is recorded.  This function
        !           293:  * takes ownership of the I/O buffer.  @c iobuf may be NULL if, for
        !           294:  * example, the net device wishes to report an error due to being
        !           295:  * unable to allocate an I/O buffer.
        !           296:  */
        !           297: void netdev_rx_err ( struct net_device *netdev,
        !           298:                     struct io_buffer *iobuf, int rc ) {
        !           299: 
        !           300:        DBGC ( netdev, "NETDEV %s failed to receive %p: %s\n",
        !           301:               netdev->name, iobuf, strerror ( rc ) );
        !           302: 
        !           303:        /* Discard packet */
        !           304:        free_iob ( iobuf );
        !           305: 
        !           306:        /* Update statistics counter */
        !           307:        netdev_record_stat ( &netdev->rx_stats, rc );
        !           308: }
        !           309: 
        !           310: /**
        !           311:  * Poll for completed and received packets on network device
        !           312:  *
        !           313:  * @v netdev           Network device
        !           314:  *
        !           315:  * Polls the network device for completed transmissions and received
        !           316:  * packets.  Any received packets will be added to the RX packet queue
        !           317:  * via netdev_rx().
        !           318:  */
        !           319: void netdev_poll ( struct net_device *netdev ) {
        !           320: 
        !           321:        if ( netdev_is_open ( netdev ) )
        !           322:                netdev->op->poll ( netdev );
        !           323: }
        !           324: 
        !           325: /**
        !           326:  * Remove packet from device's receive queue
        !           327:  *
        !           328:  * @v netdev           Network device
        !           329:  * @ret iobuf          I/O buffer, or NULL
        !           330:  *
        !           331:  * Removes the first packet from the device's RX queue and returns it.
        !           332:  * Ownership of the packet is transferred to the caller.
        !           333:  */
        !           334: struct io_buffer * netdev_rx_dequeue ( struct net_device *netdev ) {
        !           335:        struct io_buffer *iobuf;
        !           336: 
        !           337:        iobuf = list_first_entry ( &netdev->rx_queue, struct io_buffer, list );
        !           338:        if ( ! iobuf )
        !           339:                return NULL;
        !           340: 
        !           341:        list_del ( &iobuf->list );
        !           342:        return iobuf;
        !           343: }
        !           344: 
        !           345: /**
        !           346:  * Flush device's receive queue
        !           347:  *
        !           348:  * @v netdev           Network device
        !           349:  */
        !           350: static void netdev_rx_flush ( struct net_device *netdev ) {
        !           351:        struct io_buffer *iobuf;
        !           352: 
        !           353:        /* Discard any packets in the RX queue */
        !           354:        while ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
        !           355:                netdev_rx_err ( netdev, iobuf, -ECANCELED );
        !           356:        }
        !           357: }
        !           358: 
        !           359: /**
        !           360:  * Free network device
        !           361:  *
        !           362:  * @v refcnt           Network device reference counter
        !           363:  */
        !           364: static void free_netdev ( struct refcnt *refcnt ) {
        !           365:        struct net_device *netdev =
        !           366:                container_of ( refcnt, struct net_device, refcnt );
        !           367:        
        !           368:        netdev_tx_flush ( netdev );
        !           369:        netdev_rx_flush ( netdev );
        !           370:        clear_settings ( netdev_settings ( netdev ) );
        !           371:        free ( netdev );
        !           372: }
        !           373: 
        !           374: /**
        !           375:  * Allocate network device
        !           376:  *
        !           377:  * @v priv_size                Size of private data area (net_device::priv)
        !           378:  * @ret netdev         Network device, or NULL
        !           379:  *
        !           380:  * Allocates space for a network device and its private data area.
        !           381:  */
        !           382: struct net_device * alloc_netdev ( size_t priv_size ) {
        !           383:        struct net_device *netdev;
        !           384:        size_t total_len;
        !           385: 
        !           386:        total_len = ( sizeof ( *netdev ) + priv_size );
        !           387:        netdev = zalloc ( total_len );
        !           388:        if ( netdev ) {
        !           389:                ref_init ( &netdev->refcnt, free_netdev );
        !           390:                netdev->link_rc = -EUNKNOWN_LINK_STATUS;
        !           391:                INIT_LIST_HEAD ( &netdev->tx_queue );
        !           392:                INIT_LIST_HEAD ( &netdev->rx_queue );
        !           393:                netdev_settings_init ( netdev );
        !           394:                netdev->priv = ( ( ( void * ) netdev ) + sizeof ( *netdev ) );
        !           395:        }
        !           396:        return netdev;
        !           397: }
        !           398: 
        !           399: /**
        !           400:  * Register network device
        !           401:  *
        !           402:  * @v netdev           Network device
        !           403:  * @ret rc             Return status code
        !           404:  *
        !           405:  * Gives the network device a name and adds it to the list of network
        !           406:  * devices.
        !           407:  */
        !           408: int register_netdev ( struct net_device *netdev ) {
        !           409:        static unsigned int ifindex = 0;
        !           410:        struct net_driver *driver;
        !           411:        int rc;
        !           412: 
        !           413:        /* Create device name */
        !           414:        if ( netdev->name[0] == '\0' ) {
        !           415:                snprintf ( netdev->name, sizeof ( netdev->name ), "net%d",
        !           416:                           ifindex++ );
        !           417:        }
        !           418: 
        !           419:        /* Set initial link-layer address */
        !           420:        netdev->ll_protocol->init_addr ( netdev->hw_addr, netdev->ll_addr );
        !           421: 
        !           422:        /* Add to device list */
        !           423:        netdev_get ( netdev );
        !           424:        list_add_tail ( &netdev->list, &net_devices );
        !           425:        DBGC ( netdev, "NETDEV %s registered (phys %s hwaddr %s)\n",
        !           426:               netdev->name, netdev->dev->name,
        !           427:               netdev_addr ( netdev ) );
        !           428: 
        !           429:        /* Register per-netdev configuration settings */
        !           430:        if ( ( rc = register_settings ( netdev_settings ( netdev ),
        !           431:                                        NULL, netdev->name ) ) != 0 ) {
        !           432:                DBGC ( netdev, "NETDEV %s could not register settings: %s\n",
        !           433:                       netdev->name, strerror ( rc ) );
        !           434:                goto err_register_settings;
        !           435:        }
        !           436: 
        !           437:        /* Probe device */
        !           438:        for_each_table_entry ( driver, NET_DRIVERS ) {
        !           439:                if ( ( rc = driver->probe ( netdev ) ) != 0 ) {
        !           440:                        DBGC ( netdev, "NETDEV %s could not add %s device: "
        !           441:                               "%s\n", netdev->name, driver->name,
        !           442:                               strerror ( rc ) );
        !           443:                        goto err_probe;
        !           444:                }
        !           445:        }
        !           446: 
        !           447:        return 0;
        !           448: 
        !           449:  err_probe:
        !           450:        for_each_table_entry_continue_reverse ( driver, NET_DRIVERS )
        !           451:                driver->remove ( netdev );
        !           452:        unregister_settings ( netdev_settings ( netdev ) );
        !           453:  err_register_settings:
        !           454:        return rc;
        !           455: }
        !           456: 
        !           457: /**
        !           458:  * Open network device
        !           459:  *
        !           460:  * @v netdev           Network device
        !           461:  * @ret rc             Return status code
        !           462:  */
        !           463: int netdev_open ( struct net_device *netdev ) {
        !           464:        int rc;
        !           465: 
        !           466:        /* Do nothing if device is already open */
        !           467:        if ( netdev->state & NETDEV_OPEN )
        !           468:                return 0;
        !           469: 
        !           470:        DBGC ( netdev, "NETDEV %s opening\n", netdev->name );
        !           471: 
        !           472:        /* Open the device */
        !           473:        if ( ( rc = netdev->op->open ( netdev ) ) != 0 )
        !           474:                return rc;
        !           475: 
        !           476:        /* Mark as opened */
        !           477:        netdev->state |= NETDEV_OPEN;
        !           478: 
        !           479:        /* Add to head of open devices list */
        !           480:        list_add ( &netdev->open_list, &open_net_devices );
        !           481: 
        !           482:        /* Notify drivers of device state change */
        !           483:        netdev_notify ( netdev );
        !           484: 
        !           485:        return 0;
        !           486: }
        !           487: 
        !           488: /**
        !           489:  * Close network device
        !           490:  *
        !           491:  * @v netdev           Network device
        !           492:  */
        !           493: void netdev_close ( struct net_device *netdev ) {
        !           494: 
        !           495:        /* Do nothing if device is already closed */
        !           496:        if ( ! ( netdev->state & NETDEV_OPEN ) )
        !           497:                return;
        !           498: 
        !           499:        DBGC ( netdev, "NETDEV %s closing\n", netdev->name );
        !           500: 
        !           501:        /* Remove from open devices list */
        !           502:        list_del ( &netdev->open_list );
        !           503: 
        !           504:        /* Mark as closed */
        !           505:        netdev->state &= ~NETDEV_OPEN;
        !           506: 
        !           507:        /* Notify drivers of device state change */
        !           508:        netdev_notify ( netdev );
        !           509: 
        !           510:        /* Close the device */
        !           511:        netdev->op->close ( netdev );
        !           512: 
        !           513:        /* Flush TX and RX queues */
        !           514:        netdev_tx_flush ( netdev );
        !           515:        netdev_rx_flush ( netdev );
        !           516: }
        !           517: 
        !           518: /**
        !           519:  * Unregister network device
        !           520:  *
        !           521:  * @v netdev           Network device
        !           522:  *
        !           523:  * Removes the network device from the list of network devices.
        !           524:  */
        !           525: void unregister_netdev ( struct net_device *netdev ) {
        !           526:        struct net_driver *driver;
        !           527: 
        !           528:        /* Ensure device is closed */
        !           529:        netdev_close ( netdev );
        !           530: 
        !           531:        /* Remove device */
        !           532:        for_each_table_entry_reverse ( driver, NET_DRIVERS )
        !           533:                driver->remove ( netdev );
        !           534: 
        !           535:        /* Unregister per-netdev configuration settings */
        !           536:        unregister_settings ( netdev_settings ( netdev ) );
        !           537: 
        !           538:        /* Remove from device list */
        !           539:        list_del ( &netdev->list );
        !           540:        netdev_put ( netdev );
        !           541:        DBGC ( netdev, "NETDEV %s unregistered\n", netdev->name );
        !           542: }
        !           543: 
        !           544: /** Enable or disable interrupts
        !           545:  *
        !           546:  * @v netdev           Network device
        !           547:  * @v enable           Interrupts should be enabled
        !           548:  */
        !           549: void netdev_irq ( struct net_device *netdev, int enable ) {
        !           550: 
        !           551:        /* Do nothing if device does not support interrupts */
        !           552:        if ( ! netdev_irq_supported ( netdev ) )
        !           553:                return;
        !           554: 
        !           555:        /* Enable or disable device interrupts */
        !           556:        netdev->op->irq ( netdev, enable );
        !           557: 
        !           558:        /* Record interrupt enabled state */
        !           559:        netdev->state &= ~NETDEV_IRQ_ENABLED;
        !           560:        if ( enable )
        !           561:                netdev->state |= NETDEV_IRQ_ENABLED;
        !           562: }
        !           563: 
        !           564: /**
        !           565:  * Get network device by name
        !           566:  *
        !           567:  * @v name             Network device name
        !           568:  * @ret netdev         Network device, or NULL
        !           569:  */
        !           570: struct net_device * find_netdev ( const char *name ) {
        !           571:        struct net_device *netdev;
        !           572: 
        !           573:        list_for_each_entry ( netdev, &net_devices, list ) {
        !           574:                if ( strcmp ( netdev->name, name ) == 0 )
        !           575:                        return netdev;
        !           576:        }
        !           577: 
        !           578:        return NULL;
        !           579: }
        !           580: 
        !           581: /**
        !           582:  * Get network device by PCI bus:dev.fn address
        !           583:  *
        !           584:  * @v bus_type         Bus type
        !           585:  * @v location         Bus location
        !           586:  * @ret netdev         Network device, or NULL
        !           587:  */
        !           588: struct net_device * find_netdev_by_location ( unsigned int bus_type,
        !           589:                                              unsigned int location ) {
        !           590:        struct net_device *netdev;
        !           591: 
        !           592:        list_for_each_entry ( netdev, &net_devices, list ) {
        !           593:                if ( ( netdev->dev->desc.bus_type == bus_type ) &&
        !           594:                     ( netdev->dev->desc.location == location ) )
        !           595:                        return netdev;
        !           596:        }
        !           597: 
        !           598:        return NULL;    
        !           599: }
        !           600: 
        !           601: /**
        !           602:  * Get most recently opened network device
        !           603:  *
        !           604:  * @ret netdev         Most recently opened network device, or NULL
        !           605:  */
        !           606: struct net_device * last_opened_netdev ( void ) {
        !           607:        struct net_device *netdev;
        !           608: 
        !           609:        netdev = list_first_entry ( &open_net_devices, struct net_device,
        !           610:                                    open_list );
        !           611:        if ( ! netdev )
        !           612:                return NULL;
        !           613: 
        !           614:        assert ( netdev_is_open ( netdev ) );
        !           615:        return netdev;
        !           616: }
        !           617: 
        !           618: /**
        !           619:  * Transmit network-layer packet
        !           620:  *
        !           621:  * @v iobuf            I/O buffer
        !           622:  * @v netdev           Network device
        !           623:  * @v net_protocol     Network-layer protocol
        !           624:  * @v ll_dest          Destination link-layer address
        !           625:  * @v ll_source                Source link-layer address
        !           626:  * @ret rc             Return status code
        !           627:  *
        !           628:  * Prepends link-layer headers to the I/O buffer and transmits the
        !           629:  * packet via the specified network device.  This function takes
        !           630:  * ownership of the I/O buffer.
        !           631:  */
        !           632: int net_tx ( struct io_buffer *iobuf, struct net_device *netdev,
        !           633:             struct net_protocol *net_protocol, const void *ll_dest,
        !           634:             const void *ll_source ) {
        !           635:        struct ll_protocol *ll_protocol = netdev->ll_protocol;
        !           636:        int rc;
        !           637: 
        !           638:        /* Force a poll on the netdevice to (potentially) clear any
        !           639:         * backed-up TX completions.  This is needed on some network
        !           640:         * devices to avoid excessive losses due to small TX ring
        !           641:         * sizes.
        !           642:         */
        !           643:        netdev_poll ( netdev );
        !           644: 
        !           645:        /* Add link-layer header */
        !           646:        if ( ( rc = ll_protocol->push ( netdev, iobuf, ll_dest, ll_source,
        !           647:                                        net_protocol->net_proto ) ) != 0 ) {
        !           648:                free_iob ( iobuf );
        !           649:                return rc;
        !           650:        }
        !           651: 
        !           652:        /* Transmit packet */
        !           653:        return netdev_tx ( netdev, iobuf );
        !           654: }
        !           655: 
        !           656: /**
        !           657:  * Process received network-layer packet
        !           658:  *
        !           659:  * @v iobuf            I/O buffer
        !           660:  * @v netdev           Network device
        !           661:  * @v net_proto                Network-layer protocol, in network-byte order
        !           662:  * @v ll_dest          Destination link-layer address
        !           663:  * @v ll_source                Source link-layer address
        !           664:  * @ret rc             Return status code
        !           665:  */
        !           666: int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
        !           667:             uint16_t net_proto, const void *ll_dest, const void *ll_source ) {
        !           668:        struct net_protocol *net_protocol;
        !           669: 
        !           670:        /* Hand off to network-layer protocol, if any */
        !           671:        for_each_table_entry ( net_protocol, NET_PROTOCOLS ) {
        !           672:                if ( net_protocol->net_proto == net_proto )
        !           673:                        return net_protocol->rx ( iobuf, netdev, ll_dest,
        !           674:                                                  ll_source );
        !           675:        }
        !           676: 
        !           677:        DBGC ( netdev, "NETDEV %s unknown network protocol %04x\n",
        !           678:               netdev->name, ntohs ( net_proto ) );
        !           679:        free_iob ( iobuf );
        !           680:        return -ENOTSUP;
        !           681: }
        !           682: 
        !           683: /**
        !           684:  * Poll the network stack
        !           685:  *
        !           686:  * This polls all interfaces for received packets, and processes
        !           687:  * packets from the RX queue.
        !           688:  */
        !           689: void net_poll ( void ) {
        !           690:        struct net_device *netdev;
        !           691:        struct io_buffer *iobuf;
        !           692:        struct ll_protocol *ll_protocol;
        !           693:        const void *ll_dest;
        !           694:        const void *ll_source;
        !           695:        uint16_t net_proto;
        !           696:        int rc;
        !           697: 
        !           698:        /* Poll and process each network device */
        !           699:        list_for_each_entry ( netdev, &net_devices, list ) {
        !           700: 
        !           701:                /* Poll for new packets */
        !           702:                netdev_poll ( netdev );
        !           703: 
        !           704:                /* Leave received packets on the queue if receive
        !           705:                 * queue processing is currently frozen.  This will
        !           706:                 * happen when the raw packets are to be manually
        !           707:                 * dequeued using netdev_rx_dequeue(), rather than
        !           708:                 * processed via the usual networking stack.
        !           709:                 */
        !           710:                if ( netdev_rx_frozen ( netdev ) )
        !           711:                        continue;
        !           712: 
        !           713:                /* Process at most one received packet.  Give priority
        !           714:                 * to getting packets out of the NIC over processing
        !           715:                 * the received packets, because we advertise a window
        !           716:                 * that assumes that we can receive packets from the
        !           717:                 * NIC faster than they arrive.
        !           718:                 */
        !           719:                if ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
        !           720: 
        !           721:                        DBGC ( netdev, "NETDEV %s processing %p (%p+%zx)\n",
        !           722:                               netdev->name, iobuf, iobuf->data,
        !           723:                               iob_len ( iobuf ) );
        !           724: 
        !           725:                        /* Remove link-layer header */
        !           726:                        ll_protocol = netdev->ll_protocol;
        !           727:                        if ( ( rc = ll_protocol->pull ( netdev, iobuf,
        !           728:                                                        &ll_dest, &ll_source,
        !           729:                                                        &net_proto ) ) != 0 ) {
        !           730:                                free_iob ( iobuf );
        !           731:                                continue;
        !           732:                        }
        !           733: 
        !           734:                        /* Hand packet to network layer */
        !           735:                        if ( ( rc = net_rx ( iob_disown ( iobuf ), netdev,
        !           736:                                             net_proto, ll_dest,
        !           737:                                             ll_source ) ) != 0 ) {
        !           738:                                /* Record error for diagnosis */
        !           739:                                netdev_rx_err ( netdev, NULL, rc );
        !           740:                        }
        !           741:                }
        !           742:        }
        !           743: }
        !           744: 
        !           745: /**
        !           746:  * Single-step the network stack
        !           747:  *
        !           748:  * @v process          Network stack process
        !           749:  */
        !           750: static void net_step ( struct process *process __unused ) {
        !           751:        net_poll();
        !           752: }
        !           753: 
        !           754: /** Networking stack process */
        !           755: struct process net_process __permanent_process = {
        !           756:        .list = LIST_HEAD_INIT ( net_process.list ),
        !           757:        .step = net_step,
        !           758: };

unix.superglobalmegacorp.com

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