iPXE
netdevice.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017  * 02110-1301, USA.
00018  *
00019  * You can also choose to distribute this program under the terms of
00020  * the Unmodified Binary Distribution Licence (as given in the file
00021  * COPYING.UBDL), provided that you have satisfied its requirements.
00022  */
00023 
00024 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00025 
00026 #include <stdint.h>
00027 #include <stdlib.h>
00028 #include <stdio.h>
00029 #include <byteswap.h>
00030 #include <string.h>
00031 #include <errno.h>
00032 #include <config/general.h>
00033 #include <ipxe/if_ether.h>
00034 #include <ipxe/iobuf.h>
00035 #include <ipxe/tables.h>
00036 #include <ipxe/process.h>
00037 #include <ipxe/init.h>
00038 #include <ipxe/malloc.h>
00039 #include <ipxe/device.h>
00040 #include <ipxe/errortab.h>
00041 #include <ipxe/profile.h>
00042 #include <ipxe/fault.h>
00043 #include <ipxe/vlan.h>
00044 #include <ipxe/netdevice.h>
00045 
00046 /** @file
00047  *
00048  * Network device management
00049  *
00050  */
00051 
00052 /** List of network devices */
00053 struct list_head net_devices = LIST_HEAD_INIT ( net_devices );
00054 
00055 /** List of open network devices, in reverse order of opening */
00056 static struct list_head open_net_devices = LIST_HEAD_INIT ( open_net_devices );
00057 
00058 /** Network device index */
00059 static unsigned int netdev_index = 0;
00060 
00061 /** Network polling profiler */
00062 static struct profiler net_poll_profiler __profiler = { .name = "net.poll" };
00063 
00064 /** Network receive profiler */
00065 static struct profiler net_rx_profiler __profiler = { .name = "net.rx" };
00066 
00067 /** Network transmit profiler */
00068 static struct profiler net_tx_profiler __profiler = { .name = "net.tx" };
00069 
00070 /** Default unknown link status code */
00071 #define EUNKNOWN_LINK_STATUS __einfo_error ( EINFO_EUNKNOWN_LINK_STATUS )
00072 #define EINFO_EUNKNOWN_LINK_STATUS \
00073         __einfo_uniqify ( EINFO_EINPROGRESS, 0x01, "Unknown" )
00074 
00075 /** Default not-yet-attempted-configuration status code */
00076 #define EUNUSED_CONFIG __einfo_error ( EINFO_EUNUSED_CONFIG )
00077 #define EINFO_EUNUSED_CONFIG \
00078         __einfo_uniqify ( EINFO_EINPROGRESS, 0x02, "Unused" )
00079 
00080 /** Default configuration-in-progress status code */
00081 #define EINPROGRESS_CONFIG __einfo_error ( EINFO_EINPROGRESS_CONFIG )
00082 #define EINFO_EINPROGRESS_CONFIG \
00083         __einfo_uniqify ( EINFO_EINPROGRESS, 0x03, "Incomplete" )
00084 
00085 /** Default link-down status code */
00086 #define ENOTCONN_LINK_DOWN __einfo_error ( EINFO_ENOTCONN_LINK_DOWN )
00087 #define EINFO_ENOTCONN_LINK_DOWN \
00088         __einfo_uniqify ( EINFO_ENOTCONN, 0x01, "Down" )
00089 
00090 /** Human-readable message for the default link statuses */
00091 struct errortab netdev_errors[] __errortab = {
00092         __einfo_errortab ( EINFO_EUNKNOWN_LINK_STATUS ),
00093         __einfo_errortab ( EINFO_ENOTCONN_LINK_DOWN ),
00094         __einfo_errortab ( EINFO_EUNUSED_CONFIG ),
00095         __einfo_errortab ( EINFO_EINPROGRESS_CONFIG ),
00096 };
00097 
00098 /**
00099  * Check whether or not network device has a link-layer address
00100  *
00101  * @v netdev            Network device
00102  * @ret has_ll_addr     Network device has a link-layer address
00103  */
00104 static int netdev_has_ll_addr ( struct net_device *netdev ) {
00105         uint8_t *ll_addr = netdev->ll_addr;
00106         size_t remaining = sizeof ( netdev->ll_addr );
00107 
00108         while ( remaining-- ) {
00109                 if ( *(ll_addr++) != 0 )
00110                         return 1;
00111         }
00112         return 0;
00113 }
00114 
00115 /**
00116  * Notify drivers of network device or link state change
00117  *
00118  * @v netdev            Network device
00119  */
00120 static void netdev_notify ( struct net_device *netdev ) {
00121         struct net_driver *driver;
00122 
00123         for_each_table_entry ( driver, NET_DRIVERS ) {
00124                 if ( driver->notify )
00125                         driver->notify ( netdev );
00126         }
00127 }
00128 
00129 /**
00130  * Freeze network device receive queue processing
00131  *
00132  * @v netdev            Network device
00133  */
00134 void netdev_rx_freeze ( struct net_device *netdev ) {
00135 
00136         /* Mark receive queue processing as frozen */
00137         netdev->state |= NETDEV_RX_FROZEN;
00138 
00139         /* Notify drivers of change */
00140         netdev_notify ( netdev );
00141 }
00142 
00143 /**
00144  * Unfreeze network device receive queue processing
00145  *
00146  * @v netdev            Network device
00147  */
00148 void netdev_rx_unfreeze ( struct net_device *netdev ) {
00149 
00150         /* Mark receive queue processing as not frozen */
00151         netdev->state &= ~NETDEV_RX_FROZEN;
00152 
00153         /* Notify drivers of change */
00154         netdev_notify ( netdev );
00155 }
00156 
00157 /**
00158  * Mark network device as having a specific link state
00159  *
00160  * @v netdev            Network device
00161  * @v rc                Link status code
00162  */
00163 void netdev_link_err ( struct net_device *netdev, int rc ) {
00164 
00165         /* Stop link block timer */
00166         stop_timer ( &netdev->link_block );
00167 
00168         /* Record link state */
00169         netdev->link_rc = rc;
00170         if ( netdev->link_rc == 0 ) {
00171                 DBGC ( netdev, "NETDEV %s link is up\n", netdev->name );
00172         } else {
00173                 DBGC ( netdev, "NETDEV %s link is down: %s\n",
00174                        netdev->name, strerror ( netdev->link_rc ) );
00175         }
00176 
00177         /* Notify drivers of link state change */
00178         netdev_notify ( netdev );
00179 }
00180 
00181 /**
00182  * Mark network device as having link down
00183  *
00184  * @v netdev            Network device
00185  */
00186 void netdev_link_down ( struct net_device *netdev ) {
00187 
00188         /* Avoid clobbering a more detailed link status code, if one
00189          * is already set.
00190          */
00191         if ( ( netdev->link_rc == 0 ) ||
00192              ( netdev->link_rc == -EUNKNOWN_LINK_STATUS ) ) {
00193                 netdev_link_err ( netdev, -ENOTCONN_LINK_DOWN );
00194         }
00195 }
00196 
00197 /**
00198  * Mark network device link as being blocked
00199  *
00200  * @v netdev            Network device
00201  * @v timeout           Timeout (in ticks)
00202  */
00203 void netdev_link_block ( struct net_device *netdev, unsigned long timeout ) {
00204 
00205         /* Start link block timer */
00206         if ( ! netdev_link_blocked ( netdev ) ) {
00207                 DBGC ( netdev, "NETDEV %s link blocked for %ld ticks\n",
00208                        netdev->name, timeout );
00209         }
00210         start_timer_fixed ( &netdev->link_block, timeout );
00211 }
00212 
00213 /**
00214  * Mark network device link as being unblocked
00215  *
00216  * @v netdev            Network device
00217  */
00218 void netdev_link_unblock ( struct net_device *netdev ) {
00219 
00220         /* Stop link block timer */
00221         if ( netdev_link_blocked ( netdev ) )
00222                 DBGC ( netdev, "NETDEV %s link unblocked\n", netdev->name );
00223         stop_timer ( &netdev->link_block );
00224 }
00225 
00226 /**
00227  * Handle network device link block timer expiry
00228  *
00229  * @v timer             Link block timer
00230  * @v fail              Failure indicator
00231  */
00232 static void netdev_link_block_expired ( struct retry_timer *timer,
00233                                         int fail __unused ) {
00234         struct net_device *netdev =
00235                 container_of ( timer, struct net_device, link_block );
00236 
00237         /* Assume link is no longer blocked */
00238         DBGC ( netdev, "NETDEV %s link block expired\n", netdev->name );
00239 }
00240 
00241 /**
00242  * Record network device statistic
00243  *
00244  * @v stats             Network device statistics
00245  * @v rc                Status code
00246  */
00247 static void netdev_record_stat ( struct net_device_stats *stats, int rc ) {
00248         struct net_device_error *error;
00249         struct net_device_error *least_common_error;
00250         unsigned int i;
00251 
00252         /* If this is not an error, just update the good counter */
00253         if ( rc == 0 ) {
00254                 stats->good++;
00255                 return;
00256         }
00257 
00258         /* Update the bad counter */
00259         stats->bad++;
00260 
00261         /* Locate the appropriate error record */
00262         least_common_error = &stats->errors[0];
00263         for ( i = 0 ; i < ( sizeof ( stats->errors ) /
00264                             sizeof ( stats->errors[0] ) ) ; i++ ) {
00265                 error = &stats->errors[i];
00266                 /* Update matching record, if found */
00267                 if ( error->rc == rc ) {
00268                         error->count++;
00269                         return;
00270                 }
00271                 if ( error->count < least_common_error->count )
00272                         least_common_error = error;
00273         }
00274 
00275         /* Overwrite the least common error record */
00276         least_common_error->rc = rc;
00277         least_common_error->count = 1;
00278 }
00279 
00280 /**
00281  * Transmit raw packet via network device
00282  *
00283  * @v netdev            Network device
00284  * @v iobuf             I/O buffer
00285  * @ret rc              Return status code
00286  *
00287  * Transmits the packet via the specified network device.  This
00288  * function takes ownership of the I/O buffer.
00289  */
00290 int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf ) {
00291         int rc;
00292 
00293         DBGC2 ( netdev, "NETDEV %s transmitting %p (%p+%zx)\n",
00294                 netdev->name, iobuf, iobuf->data, iob_len ( iobuf ) );
00295         profile_start ( &net_tx_profiler );
00296 
00297         /* Enqueue packet */
00298         list_add_tail ( &iobuf->list, &netdev->tx_queue );
00299 
00300         /* Avoid calling transmit() on unopened network devices */
00301         if ( ! netdev_is_open ( netdev ) ) {
00302                 rc = -ENETUNREACH;
00303                 goto err;
00304         }
00305 
00306         /* Discard packet (for test purposes) if applicable */
00307         if ( ( rc = inject_fault ( NETDEV_DISCARD_RATE ) ) != 0 )
00308                 goto err;
00309 
00310         /* Transmit packet */
00311         if ( ( rc = netdev->op->transmit ( netdev, iobuf ) ) != 0 )
00312                 goto err;
00313 
00314         profile_stop ( &net_tx_profiler );
00315         return 0;
00316 
00317  err:
00318         netdev_tx_complete_err ( netdev, iobuf, rc );
00319         return rc;
00320 }
00321 
00322 /**
00323  * Defer transmitted packet
00324  *
00325  * @v netdev            Network device
00326  * @v iobuf             I/O buffer
00327  *
00328  * Drivers may call netdev_tx_defer() if there is insufficient space
00329  * in the transmit descriptor ring.  Any packets deferred in this way
00330  * will be automatically retransmitted as soon as space becomes
00331  * available (i.e. as soon as the driver calls netdev_tx_complete()).
00332  *
00333  * The packet must currently be in the network device's TX queue.
00334  *
00335  * Drivers utilising netdev_tx_defer() must ensure that space in the
00336  * transmit descriptor ring is freed up @b before calling
00337  * netdev_tx_complete().  For example, if the ring is modelled using a
00338  * producer counter and a consumer counter, then the consumer counter
00339  * must be incremented before the call to netdev_tx_complete().
00340  * Failure to do this will cause the retransmitted packet to be
00341  * immediately redeferred (which will result in out-of-order
00342  * transmissions and other nastiness).
00343  */
00344 void netdev_tx_defer ( struct net_device *netdev, struct io_buffer *iobuf ) {
00345 
00346         /* Catch data corruption as early as possible */
00347         list_check_contains_entry ( iobuf, &netdev->tx_queue, list );
00348 
00349         /* Remove from transmit queue */
00350         list_del ( &iobuf->list );
00351 
00352         /* Add to deferred transmit queue */
00353         list_add_tail ( &iobuf->list, &netdev->tx_deferred );
00354 
00355         /* Record "out of space" statistic */
00356         netdev_tx_err ( netdev, NULL, -ENOBUFS );
00357 }
00358 
00359 /**
00360  * Discard transmitted packet
00361  *
00362  * @v netdev            Network device
00363  * @v iobuf             I/O buffer, or NULL
00364  * @v rc                Packet status code
00365  *
00366  * The packet is discarded and a TX error is recorded.  This function
00367  * takes ownership of the I/O buffer.
00368  */
00369 void netdev_tx_err ( struct net_device *netdev,
00370                      struct io_buffer *iobuf, int rc ) {
00371 
00372         /* Update statistics counter */
00373         netdev_record_stat ( &netdev->tx_stats, rc );
00374         if ( rc == 0 ) {
00375                 DBGC2 ( netdev, "NETDEV %s transmission %p complete\n",
00376                         netdev->name, iobuf );
00377         } else {
00378                 DBGC ( netdev, "NETDEV %s transmission %p failed: %s\n",
00379                        netdev->name, iobuf, strerror ( rc ) );
00380         }
00381 
00382         /* Discard packet */
00383         free_iob ( iobuf );
00384 }
00385 
00386 /**
00387  * Complete network transmission
00388  *
00389  * @v netdev            Network device
00390  * @v iobuf             I/O buffer
00391  * @v rc                Packet status code
00392  *
00393  * The packet must currently be in the network device's TX queue.
00394  */
00395 void netdev_tx_complete_err ( struct net_device *netdev,
00396                               struct io_buffer *iobuf, int rc ) {
00397 
00398         /* Catch data corruption as early as possible */
00399         list_check_contains_entry ( iobuf, &netdev->tx_queue, list );
00400 
00401         /* Dequeue and free I/O buffer */
00402         list_del ( &iobuf->list );
00403         netdev_tx_err ( netdev, iobuf, rc );
00404 
00405         /* Handle pending transmit queue */
00406         while ( ( iobuf = list_first_entry ( &netdev->tx_deferred,
00407                                              struct io_buffer, list ) ) ) {
00408 
00409                 /* Remove from pending transmit queue */
00410                 list_del ( &iobuf->list );
00411 
00412                 /* When any transmit completion fails, cancel all
00413                  * pending transmissions.
00414                  */
00415                 if ( rc != 0 ) {
00416                         netdev_tx_err ( netdev, iobuf, -ECANCELED );
00417                         continue;
00418                 }
00419 
00420                 /* Otherwise, attempt to transmit the first pending packet */
00421                 netdev_tx ( netdev, iobuf );
00422                 break;
00423         }
00424 }
00425 
00426 /**
00427  * Complete network transmission
00428  *
00429  * @v netdev            Network device
00430  * @v rc                Packet status code
00431  *
00432  * Completes the oldest outstanding packet in the TX queue.
00433  */
00434 void netdev_tx_complete_next_err ( struct net_device *netdev, int rc ) {
00435         struct io_buffer *iobuf;
00436 
00437         if ( ( iobuf = list_first_entry ( &netdev->tx_queue, struct io_buffer,
00438                                           list ) ) != NULL ) {
00439                 netdev_tx_complete_err ( netdev, iobuf, rc );
00440         }
00441 }
00442 
00443 /**
00444  * Flush device's transmit queue
00445  *
00446  * @v netdev            Network device
00447  */
00448 static void netdev_tx_flush ( struct net_device *netdev ) {
00449 
00450         /* Discard any packets in the TX queue.  This will also cause
00451          * any packets in the deferred TX queue to be discarded
00452          * automatically.
00453          */
00454         while ( ! list_empty ( &netdev->tx_queue ) ) {
00455                 netdev_tx_complete_next_err ( netdev, -ECANCELED );
00456         }
00457         assert ( list_empty ( &netdev->tx_queue ) );
00458         assert ( list_empty ( &netdev->tx_deferred ) );
00459 }
00460 
00461 /**
00462  * Add packet to receive queue
00463  *
00464  * @v netdev            Network device
00465  * @v iobuf             I/O buffer, or NULL
00466  *
00467  * The packet is added to the network device's RX queue.  This
00468  * function takes ownership of the I/O buffer.
00469  */
00470 void netdev_rx ( struct net_device *netdev, struct io_buffer *iobuf ) {
00471         int rc;
00472 
00473         DBGC2 ( netdev, "NETDEV %s received %p (%p+%zx)\n",
00474                 netdev->name, iobuf, iobuf->data, iob_len ( iobuf ) );
00475 
00476         /* Discard packet (for test purposes) if applicable */
00477         if ( ( rc = inject_fault ( NETDEV_DISCARD_RATE ) ) != 0 ) {
00478                 netdev_rx_err ( netdev, iobuf, rc );
00479                 return;
00480         }
00481 
00482         /* Enqueue packet */
00483         list_add_tail ( &iobuf->list, &netdev->rx_queue );
00484 
00485         /* Update statistics counter */
00486         netdev_record_stat ( &netdev->rx_stats, 0 );
00487 }
00488 
00489 /**
00490  * Discard received packet
00491  *
00492  * @v netdev            Network device
00493  * @v iobuf             I/O buffer, or NULL
00494  * @v rc                Packet status code
00495  *
00496  * The packet is discarded and an RX error is recorded.  This function
00497  * takes ownership of the I/O buffer.  @c iobuf may be NULL if, for
00498  * example, the net device wishes to report an error due to being
00499  * unable to allocate an I/O buffer.
00500  */
00501 void netdev_rx_err ( struct net_device *netdev,
00502                      struct io_buffer *iobuf, int rc ) {
00503 
00504         DBGC ( netdev, "NETDEV %s failed to receive %p: %s\n",
00505                netdev->name, iobuf, strerror ( rc ) );
00506 
00507         /* Discard packet */
00508         free_iob ( iobuf );
00509 
00510         /* Update statistics counter */
00511         netdev_record_stat ( &netdev->rx_stats, rc );
00512 }
00513 
00514 /**
00515  * Poll for completed and received packets on network device
00516  *
00517  * @v netdev            Network device
00518  *
00519  * Polls the network device for completed transmissions and received
00520  * packets.  Any received packets will be added to the RX packet queue
00521  * via netdev_rx().
00522  */
00523 void netdev_poll ( struct net_device *netdev ) {
00524 
00525         if ( netdev_is_open ( netdev ) )
00526                 netdev->op->poll ( netdev );
00527 }
00528 
00529 /**
00530  * Remove packet from device's receive queue
00531  *
00532  * @v netdev            Network device
00533  * @ret iobuf           I/O buffer, or NULL
00534  *
00535  * Removes the first packet from the device's RX queue and returns it.
00536  * Ownership of the packet is transferred to the caller.
00537  */
00538 struct io_buffer * netdev_rx_dequeue ( struct net_device *netdev ) {
00539         struct io_buffer *iobuf;
00540 
00541         iobuf = list_first_entry ( &netdev->rx_queue, struct io_buffer, list );
00542         if ( ! iobuf )
00543                 return NULL;
00544 
00545         list_del ( &iobuf->list );
00546         return iobuf;
00547 }
00548 
00549 /**
00550  * Flush device's receive queue
00551  *
00552  * @v netdev            Network device
00553  */
00554 static void netdev_rx_flush ( struct net_device *netdev ) {
00555         struct io_buffer *iobuf;
00556 
00557         /* Discard any packets in the RX queue */
00558         while ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
00559                 netdev_rx_err ( netdev, iobuf, -ECANCELED );
00560         }
00561 }
00562 
00563 /**
00564  * Finish network device configuration
00565  *
00566  * @v config            Network device configuration
00567  * @v rc                Reason for completion
00568  */
00569 static void netdev_config_close ( struct net_device_configuration *config,
00570                                   int rc ) {
00571         struct net_device_configurator *configurator = config->configurator;
00572         struct net_device *netdev = config->netdev;
00573 
00574         /* Restart interface */
00575         intf_restart ( &config->job, rc );
00576 
00577         /* Record configuration result */
00578         config->rc = rc;
00579         if ( rc == 0 ) {
00580                 DBGC ( netdev, "NETDEV %s configured via %s\n",
00581                        netdev->name, configurator->name );
00582         } else {
00583                 DBGC ( netdev, "NETDEV %s configuration via %s failed: %s\n",
00584                        netdev->name, configurator->name, strerror ( rc ) );
00585         }
00586 }
00587 
00588 /** Network device configuration interface operations */
00589 static struct interface_operation netdev_config_ops[] = {
00590         INTF_OP ( intf_close, struct net_device_configuration *,
00591                   netdev_config_close ),
00592 };
00593 
00594 /** Network device configuration interface descriptor */
00595 static struct interface_descriptor netdev_config_desc =
00596         INTF_DESC ( struct net_device_configuration, job, netdev_config_ops );
00597 
00598 /**
00599  * Free network device
00600  *
00601  * @v refcnt            Network device reference counter
00602  */
00603 static void free_netdev ( struct refcnt *refcnt ) {
00604         struct net_device *netdev =
00605                 container_of ( refcnt, struct net_device, refcnt );
00606 
00607         stop_timer ( &netdev->link_block );
00608         netdev_tx_flush ( netdev );
00609         netdev_rx_flush ( netdev );
00610         clear_settings ( netdev_settings ( netdev ) );
00611         free ( netdev );
00612 }
00613 
00614 /**
00615  * Allocate network device
00616  *
00617  * @v priv_len          Length of private data area (net_device::priv)
00618  * @ret netdev          Network device, or NULL
00619  *
00620  * Allocates space for a network device and its private data area.
00621  */
00622 struct net_device * alloc_netdev ( size_t priv_len ) {
00623         struct net_device *netdev;
00624         struct net_device_configurator *configurator;
00625         struct net_device_configuration *config;
00626         unsigned int num_configs;
00627         size_t confs_len;
00628         size_t total_len;
00629 
00630         num_configs = table_num_entries ( NET_DEVICE_CONFIGURATORS );
00631         confs_len = ( num_configs * sizeof ( netdev->configs[0] ) );
00632         total_len = ( sizeof ( *netdev ) + confs_len + priv_len );
00633         netdev = zalloc ( total_len );
00634         if ( netdev ) {
00635                 ref_init ( &netdev->refcnt, free_netdev );
00636                 netdev->link_rc = -EUNKNOWN_LINK_STATUS;
00637                 timer_init ( &netdev->link_block, netdev_link_block_expired,
00638                              &netdev->refcnt );
00639                 INIT_LIST_HEAD ( &netdev->tx_queue );
00640                 INIT_LIST_HEAD ( &netdev->tx_deferred );
00641                 INIT_LIST_HEAD ( &netdev->rx_queue );
00642                 netdev_settings_init ( netdev );
00643                 config = netdev->configs;
00644                 for_each_table_entry ( configurator, NET_DEVICE_CONFIGURATORS ){
00645                         config->netdev = netdev;
00646                         config->configurator = configurator;
00647                         config->rc = -EUNUSED_CONFIG;
00648                         intf_init ( &config->job, &netdev_config_desc,
00649                                     &netdev->refcnt );
00650                         config++;
00651                 }
00652                 netdev->priv = ( ( ( void * ) netdev ) + sizeof ( *netdev ) +
00653                                  confs_len );
00654         }
00655         return netdev;
00656 }
00657 
00658 /**
00659  * Register network device
00660  *
00661  * @v netdev            Network device
00662  * @ret rc              Return status code
00663  *
00664  * Gives the network device a name and adds it to the list of network
00665  * devices.
00666  */
00667 int register_netdev ( struct net_device *netdev ) {
00668         struct ll_protocol *ll_protocol = netdev->ll_protocol;
00669         struct net_driver *driver;
00670         struct net_device *duplicate;
00671         uint32_t seed;
00672         int rc;
00673 
00674         /* Set initial link-layer address, if not already set */
00675         if ( ! netdev_has_ll_addr ( netdev ) ) {
00676                 ll_protocol->init_addr ( netdev->hw_addr, netdev->ll_addr );
00677         }
00678 
00679         /* Set MTU, if not already set */
00680         if ( ! netdev->mtu ) {
00681                 netdev->mtu = ( netdev->max_pkt_len -
00682                                 ll_protocol->ll_header_len );
00683         }
00684 
00685         /* Reject network devices that are already available via a
00686          * different hardware device.
00687          */
00688         duplicate = find_netdev_by_ll_addr ( ll_protocol, netdev->ll_addr );
00689         if ( duplicate && ( duplicate->dev != netdev->dev ) ) {
00690                 DBGC ( netdev, "NETDEV rejecting duplicate (phys %s) of %s "
00691                        "(phys %s)\n", netdev->dev->name, duplicate->name,
00692                        duplicate->dev->name );
00693                 rc = -EEXIST;
00694                 goto err_duplicate;
00695         }
00696 
00697         /* Reject named network devices that already exist */
00698         if ( netdev->name[0] && ( duplicate = find_netdev ( netdev->name ) ) ) {
00699                 DBGC ( netdev, "NETDEV rejecting duplicate name %s\n",
00700                        duplicate->name );
00701                 rc = -EEXIST;
00702                 goto err_duplicate;
00703         }
00704 
00705         /* Record device index and create device name */
00706         if ( netdev->name[0] == '\0' ) {
00707                 snprintf ( netdev->name, sizeof ( netdev->name ), "net%d",
00708                            netdev_index );
00709         }
00710         netdev->index = ++netdev_index;
00711 
00712         /* Use least significant bits of the link-layer address to
00713          * improve the randomness of the (non-cryptographic) random
00714          * number generator.
00715          */
00716         memcpy ( &seed, ( netdev->ll_addr + ll_protocol->ll_addr_len
00717                           - sizeof ( seed ) ), sizeof ( seed ) );
00718         srand ( rand() ^ seed );
00719 
00720         /* Add to device list */
00721         netdev_get ( netdev );
00722         list_add_tail ( &netdev->list, &net_devices );
00723         DBGC ( netdev, "NETDEV %s registered (phys %s hwaddr %s)\n",
00724                netdev->name, netdev->dev->name,
00725                netdev_addr ( netdev ) );
00726 
00727         /* Register per-netdev configuration settings */
00728         if ( ( rc = register_settings ( netdev_settings ( netdev ),
00729                                         NULL, netdev->name ) ) != 0 ) {
00730                 DBGC ( netdev, "NETDEV %s could not register settings: %s\n",
00731                        netdev->name, strerror ( rc ) );
00732                 goto err_register_settings;
00733         }
00734 
00735         /* Probe device */
00736         for_each_table_entry ( driver, NET_DRIVERS ) {
00737                 if ( driver->probe && ( rc = driver->probe ( netdev ) ) != 0 ) {
00738                         DBGC ( netdev, "NETDEV %s could not add %s device: "
00739                                "%s\n", netdev->name, driver->name,
00740                                strerror ( rc ) );
00741                         goto err_probe;
00742                 }
00743         }
00744 
00745         return 0;
00746 
00747  err_probe:
00748         for_each_table_entry_continue_reverse ( driver, NET_DRIVERS ) {
00749                 if ( driver->remove )
00750                         driver->remove ( netdev );
00751         }
00752         clear_settings ( netdev_settings ( netdev ) );
00753         unregister_settings ( netdev_settings ( netdev ) );
00754  err_register_settings:
00755         list_del ( &netdev->list );
00756         netdev_put ( netdev );
00757  err_duplicate:
00758         return rc;
00759 }
00760 
00761 /**
00762  * Open network device
00763  *
00764  * @v netdev            Network device
00765  * @ret rc              Return status code
00766  */
00767 int netdev_open ( struct net_device *netdev ) {
00768         int rc;
00769 
00770         /* Do nothing if device is already open */
00771         if ( netdev->state & NETDEV_OPEN )
00772                 return 0;
00773 
00774         DBGC ( netdev, "NETDEV %s opening\n", netdev->name );
00775 
00776         /* Mark as opened */
00777         netdev->state |= NETDEV_OPEN;
00778 
00779         /* Open the device */
00780         if ( ( rc = netdev->op->open ( netdev ) ) != 0 )
00781                 goto err;
00782 
00783         /* Add to head of open devices list */
00784         list_add ( &netdev->open_list, &open_net_devices );
00785 
00786         /* Notify drivers of device state change */
00787         netdev_notify ( netdev );
00788 
00789         return 0;
00790 
00791  err:
00792         netdev->state &= ~NETDEV_OPEN;
00793         return rc;
00794 }
00795 
00796 /**
00797  * Close network device
00798  *
00799  * @v netdev            Network device
00800  */
00801 void netdev_close ( struct net_device *netdev ) {
00802         unsigned int num_configs;
00803         unsigned int i;
00804 
00805         /* Do nothing if device is already closed */
00806         if ( ! ( netdev->state & NETDEV_OPEN ) )
00807                 return;
00808 
00809         DBGC ( netdev, "NETDEV %s closing\n", netdev->name );
00810 
00811         /* Terminate any ongoing configurations.  Use intf_close()
00812          * rather than intf_restart() to allow the cancellation to be
00813          * reported back to us if a configuration is actually in
00814          * progress.
00815          */
00816         num_configs = table_num_entries ( NET_DEVICE_CONFIGURATORS );
00817         for ( i = 0 ; i < num_configs ; i++ )
00818                 intf_close ( &netdev->configs[i].job, -ECANCELED );
00819 
00820         /* Remove from open devices list */
00821         list_del ( &netdev->open_list );
00822 
00823         /* Mark as closed */
00824         netdev->state &= ~NETDEV_OPEN;
00825 
00826         /* Notify drivers of device state change */
00827         netdev_notify ( netdev );
00828 
00829         /* Close the device */
00830         netdev->op->close ( netdev );
00831 
00832         /* Flush TX and RX queues */
00833         netdev_tx_flush ( netdev );
00834         netdev_rx_flush ( netdev );
00835 }
00836 
00837 /**
00838  * Unregister network device
00839  *
00840  * @v netdev            Network device
00841  *
00842  * Removes the network device from the list of network devices.
00843  */
00844 void unregister_netdev ( struct net_device *netdev ) {
00845         struct net_driver *driver;
00846 
00847         /* Ensure device is closed */
00848         netdev_close ( netdev );
00849 
00850         /* Remove device */
00851         for_each_table_entry_reverse ( driver, NET_DRIVERS ) {
00852                 if ( driver->remove )
00853                         driver->remove ( netdev );
00854         }
00855 
00856         /* Unregister per-netdev configuration settings */
00857         clear_settings ( netdev_settings ( netdev ) );
00858         unregister_settings ( netdev_settings ( netdev ) );
00859 
00860         /* Remove from device list */
00861         DBGC ( netdev, "NETDEV %s unregistered\n", netdev->name );
00862         list_del ( &netdev->list );
00863         netdev_put ( netdev );
00864 
00865         /* Reset network device index if no devices remain */
00866         if ( list_empty ( &net_devices ) )
00867                 netdev_index = 0;
00868 }
00869 
00870 /** Enable or disable interrupts
00871  *
00872  * @v netdev            Network device
00873  * @v enable            Interrupts should be enabled
00874  */
00875 void netdev_irq ( struct net_device *netdev, int enable ) {
00876 
00877         /* Enable or disable device interrupts, if applicable */
00878         if ( netdev_irq_supported ( netdev ) )
00879                 netdev->op->irq ( netdev, enable );
00880 
00881         /* Record interrupt enabled state */
00882         netdev->state &= ~NETDEV_IRQ_ENABLED;
00883         if ( enable )
00884                 netdev->state |= NETDEV_IRQ_ENABLED;
00885 }
00886 
00887 /**
00888  * Get network device by name
00889  *
00890  * @v name              Network device name
00891  * @ret netdev          Network device, or NULL
00892  */
00893 struct net_device * find_netdev ( const char *name ) {
00894         struct net_device *netdev;
00895 
00896         /* Allow "netX" shortcut */
00897         if ( strcmp ( name, "netX" ) == 0 )
00898                 return last_opened_netdev();
00899 
00900         /* Identify network device by name */
00901         list_for_each_entry ( netdev, &net_devices, list ) {
00902                 if ( strcmp ( netdev->name, name ) == 0 )
00903                         return netdev;
00904         }
00905 
00906         return NULL;
00907 }
00908 
00909 /**
00910  * Get network device by index
00911  *
00912  * @v index             Network device index
00913  * @ret netdev          Network device, or NULL
00914  */
00915 struct net_device * find_netdev_by_index ( unsigned int index ) {
00916         struct net_device *netdev;
00917 
00918         /* Identify network device by index */
00919         list_for_each_entry ( netdev, &net_devices, list ) {
00920                 if ( netdev->index == index )
00921                         return netdev;
00922         }
00923 
00924         return NULL;
00925 }
00926 
00927 /**
00928  * Get network device by PCI bus:dev.fn address
00929  *
00930  * @v bus_type          Bus type
00931  * @v location          Bus location
00932  * @ret netdev          Network device, or NULL
00933  */
00934 struct net_device * find_netdev_by_location ( unsigned int bus_type,
00935                                               unsigned int location ) {
00936         struct net_device *netdev;
00937 
00938         list_for_each_entry ( netdev, &net_devices, list ) {
00939                 if ( ( netdev->dev->desc.bus_type == bus_type ) &&
00940                      ( netdev->dev->desc.location == location ) )
00941                         return netdev;
00942         }
00943 
00944         return NULL;    
00945 }
00946 
00947 /**
00948  * Get network device by link-layer address
00949  *
00950  * @v ll_protocol       Link-layer protocol
00951  * @v ll_addr           Link-layer address
00952  * @ret netdev          Network device, or NULL
00953  */
00954 struct net_device * find_netdev_by_ll_addr ( struct ll_protocol *ll_protocol,
00955                                              const void *ll_addr ) {
00956         struct net_device *netdev;
00957 
00958         list_for_each_entry ( netdev, &net_devices, list ) {
00959                 if ( ( netdev->ll_protocol == ll_protocol ) &&
00960                      ( memcmp ( netdev->ll_addr, ll_addr,
00961                                 ll_protocol->ll_addr_len ) == 0 ) )
00962                         return netdev;
00963         }
00964 
00965         return NULL;
00966 }
00967 
00968 /**
00969  * Get most recently opened network device
00970  *
00971  * @ret netdev          Most recently opened network device, or NULL
00972  */
00973 struct net_device * last_opened_netdev ( void ) {
00974         struct net_device *netdev;
00975 
00976         netdev = list_first_entry ( &open_net_devices, struct net_device,
00977                                     open_list );
00978         if ( ! netdev )
00979                 return NULL;
00980 
00981         assert ( netdev_is_open ( netdev ) );
00982         return netdev;
00983 }
00984 
00985 /**
00986  * Transmit network-layer packet
00987  *
00988  * @v iobuf             I/O buffer
00989  * @v netdev            Network device
00990  * @v net_protocol      Network-layer protocol
00991  * @v ll_dest           Destination link-layer address
00992  * @v ll_source         Source link-layer address
00993  * @ret rc              Return status code
00994  *
00995  * Prepends link-layer headers to the I/O buffer and transmits the
00996  * packet via the specified network device.  This function takes
00997  * ownership of the I/O buffer.
00998  */
00999 int net_tx ( struct io_buffer *iobuf, struct net_device *netdev,
01000              struct net_protocol *net_protocol, const void *ll_dest,
01001              const void *ll_source ) {
01002         struct ll_protocol *ll_protocol = netdev->ll_protocol;
01003         int rc;
01004 
01005         /* Add link-layer header */
01006         if ( ( rc = ll_protocol->push ( netdev, iobuf, ll_dest, ll_source,
01007                                         net_protocol->net_proto ) ) != 0 ) {
01008                 /* Record error for diagnosis */
01009                 netdev_tx_err ( netdev, iobuf, rc );
01010                 return rc;
01011         }
01012 
01013         /* Transmit packet */
01014         return netdev_tx ( netdev, iobuf );
01015 }
01016 
01017 /**
01018  * Process received network-layer packet
01019  *
01020  * @v iobuf             I/O buffer
01021  * @v netdev            Network device
01022  * @v net_proto         Network-layer protocol, in network-byte order
01023  * @v ll_dest           Destination link-layer address
01024  * @v ll_source         Source link-layer address
01025  * @v flags             Packet flags
01026  * @ret rc              Return status code
01027  */
01028 int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
01029              uint16_t net_proto, const void *ll_dest, const void *ll_source,
01030              unsigned int flags ) {
01031         struct net_protocol *net_protocol;
01032 
01033         /* Hand off to network-layer protocol, if any */
01034         for_each_table_entry ( net_protocol, NET_PROTOCOLS ) {
01035                 if ( net_protocol->net_proto == net_proto )
01036                         return net_protocol->rx ( iobuf, netdev, ll_dest,
01037                                                   ll_source, flags );
01038         }
01039 
01040         DBGC ( netdev, "NETDEV %s unknown network protocol %04x\n",
01041                netdev->name, ntohs ( net_proto ) );
01042         free_iob ( iobuf );
01043         return -ENOTSUP;
01044 }
01045 
01046 /**
01047  * Poll the network stack
01048  *
01049  * This polls all interfaces for received packets, and processes
01050  * packets from the RX queue.
01051  */
01052 void net_poll ( void ) {
01053         struct net_device *netdev;
01054         struct io_buffer *iobuf;
01055         struct ll_protocol *ll_protocol;
01056         const void *ll_dest;
01057         const void *ll_source;
01058         uint16_t net_proto;
01059         unsigned int flags;
01060         int rc;
01061 
01062         /* Poll and process each network device */
01063         list_for_each_entry ( netdev, &net_devices, list ) {
01064 
01065                 /* Poll for new packets */
01066                 profile_start ( &net_poll_profiler );
01067                 netdev_poll ( netdev );
01068                 profile_stop ( &net_poll_profiler );
01069 
01070                 /* Leave received packets on the queue if receive
01071                  * queue processing is currently frozen.  This will
01072                  * happen when the raw packets are to be manually
01073                  * dequeued using netdev_rx_dequeue(), rather than
01074                  * processed via the usual networking stack.
01075                  */
01076                 if ( netdev_rx_frozen ( netdev ) )
01077                         continue;
01078 
01079                 /* Process all received packets */
01080                 while ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
01081 
01082                         DBGC2 ( netdev, "NETDEV %s processing %p (%p+%zx)\n",
01083                                 netdev->name, iobuf, iobuf->data,
01084                                 iob_len ( iobuf ) );
01085                         profile_start ( &net_rx_profiler );
01086 
01087                         /* Remove link-layer header */
01088                         ll_protocol = netdev->ll_protocol;
01089                         if ( ( rc = ll_protocol->pull ( netdev, iobuf,
01090                                                         &ll_dest, &ll_source,
01091                                                         &net_proto,
01092                                                         &flags ) ) != 0 ) {
01093                                 free_iob ( iobuf );
01094                                 continue;
01095                         }
01096 
01097                         /* Hand packet to network layer */
01098                         if ( ( rc = net_rx ( iob_disown ( iobuf ), netdev,
01099                                              net_proto, ll_dest,
01100                                              ll_source, flags ) ) != 0 ) {
01101                                 /* Record error for diagnosis */
01102                                 netdev_rx_err ( netdev, NULL, rc );
01103                         }
01104                         profile_stop ( &net_rx_profiler );
01105                 }
01106         }
01107 }
01108 
01109 /**
01110  * Single-step the network stack
01111  *
01112  * @v process           Network stack process
01113  */
01114 static void net_step ( struct process *process __unused ) {
01115         net_poll();
01116 }
01117 
01118 /**
01119  * Get the VLAN tag (when VLAN support is not present)
01120  *
01121  * @v netdev            Network device
01122  * @ret tag             0, indicating that device is not a VLAN device
01123  */
01124 __weak unsigned int vlan_tag ( struct net_device *netdev __unused ) {
01125         return 0;
01126 }
01127 
01128 /**
01129  * Identify VLAN device (when VLAN support is not present)
01130  *
01131  * @v trunk             Trunk network device
01132  * @v tag               VLAN tag
01133  * @ret netdev          VLAN device, if any
01134  */
01135 __weak struct net_device * vlan_find ( struct net_device *trunk __unused,
01136                                        unsigned int tag __unused ) {
01137         return NULL;
01138 }
01139 
01140 /** Networking stack process */
01141 PERMANENT_PROCESS ( net_process, net_step );
01142 
01143 /**
01144  * Discard some cached network device data
01145  *
01146  * @ret discarded       Number of cached items discarded
01147  */
01148 static unsigned int net_discard ( void ) {
01149         struct net_device *netdev;
01150         struct io_buffer *iobuf;
01151         unsigned int discarded = 0;
01152 
01153         /* Try to drop one deferred TX packet from each network device */
01154         for_each_netdev ( netdev ) {
01155                 if ( ( iobuf = list_first_entry ( &netdev->tx_deferred,
01156                                                   struct io_buffer,
01157                                                   list ) ) != NULL ) {
01158 
01159                         /* Discard first deferred packet */
01160                         list_del ( &iobuf->list );
01161                         free_iob ( iobuf );
01162 
01163                         /* Report discard */
01164                         discarded++;
01165                 }
01166         }
01167 
01168         return discarded;
01169 }
01170 
01171 /** Network device cache discarder */
01172 struct cache_discarder net_discarder __cache_discarder ( CACHE_NORMAL ) = {
01173         .discard = net_discard,
01174 };
01175 
01176 /**
01177  * Find network device configurator
01178  *
01179  * @v name              Name
01180  * @ret configurator    Network device configurator, or NULL
01181  */
01182 struct net_device_configurator * find_netdev_configurator ( const char *name ) {
01183         struct net_device_configurator *configurator;
01184 
01185         for_each_table_entry ( configurator, NET_DEVICE_CONFIGURATORS ) {
01186                 if ( strcmp ( configurator->name, name ) == 0 )
01187                         return configurator;
01188         }
01189         return NULL;
01190 }
01191 
01192 /**
01193  * Start network device configuration
01194  *
01195  * @v netdev            Network device
01196  * @v configurator      Network device configurator
01197  * @ret rc              Return status code
01198  */
01199 int netdev_configure ( struct net_device *netdev,
01200                        struct net_device_configurator *configurator ) {
01201         struct net_device_configuration *config =
01202                 netdev_configuration ( netdev, configurator );
01203         int rc;
01204 
01205         /* Check applicability of configurator */
01206         if ( ! netdev_configurator_applies ( netdev, configurator ) ) {
01207                 DBGC ( netdev, "NETDEV %s does not support configuration via "
01208                        "%s\n", netdev->name, configurator->name );
01209                 return -ENOTSUP;
01210         }
01211 
01212         /* Terminate any ongoing configuration */
01213         intf_restart ( &config->job, -ECANCELED );
01214 
01215         /* Mark configuration as being in progress */
01216         config->rc = -EINPROGRESS_CONFIG;
01217 
01218         DBGC ( netdev, "NETDEV %s starting configuration via %s\n",
01219                netdev->name, configurator->name );
01220 
01221         /* Start configuration */
01222         if ( ( rc = configurator->start ( &config->job, netdev ) ) != 0 ) {
01223                 DBGC ( netdev, "NETDEV %s could not start configuration via "
01224                        "%s: %s\n", netdev->name, configurator->name,
01225                        strerror ( rc ) );
01226                 config->rc = rc;
01227                 return rc;
01228         }
01229 
01230         return 0;
01231 }
01232 
01233 /**
01234  * Start network device configuration via all supported configurators
01235  *
01236  * @v netdev            Network device
01237  * @ret rc              Return status code
01238  */
01239 int netdev_configure_all ( struct net_device *netdev ) {
01240         struct net_device_configurator *configurator;
01241         int rc;
01242 
01243         /* Start configuration for each configurator */
01244         for_each_table_entry ( configurator, NET_DEVICE_CONFIGURATORS ) {
01245 
01246                 /* Skip any inapplicable configurators */
01247                 if ( ! netdev_configurator_applies ( netdev, configurator ) )
01248                         continue;
01249 
01250                 /* Start configuration */
01251                 if ( ( rc = netdev_configure ( netdev, configurator ) ) != 0 )
01252                         return rc;
01253         }
01254 
01255         return 0;
01256 }
01257 
01258 /**
01259  * Check if network device has a configuration with a specified status code
01260  *
01261  * @v netdev            Network device
01262  * @v rc                Status code
01263  * @ret has_rc          Network device has a configuration with this status code
01264  */
01265 static int netdev_has_configuration_rc ( struct net_device *netdev, int rc ) {
01266         unsigned int num_configs;
01267         unsigned int i;
01268 
01269         num_configs = table_num_entries ( NET_DEVICE_CONFIGURATORS );
01270         for ( i = 0 ; i < num_configs ; i++ ) {
01271                 if ( netdev->configs[i].rc == rc )
01272                         return 1;
01273         }
01274         return 0;
01275 }
01276 
01277 /**
01278  * Check if network device configuration is in progress
01279  *
01280  * @v netdev            Network device
01281  * @ret is_in_progress  Network device configuration is in progress
01282  */
01283 int netdev_configuration_in_progress ( struct net_device *netdev ) {
01284 
01285         return netdev_has_configuration_rc ( netdev, -EINPROGRESS_CONFIG );
01286 }
01287 
01288 /**
01289  * Check if network device has at least one successful configuration
01290  *
01291  * @v netdev            Network device
01292  * @v configurator      Configurator
01293  * @ret rc              Return status code
01294  */
01295 int netdev_configuration_ok ( struct net_device *netdev ) {
01296 
01297         return netdev_has_configuration_rc ( netdev, 0 );
01298 }