Annotation of qemu/roms/ipxe/src/net/netdevice.c, revision 1.1.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.