2
* Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
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.
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.
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.
19
FILE_LICENCE ( GPL2_OR_LATER );
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>
39
* Network device management
43
/** List of network devices */
44
struct list_head net_devices = LIST_HEAD_INIT ( net_devices );
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 );
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" )
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" )
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 ),
66
* Check whether or not network device has a link-layer address
68
* @v netdev Network device
69
* @ret has_ll_addr Network device has a link-layer address
71
static int netdev_has_ll_addr ( struct net_device *netdev ) {
72
uint8_t *ll_addr = netdev->ll_addr;
73
size_t remaining = sizeof ( netdev->ll_addr );
75
while ( remaining-- ) {
76
if ( *(ll_addr++) != 0 )
83
* Notify drivers of network device or link state change
85
* @v netdev Network device
87
static void netdev_notify ( struct net_device *netdev ) {
88
struct net_driver *driver;
90
for_each_table_entry ( driver, NET_DRIVERS )
91
driver->notify ( netdev );
95
* Mark network device as having a specific link state
97
* @v netdev Network device
98
* @v rc Link status code
100
void netdev_link_err ( struct net_device *netdev, int rc ) {
102
/* Record link state */
103
netdev->link_rc = rc;
104
if ( netdev->link_rc == 0 ) {
105
DBGC ( netdev, "NETDEV %s link is up\n", netdev->name );
107
DBGC ( netdev, "NETDEV %s link is down: %s\n",
108
netdev->name, strerror ( netdev->link_rc ) );
111
/* Notify drivers of link state change */
112
netdev_notify ( netdev );
116
* Mark network device as having link down
118
* @v netdev Network device
120
void netdev_link_down ( struct net_device *netdev ) {
122
/* Avoid clobbering a more detailed link status code, if one
125
if ( ( netdev->link_rc == 0 ) ||
126
( netdev->link_rc == -EUNKNOWN_LINK_STATUS ) ) {
127
netdev_link_err ( netdev, -ENOTCONN_LINK_DOWN );
132
* Record network device statistic
134
* @v stats Network device statistics
137
static void netdev_record_stat ( struct net_device_stats *stats, int rc ) {
138
struct net_device_error *error;
139
struct net_device_error *least_common_error;
142
/* If this is not an error, just update the good counter */
148
/* Update the bad counter */
151
/* Locate the appropriate error record */
152
least_common_error = &stats->errors[0];
153
for ( i = 0 ; i < ( sizeof ( stats->errors ) /
154
sizeof ( stats->errors[0] ) ) ; i++ ) {
155
error = &stats->errors[i];
156
/* Update matching record, if found */
157
if ( error->rc == rc ) {
161
if ( error->count < least_common_error->count )
162
least_common_error = error;
165
/* Overwrite the least common error record */
166
least_common_error->rc = rc;
167
least_common_error->count = 1;
171
* Transmit raw packet via network device
173
* @v netdev Network device
174
* @v iobuf I/O buffer
175
* @ret rc Return status code
177
* Transmits the packet via the specified network device. This
178
* function takes ownership of the I/O buffer.
180
int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf ) {
183
DBGC2 ( netdev, "NETDEV %s transmitting %p (%p+%zx)\n",
184
netdev->name, iobuf, iobuf->data, iob_len ( iobuf ) );
187
list_add_tail ( &iobuf->list, &netdev->tx_queue );
189
/* Avoid calling transmit() on unopened network devices */
190
if ( ! netdev_is_open ( netdev ) ) {
195
/* Discard packet (for test purposes) if applicable */
196
if ( ( NETDEV_DISCARD_RATE > 0 ) &&
197
( ( random() % NETDEV_DISCARD_RATE ) == 0 ) ) {
202
/* Transmit packet */
203
if ( ( rc = netdev->op->transmit ( netdev, iobuf ) ) != 0 )
209
netdev_tx_complete_err ( netdev, iobuf, rc );
214
* Discard transmitted packet
216
* @v netdev Network device
217
* @v iobuf I/O buffer, or NULL
218
* @v rc Packet status code
220
* The packet is discarded and a TX error is recorded. This function
221
* takes ownership of the I/O buffer.
223
void netdev_tx_err ( struct net_device *netdev,
224
struct io_buffer *iobuf, int rc ) {
226
/* Update statistics counter */
227
netdev_record_stat ( &netdev->tx_stats, rc );
229
DBGC2 ( netdev, "NETDEV %s transmission %p complete\n",
230
netdev->name, iobuf );
232
DBGC ( netdev, "NETDEV %s transmission %p failed: %s\n",
233
netdev->name, iobuf, strerror ( rc ) );
241
* Complete network transmission
243
* @v netdev Network device
244
* @v iobuf I/O buffer
245
* @v rc Packet status code
247
* The packet must currently be in the network device's TX queue.
249
void netdev_tx_complete_err ( struct net_device *netdev,
250
struct io_buffer *iobuf, int rc ) {
252
/* Catch data corruption as early as possible */
253
list_check_contains_entry ( iobuf, &netdev->tx_queue, list );
255
/* Dequeue and free I/O buffer */
256
list_del ( &iobuf->list );
257
netdev_tx_err ( netdev, iobuf, rc );
261
* Complete network transmission
263
* @v netdev Network device
264
* @v rc Packet status code
266
* Completes the oldest outstanding packet in the TX queue.
268
void netdev_tx_complete_next_err ( struct net_device *netdev, int rc ) {
269
struct io_buffer *iobuf;
271
list_for_each_entry ( iobuf, &netdev->tx_queue, list ) {
272
netdev_tx_complete_err ( netdev, iobuf, rc );
278
* Flush device's transmit queue
280
* @v netdev Network device
282
static void netdev_tx_flush ( struct net_device *netdev ) {
284
/* Discard any packets in the TX queue */
285
while ( ! list_empty ( &netdev->tx_queue ) ) {
286
netdev_tx_complete_next_err ( netdev, -ECANCELED );
291
* Add packet to receive queue
293
* @v netdev Network device
294
* @v iobuf I/O buffer, or NULL
296
* The packet is added to the network device's RX queue. This
297
* function takes ownership of the I/O buffer.
299
void netdev_rx ( struct net_device *netdev, struct io_buffer *iobuf ) {
301
DBGC2 ( netdev, "NETDEV %s received %p (%p+%zx)\n",
302
netdev->name, iobuf, iobuf->data, iob_len ( iobuf ) );
304
/* Discard packet (for test purposes) if applicable */
305
if ( ( NETDEV_DISCARD_RATE > 0 ) &&
306
( ( random() % NETDEV_DISCARD_RATE ) == 0 ) ) {
307
netdev_rx_err ( netdev, iobuf, -EAGAIN );
312
list_add_tail ( &iobuf->list, &netdev->rx_queue );
314
/* Update statistics counter */
315
netdev_record_stat ( &netdev->rx_stats, 0 );
319
* Discard received packet
321
* @v netdev Network device
322
* @v iobuf I/O buffer, or NULL
323
* @v rc Packet status code
325
* The packet is discarded and an RX error is recorded. This function
326
* takes ownership of the I/O buffer. @c iobuf may be NULL if, for
327
* example, the net device wishes to report an error due to being
328
* unable to allocate an I/O buffer.
330
void netdev_rx_err ( struct net_device *netdev,
331
struct io_buffer *iobuf, int rc ) {
333
DBGC ( netdev, "NETDEV %s failed to receive %p: %s\n",
334
netdev->name, iobuf, strerror ( rc ) );
339
/* Update statistics counter */
340
netdev_record_stat ( &netdev->rx_stats, rc );
344
* Poll for completed and received packets on network device
346
* @v netdev Network device
348
* Polls the network device for completed transmissions and received
349
* packets. Any received packets will be added to the RX packet queue
352
void netdev_poll ( struct net_device *netdev ) {
354
if ( netdev_is_open ( netdev ) )
355
netdev->op->poll ( netdev );
359
* Remove packet from device's receive queue
361
* @v netdev Network device
362
* @ret iobuf I/O buffer, or NULL
364
* Removes the first packet from the device's RX queue and returns it.
365
* Ownership of the packet is transferred to the caller.
367
struct io_buffer * netdev_rx_dequeue ( struct net_device *netdev ) {
368
struct io_buffer *iobuf;
370
iobuf = list_first_entry ( &netdev->rx_queue, struct io_buffer, list );
374
list_del ( &iobuf->list );
379
* Flush device's receive queue
381
* @v netdev Network device
383
static void netdev_rx_flush ( struct net_device *netdev ) {
384
struct io_buffer *iobuf;
386
/* Discard any packets in the RX queue */
387
while ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
388
netdev_rx_err ( netdev, iobuf, -ECANCELED );
393
* Free network device
395
* @v refcnt Network device reference counter
397
static void free_netdev ( struct refcnt *refcnt ) {
398
struct net_device *netdev =
399
container_of ( refcnt, struct net_device, refcnt );
401
netdev_tx_flush ( netdev );
402
netdev_rx_flush ( netdev );
403
clear_settings ( netdev_settings ( netdev ) );
408
* Allocate network device
410
* @v priv_size Size of private data area (net_device::priv)
411
* @ret netdev Network device, or NULL
413
* Allocates space for a network device and its private data area.
415
struct net_device * alloc_netdev ( size_t priv_size ) {
416
struct net_device *netdev;
419
total_len = ( sizeof ( *netdev ) + priv_size );
420
netdev = zalloc ( total_len );
422
ref_init ( &netdev->refcnt, free_netdev );
423
netdev->link_rc = -EUNKNOWN_LINK_STATUS;
424
INIT_LIST_HEAD ( &netdev->tx_queue );
425
INIT_LIST_HEAD ( &netdev->rx_queue );
426
netdev_settings_init ( netdev );
427
netdev->priv = ( ( ( void * ) netdev ) + sizeof ( *netdev ) );
433
* Register network device
435
* @v netdev Network device
436
* @ret rc Return status code
438
* Gives the network device a name and adds it to the list of network
441
int register_netdev ( struct net_device *netdev ) {
442
static unsigned int ifindex = 0;
443
struct net_driver *driver;
446
/* Create device name */
447
if ( netdev->name[0] == '\0' ) {
448
snprintf ( netdev->name, sizeof ( netdev->name ), "net%d",
452
/* Set initial link-layer address, if not already set */
453
if ( ! netdev_has_ll_addr ( netdev ) ) {
454
netdev->ll_protocol->init_addr ( netdev->hw_addr,
458
/* Add to device list */
459
netdev_get ( netdev );
460
list_add_tail ( &netdev->list, &net_devices );
461
DBGC ( netdev, "NETDEV %s registered (phys %s hwaddr %s)\n",
462
netdev->name, netdev->dev->name,
463
netdev_addr ( netdev ) );
465
/* Register per-netdev configuration settings */
466
if ( ( rc = register_settings ( netdev_settings ( netdev ),
467
NULL, netdev->name ) ) != 0 ) {
468
DBGC ( netdev, "NETDEV %s could not register settings: %s\n",
469
netdev->name, strerror ( rc ) );
470
goto err_register_settings;
474
for_each_table_entry ( driver, NET_DRIVERS ) {
475
if ( ( rc = driver->probe ( netdev ) ) != 0 ) {
476
DBGC ( netdev, "NETDEV %s could not add %s device: "
477
"%s\n", netdev->name, driver->name,
486
for_each_table_entry_continue_reverse ( driver, NET_DRIVERS )
487
driver->remove ( netdev );
488
unregister_settings ( netdev_settings ( netdev ) );
489
err_register_settings:
494
* Open network device
496
* @v netdev Network device
497
* @ret rc Return status code
499
int netdev_open ( struct net_device *netdev ) {
502
/* Do nothing if device is already open */
503
if ( netdev->state & NETDEV_OPEN )
506
DBGC ( netdev, "NETDEV %s opening\n", netdev->name );
508
/* Open the device */
509
if ( ( rc = netdev->op->open ( netdev ) ) != 0 )
513
netdev->state |= NETDEV_OPEN;
515
/* Add to head of open devices list */
516
list_add ( &netdev->open_list, &open_net_devices );
518
/* Notify drivers of device state change */
519
netdev_notify ( netdev );
525
* Close network device
527
* @v netdev Network device
529
void netdev_close ( struct net_device *netdev ) {
531
/* Do nothing if device is already closed */
532
if ( ! ( netdev->state & NETDEV_OPEN ) )
535
DBGC ( netdev, "NETDEV %s closing\n", netdev->name );
537
/* Remove from open devices list */
538
list_del ( &netdev->open_list );
541
netdev->state &= ~NETDEV_OPEN;
543
/* Notify drivers of device state change */
544
netdev_notify ( netdev );
546
/* Close the device */
547
netdev->op->close ( netdev );
549
/* Flush TX and RX queues */
550
netdev_tx_flush ( netdev );
551
netdev_rx_flush ( netdev );
555
* Unregister network device
557
* @v netdev Network device
559
* Removes the network device from the list of network devices.
561
void unregister_netdev ( struct net_device *netdev ) {
562
struct net_driver *driver;
564
/* Ensure device is closed */
565
netdev_close ( netdev );
568
for_each_table_entry_reverse ( driver, NET_DRIVERS )
569
driver->remove ( netdev );
571
/* Unregister per-netdev configuration settings */
572
unregister_settings ( netdev_settings ( netdev ) );
574
/* Remove from device list */
575
list_del ( &netdev->list );
576
netdev_put ( netdev );
577
DBGC ( netdev, "NETDEV %s unregistered\n", netdev->name );
580
/** Enable or disable interrupts
582
* @v netdev Network device
583
* @v enable Interrupts should be enabled
585
void netdev_irq ( struct net_device *netdev, int enable ) {
587
/* Do nothing if device does not support interrupts */
588
if ( ! netdev_irq_supported ( netdev ) )
591
/* Enable or disable device interrupts */
592
netdev->op->irq ( netdev, enable );
594
/* Record interrupt enabled state */
595
netdev->state &= ~NETDEV_IRQ_ENABLED;
597
netdev->state |= NETDEV_IRQ_ENABLED;
601
* Get network device by name
603
* @v name Network device name
604
* @ret netdev Network device, or NULL
606
struct net_device * find_netdev ( const char *name ) {
607
struct net_device *netdev;
609
list_for_each_entry ( netdev, &net_devices, list ) {
610
if ( strcmp ( netdev->name, name ) == 0 )
618
* Get network device by PCI bus:dev.fn address
620
* @v bus_type Bus type
621
* @v location Bus location
622
* @ret netdev Network device, or NULL
624
struct net_device * find_netdev_by_location ( unsigned int bus_type,
625
unsigned int location ) {
626
struct net_device *netdev;
628
list_for_each_entry ( netdev, &net_devices, list ) {
629
if ( ( netdev->dev->desc.bus_type == bus_type ) &&
630
( netdev->dev->desc.location == location ) )
638
* Get most recently opened network device
640
* @ret netdev Most recently opened network device, or NULL
642
struct net_device * last_opened_netdev ( void ) {
643
struct net_device *netdev;
645
netdev = list_first_entry ( &open_net_devices, struct net_device,
650
assert ( netdev_is_open ( netdev ) );
655
* Transmit network-layer packet
657
* @v iobuf I/O buffer
658
* @v netdev Network device
659
* @v net_protocol Network-layer protocol
660
* @v ll_dest Destination link-layer address
661
* @v ll_source Source link-layer address
662
* @ret rc Return status code
664
* Prepends link-layer headers to the I/O buffer and transmits the
665
* packet via the specified network device. This function takes
666
* ownership of the I/O buffer.
668
int net_tx ( struct io_buffer *iobuf, struct net_device *netdev,
669
struct net_protocol *net_protocol, const void *ll_dest,
670
const void *ll_source ) {
671
struct ll_protocol *ll_protocol = netdev->ll_protocol;
674
/* Force a poll on the netdevice to (potentially) clear any
675
* backed-up TX completions. This is needed on some network
676
* devices to avoid excessive losses due to small TX ring
679
netdev_poll ( netdev );
681
/* Add link-layer header */
682
if ( ( rc = ll_protocol->push ( netdev, iobuf, ll_dest, ll_source,
683
net_protocol->net_proto ) ) != 0 ) {
684
/* Record error for diagnosis */
685
netdev_tx_err ( netdev, iobuf, rc );
689
/* Transmit packet */
690
return netdev_tx ( netdev, iobuf );
694
* Process received network-layer packet
696
* @v iobuf I/O buffer
697
* @v netdev Network device
698
* @v net_proto Network-layer protocol, in network-byte order
699
* @v ll_dest Destination link-layer address
700
* @v ll_source Source link-layer address
701
* @v flags Packet flags
702
* @ret rc Return status code
704
int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
705
uint16_t net_proto, const void *ll_dest, const void *ll_source,
706
unsigned int flags ) {
707
struct net_protocol *net_protocol;
709
/* Hand off to network-layer protocol, if any */
710
for_each_table_entry ( net_protocol, NET_PROTOCOLS ) {
711
if ( net_protocol->net_proto == net_proto )
712
return net_protocol->rx ( iobuf, netdev, ll_dest,
716
DBGC ( netdev, "NETDEV %s unknown network protocol %04x\n",
717
netdev->name, ntohs ( net_proto ) );
723
* Poll the network stack
725
* This polls all interfaces for received packets, and processes
726
* packets from the RX queue.
728
void net_poll ( void ) {
729
struct net_device *netdev;
730
struct io_buffer *iobuf;
731
struct ll_protocol *ll_protocol;
733
const void *ll_source;
738
/* Poll and process each network device */
739
list_for_each_entry ( netdev, &net_devices, list ) {
741
/* Poll for new packets */
742
netdev_poll ( netdev );
744
/* Leave received packets on the queue if receive
745
* queue processing is currently frozen. This will
746
* happen when the raw packets are to be manually
747
* dequeued using netdev_rx_dequeue(), rather than
748
* processed via the usual networking stack.
750
if ( netdev_rx_frozen ( netdev ) )
753
/* Process at most one received packet. Give priority
754
* to getting packets out of the NIC over processing
755
* the received packets, because we advertise a window
756
* that assumes that we can receive packets from the
757
* NIC faster than they arrive.
759
if ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
761
DBGC2 ( netdev, "NETDEV %s processing %p (%p+%zx)\n",
762
netdev->name, iobuf, iobuf->data,
765
/* Remove link-layer header */
766
ll_protocol = netdev->ll_protocol;
767
if ( ( rc = ll_protocol->pull ( netdev, iobuf,
768
&ll_dest, &ll_source,
775
/* Hand packet to network layer */
776
if ( ( rc = net_rx ( iob_disown ( iobuf ), netdev,
778
ll_source, flags ) ) != 0 ) {
779
/* Record error for diagnosis */
780
netdev_rx_err ( netdev, NULL, rc );
787
* Single-step the network stack
789
* @v process Network stack process
791
static void net_step ( struct process *process __unused ) {
795
/** Networking stack process */
796
PERMANENT_PROCESS ( net_process, net_step );