~ubuntu-branches/ubuntu/trusty/virtualbox-lts-xenial/trusty-proposed

« back to all changes in this revision

Viewing changes to src/VBox/Devices/PC/ipxe/src/net/netdevice.c

  • Committer: Package Import Robot
  • Author(s): Gianfranco Costamagna
  • Date: 2016-02-23 14:28:26 UTC
  • Revision ID: package-import@ubuntu.com-20160223142826-bdu69el2z6wa2a44
Tags: upstream-4.3.36-dfsg
ImportĀ upstreamĀ versionĀ 4.3.36-dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
 
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
 * Check whether or not network device has a link-layer address
 
67
 *
 
68
 * @v netdev            Network device
 
69
 * @ret has_ll_addr     Network device has a link-layer address
 
70
 */
 
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 );
 
74
 
 
75
        while ( remaining-- ) {
 
76
                if ( *(ll_addr++) != 0 )
 
77
                        return 1;
 
78
        }
 
79
        return 0;
 
80
}
 
81
 
 
82
/**
 
83
 * Notify drivers of network device or link state change
 
84
 *
 
85
 * @v netdev            Network device
 
86
 */
 
87
static void netdev_notify ( struct net_device *netdev ) {
 
88
        struct net_driver *driver;
 
89
 
 
90
        for_each_table_entry ( driver, NET_DRIVERS )
 
91
                driver->notify ( netdev );
 
92
}
 
93
 
 
94
/**
 
95
 * Mark network device as having a specific link state
 
96
 *
 
97
 * @v netdev            Network device
 
98
 * @v rc                Link status code
 
99
 */
 
100
void netdev_link_err ( struct net_device *netdev, int rc ) {
 
101
 
 
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 );
 
106
        } else {
 
107
                DBGC ( netdev, "NETDEV %s link is down: %s\n",
 
108
                       netdev->name, strerror ( netdev->link_rc ) );
 
109
        }
 
110
 
 
111
        /* Notify drivers of link state change */
 
112
        netdev_notify ( netdev );
 
113
}
 
114
 
 
115
/**
 
116
 * Mark network device as having link down
 
117
 *
 
118
 * @v netdev            Network device
 
119
 */
 
120
void netdev_link_down ( struct net_device *netdev ) {
 
121
 
 
122
        /* Avoid clobbering a more detailed link status code, if one
 
123
         * is already set.
 
124
         */
 
125
        if ( ( netdev->link_rc == 0 ) ||
 
126
             ( netdev->link_rc == -EUNKNOWN_LINK_STATUS ) ) {
 
127
                netdev_link_err ( netdev, -ENOTCONN_LINK_DOWN );
 
128
        }
 
129
}
 
130
 
 
131
/**
 
132
 * Record network device statistic
 
133
 *
 
134
 * @v stats             Network device statistics
 
135
 * @v rc                Status code
 
136
 */
 
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;
 
140
        unsigned int i;
 
141
 
 
142
        /* If this is not an error, just update the good counter */
 
143
        if ( rc == 0 ) {
 
144
                stats->good++;
 
145
                return;
 
146
        }
 
147
 
 
148
        /* Update the bad counter */
 
149
        stats->bad++;
 
150
 
 
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 ) {
 
158
                        error->count++;
 
159
                        return;
 
160
                }
 
161
                if ( error->count < least_common_error->count )
 
162
                        least_common_error = error;
 
163
        }
 
164
 
 
165
        /* Overwrite the least common error record */
 
166
        least_common_error->rc = rc;
 
167
        least_common_error->count = 1;
 
168
}
 
169
 
 
170
/**
 
171
 * Transmit raw packet via network device
 
172
 *
 
173
 * @v netdev            Network device
 
174
 * @v iobuf             I/O buffer
 
175
 * @ret rc              Return status code
 
176
 *
 
177
 * Transmits the packet via the specified network device.  This
 
178
 * function takes ownership of the I/O buffer.
 
179
 */
 
180
int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf ) {
 
181
        int rc;
 
182
 
 
183
        DBGC2 ( netdev, "NETDEV %s transmitting %p (%p+%zx)\n",
 
184
                netdev->name, iobuf, iobuf->data, iob_len ( iobuf ) );
 
185
 
 
186
        /* Enqueue packet */
 
187
        list_add_tail ( &iobuf->list, &netdev->tx_queue );
 
188
 
 
189
        /* Avoid calling transmit() on unopened network devices */
 
190
        if ( ! netdev_is_open ( netdev ) ) {
 
191
                rc = -ENETUNREACH;
 
192
                goto err;
 
193
        }
 
194
 
 
195
        /* Discard packet (for test purposes) if applicable */
 
196
        if ( ( NETDEV_DISCARD_RATE > 0 ) &&
 
197
             ( ( random() % NETDEV_DISCARD_RATE ) == 0 ) ) {
 
198
                rc = -EAGAIN;
 
199
                goto err;
 
200
        }
 
201
 
 
202
        /* Transmit packet */
 
203
        if ( ( rc = netdev->op->transmit ( netdev, iobuf ) ) != 0 )
 
204
                goto err;
 
205
 
 
206
        return 0;
 
207
 
 
208
 err:
 
209
        netdev_tx_complete_err ( netdev, iobuf, rc );
 
210
        return rc;
 
211
}
 
212
 
 
213
/**
 
214
 * Discard transmitted packet
 
215
 *
 
216
 * @v netdev            Network device
 
217
 * @v iobuf             I/O buffer, or NULL
 
218
 * @v rc                Packet status code
 
219
 *
 
220
 * The packet is discarded and a TX error is recorded.  This function
 
221
 * takes ownership of the I/O buffer.
 
222
 */
 
223
void netdev_tx_err ( struct net_device *netdev,
 
224
                     struct io_buffer *iobuf, int rc ) {
 
225
 
 
226
        /* Update statistics counter */
 
227
        netdev_record_stat ( &netdev->tx_stats, rc );
 
228
        if ( rc == 0 ) {
 
229
                DBGC2 ( netdev, "NETDEV %s transmission %p complete\n",
 
230
                        netdev->name, iobuf );
 
231
        } else {
 
232
                DBGC ( netdev, "NETDEV %s transmission %p failed: %s\n",
 
233
                       netdev->name, iobuf, strerror ( rc ) );
 
234
        }
 
235
 
 
236
        /* Discard packet */
 
237
        free_iob ( iobuf );
 
238
}
 
239
 
 
240
/**
 
241
 * Complete network transmission
 
242
 *
 
243
 * @v netdev            Network device
 
244
 * @v iobuf             I/O buffer
 
245
 * @v rc                Packet status code
 
246
 *
 
247
 * The packet must currently be in the network device's TX queue.
 
248
 */
 
249
void netdev_tx_complete_err ( struct net_device *netdev,
 
250
                              struct io_buffer *iobuf, int rc ) {
 
251
 
 
252
        /* Catch data corruption as early as possible */
 
253
        list_check_contains_entry ( iobuf, &netdev->tx_queue, list );
 
254
 
 
255
        /* Dequeue and free I/O buffer */
 
256
        list_del ( &iobuf->list );
 
257
        netdev_tx_err ( netdev, iobuf, rc );
 
258
}
 
259
 
 
260
/**
 
261
 * Complete network transmission
 
262
 *
 
263
 * @v netdev            Network device
 
264
 * @v rc                Packet status code
 
265
 *
 
266
 * Completes the oldest outstanding packet in the TX queue.
 
267
 */
 
268
void netdev_tx_complete_next_err ( struct net_device *netdev, int rc ) {
 
269
        struct io_buffer *iobuf;
 
270
 
 
271
        list_for_each_entry ( iobuf, &netdev->tx_queue, list ) {
 
272
                netdev_tx_complete_err ( netdev, iobuf, rc );
 
273
                return;
 
274
        }
 
275
}
 
276
 
 
277
/**
 
278
 * Flush device's transmit queue
 
279
 *
 
280
 * @v netdev            Network device
 
281
 */
 
282
static void netdev_tx_flush ( struct net_device *netdev ) {
 
283
 
 
284
        /* Discard any packets in the TX queue */
 
285
        while ( ! list_empty ( &netdev->tx_queue ) ) {
 
286
                netdev_tx_complete_next_err ( netdev, -ECANCELED );
 
287
        }
 
288
}
 
289
 
 
290
/**
 
291
 * Add packet to receive queue
 
292
 *
 
293
 * @v netdev            Network device
 
294
 * @v iobuf             I/O buffer, or NULL
 
295
 *
 
296
 * The packet is added to the network device's RX queue.  This
 
297
 * function takes ownership of the I/O buffer.
 
298
 */
 
299
void netdev_rx ( struct net_device *netdev, struct io_buffer *iobuf ) {
 
300
 
 
301
        DBGC2 ( netdev, "NETDEV %s received %p (%p+%zx)\n",
 
302
                netdev->name, iobuf, iobuf->data, iob_len ( iobuf ) );
 
303
 
 
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 );
 
308
                return;
 
309
        }
 
310
 
 
311
        /* Enqueue packet */
 
312
        list_add_tail ( &iobuf->list, &netdev->rx_queue );
 
313
 
 
314
        /* Update statistics counter */
 
315
        netdev_record_stat ( &netdev->rx_stats, 0 );
 
316
}
 
317
 
 
318
/**
 
319
 * Discard received packet
 
320
 *
 
321
 * @v netdev            Network device
 
322
 * @v iobuf             I/O buffer, or NULL
 
323
 * @v rc                Packet status code
 
324
 *
 
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.
 
329
 */
 
330
void netdev_rx_err ( struct net_device *netdev,
 
331
                     struct io_buffer *iobuf, int rc ) {
 
332
 
 
333
        DBGC ( netdev, "NETDEV %s failed to receive %p: %s\n",
 
334
               netdev->name, iobuf, strerror ( rc ) );
 
335
 
 
336
        /* Discard packet */
 
337
        free_iob ( iobuf );
 
338
 
 
339
        /* Update statistics counter */
 
340
        netdev_record_stat ( &netdev->rx_stats, rc );
 
341
}
 
342
 
 
343
/**
 
344
 * Poll for completed and received packets on network device
 
345
 *
 
346
 * @v netdev            Network device
 
347
 *
 
348
 * Polls the network device for completed transmissions and received
 
349
 * packets.  Any received packets will be added to the RX packet queue
 
350
 * via netdev_rx().
 
351
 */
 
352
void netdev_poll ( struct net_device *netdev ) {
 
353
 
 
354
        if ( netdev_is_open ( netdev ) )
 
355
                netdev->op->poll ( netdev );
 
356
}
 
357
 
 
358
/**
 
359
 * Remove packet from device's receive queue
 
360
 *
 
361
 * @v netdev            Network device
 
362
 * @ret iobuf           I/O buffer, or NULL
 
363
 *
 
364
 * Removes the first packet from the device's RX queue and returns it.
 
365
 * Ownership of the packet is transferred to the caller.
 
366
 */
 
367
struct io_buffer * netdev_rx_dequeue ( struct net_device *netdev ) {
 
368
        struct io_buffer *iobuf;
 
369
 
 
370
        iobuf = list_first_entry ( &netdev->rx_queue, struct io_buffer, list );
 
371
        if ( ! iobuf )
 
372
                return NULL;
 
373
 
 
374
        list_del ( &iobuf->list );
 
375
        return iobuf;
 
376
}
 
377
 
 
378
/**
 
379
 * Flush device's receive queue
 
380
 *
 
381
 * @v netdev            Network device
 
382
 */
 
383
static void netdev_rx_flush ( struct net_device *netdev ) {
 
384
        struct io_buffer *iobuf;
 
385
 
 
386
        /* Discard any packets in the RX queue */
 
387
        while ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
 
388
                netdev_rx_err ( netdev, iobuf, -ECANCELED );
 
389
        }
 
390
}
 
391
 
 
392
/**
 
393
 * Free network device
 
394
 *
 
395
 * @v refcnt            Network device reference counter
 
396
 */
 
397
static void free_netdev ( struct refcnt *refcnt ) {
 
398
        struct net_device *netdev =
 
399
                container_of ( refcnt, struct net_device, refcnt );
 
400
        
 
401
        netdev_tx_flush ( netdev );
 
402
        netdev_rx_flush ( netdev );
 
403
        clear_settings ( netdev_settings ( netdev ) );
 
404
        free ( netdev );
 
405
}
 
406
 
 
407
/**
 
408
 * Allocate network device
 
409
 *
 
410
 * @v priv_size         Size of private data area (net_device::priv)
 
411
 * @ret netdev          Network device, or NULL
 
412
 *
 
413
 * Allocates space for a network device and its private data area.
 
414
 */
 
415
struct net_device * alloc_netdev ( size_t priv_size ) {
 
416
        struct net_device *netdev;
 
417
        size_t total_len;
 
418
 
 
419
        total_len = ( sizeof ( *netdev ) + priv_size );
 
420
        netdev = zalloc ( total_len );
 
421
        if ( netdev ) {
 
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 ) );
 
428
        }
 
429
        return netdev;
 
430
}
 
431
 
 
432
/**
 
433
 * Register network device
 
434
 *
 
435
 * @v netdev            Network device
 
436
 * @ret rc              Return status code
 
437
 *
 
438
 * Gives the network device a name and adds it to the list of network
 
439
 * devices.
 
440
 */
 
441
int register_netdev ( struct net_device *netdev ) {
 
442
        static unsigned int ifindex = 0;
 
443
        struct net_driver *driver;
 
444
        int rc;
 
445
 
 
446
        /* Create device name */
 
447
        if ( netdev->name[0] == '\0' ) {
 
448
                snprintf ( netdev->name, sizeof ( netdev->name ), "net%d",
 
449
                           ifindex++ );
 
450
        }
 
451
 
 
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,
 
455
                                                 netdev->ll_addr );
 
456
        }
 
457
 
 
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 ) );
 
464
 
 
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;
 
471
        }
 
472
 
 
473
        /* Probe device */
 
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,
 
478
                               strerror ( rc ) );
 
479
                        goto err_probe;
 
480
                }
 
481
        }
 
482
 
 
483
        return 0;
 
484
 
 
485
 err_probe:
 
486
        for_each_table_entry_continue_reverse ( driver, NET_DRIVERS )
 
487
                driver->remove ( netdev );
 
488
        unregister_settings ( netdev_settings ( netdev ) );
 
489
 err_register_settings:
 
490
        return rc;
 
491
}
 
492
 
 
493
/**
 
494
 * Open network device
 
495
 *
 
496
 * @v netdev            Network device
 
497
 * @ret rc              Return status code
 
498
 */
 
499
int netdev_open ( struct net_device *netdev ) {
 
500
        int rc;
 
501
 
 
502
        /* Do nothing if device is already open */
 
503
        if ( netdev->state & NETDEV_OPEN )
 
504
                return 0;
 
505
 
 
506
        DBGC ( netdev, "NETDEV %s opening\n", netdev->name );
 
507
 
 
508
        /* Open the device */
 
509
        if ( ( rc = netdev->op->open ( netdev ) ) != 0 )
 
510
                return rc;
 
511
 
 
512
        /* Mark as opened */
 
513
        netdev->state |= NETDEV_OPEN;
 
514
 
 
515
        /* Add to head of open devices list */
 
516
        list_add ( &netdev->open_list, &open_net_devices );
 
517
 
 
518
        /* Notify drivers of device state change */
 
519
        netdev_notify ( netdev );
 
520
 
 
521
        return 0;
 
522
}
 
523
 
 
524
/**
 
525
 * Close network device
 
526
 *
 
527
 * @v netdev            Network device
 
528
 */
 
529
void netdev_close ( struct net_device *netdev ) {
 
530
 
 
531
        /* Do nothing if device is already closed */
 
532
        if ( ! ( netdev->state & NETDEV_OPEN ) )
 
533
                return;
 
534
 
 
535
        DBGC ( netdev, "NETDEV %s closing\n", netdev->name );
 
536
 
 
537
        /* Remove from open devices list */
 
538
        list_del ( &netdev->open_list );
 
539
 
 
540
        /* Mark as closed */
 
541
        netdev->state &= ~NETDEV_OPEN;
 
542
 
 
543
        /* Notify drivers of device state change */
 
544
        netdev_notify ( netdev );
 
545
 
 
546
        /* Close the device */
 
547
        netdev->op->close ( netdev );
 
548
 
 
549
        /* Flush TX and RX queues */
 
550
        netdev_tx_flush ( netdev );
 
551
        netdev_rx_flush ( netdev );
 
552
}
 
553
 
 
554
/**
 
555
 * Unregister network device
 
556
 *
 
557
 * @v netdev            Network device
 
558
 *
 
559
 * Removes the network device from the list of network devices.
 
560
 */
 
561
void unregister_netdev ( struct net_device *netdev ) {
 
562
        struct net_driver *driver;
 
563
 
 
564
        /* Ensure device is closed */
 
565
        netdev_close ( netdev );
 
566
 
 
567
        /* Remove device */
 
568
        for_each_table_entry_reverse ( driver, NET_DRIVERS )
 
569
                driver->remove ( netdev );
 
570
 
 
571
        /* Unregister per-netdev configuration settings */
 
572
        unregister_settings ( netdev_settings ( netdev ) );
 
573
 
 
574
        /* Remove from device list */
 
575
        list_del ( &netdev->list );
 
576
        netdev_put ( netdev );
 
577
        DBGC ( netdev, "NETDEV %s unregistered\n", netdev->name );
 
578
}
 
579
 
 
580
/** Enable or disable interrupts
 
581
 *
 
582
 * @v netdev            Network device
 
583
 * @v enable            Interrupts should be enabled
 
584
 */
 
585
void netdev_irq ( struct net_device *netdev, int enable ) {
 
586
 
 
587
        /* Do nothing if device does not support interrupts */
 
588
        if ( ! netdev_irq_supported ( netdev ) )
 
589
                return;
 
590
 
 
591
        /* Enable or disable device interrupts */
 
592
        netdev->op->irq ( netdev, enable );
 
593
 
 
594
        /* Record interrupt enabled state */
 
595
        netdev->state &= ~NETDEV_IRQ_ENABLED;
 
596
        if ( enable )
 
597
                netdev->state |= NETDEV_IRQ_ENABLED;
 
598
}
 
599
 
 
600
/**
 
601
 * Get network device by name
 
602
 *
 
603
 * @v name              Network device name
 
604
 * @ret netdev          Network device, or NULL
 
605
 */
 
606
struct net_device * find_netdev ( const char *name ) {
 
607
        struct net_device *netdev;
 
608
 
 
609
        list_for_each_entry ( netdev, &net_devices, list ) {
 
610
                if ( strcmp ( netdev->name, name ) == 0 )
 
611
                        return netdev;
 
612
        }
 
613
 
 
614
        return NULL;
 
615
}
 
616
 
 
617
/**
 
618
 * Get network device by PCI bus:dev.fn address
 
619
 *
 
620
 * @v bus_type          Bus type
 
621
 * @v location          Bus location
 
622
 * @ret netdev          Network device, or NULL
 
623
 */
 
624
struct net_device * find_netdev_by_location ( unsigned int bus_type,
 
625
                                              unsigned int location ) {
 
626
        struct net_device *netdev;
 
627
 
 
628
        list_for_each_entry ( netdev, &net_devices, list ) {
 
629
                if ( ( netdev->dev->desc.bus_type == bus_type ) &&
 
630
                     ( netdev->dev->desc.location == location ) )
 
631
                        return netdev;
 
632
        }
 
633
 
 
634
        return NULL;    
 
635
}
 
636
 
 
637
/**
 
638
 * Get most recently opened network device
 
639
 *
 
640
 * @ret netdev          Most recently opened network device, or NULL
 
641
 */
 
642
struct net_device * last_opened_netdev ( void ) {
 
643
        struct net_device *netdev;
 
644
 
 
645
        netdev = list_first_entry ( &open_net_devices, struct net_device,
 
646
                                    open_list );
 
647
        if ( ! netdev )
 
648
                return NULL;
 
649
 
 
650
        assert ( netdev_is_open ( netdev ) );
 
651
        return netdev;
 
652
}
 
653
 
 
654
/**
 
655
 * Transmit network-layer packet
 
656
 *
 
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
 
663
 *
 
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.
 
667
 */
 
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;
 
672
        int rc;
 
673
 
 
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
 
677
         * sizes.
 
678
         */
 
679
        netdev_poll ( netdev );
 
680
 
 
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 );
 
686
                return rc;
 
687
        }
 
688
 
 
689
        /* Transmit packet */
 
690
        return netdev_tx ( netdev, iobuf );
 
691
}
 
692
 
 
693
/**
 
694
 * Process received network-layer packet
 
695
 *
 
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
 
703
 */
 
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;
 
708
 
 
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,
 
713
                                                  ll_source, flags );
 
714
        }
 
715
 
 
716
        DBGC ( netdev, "NETDEV %s unknown network protocol %04x\n",
 
717
               netdev->name, ntohs ( net_proto ) );
 
718
        free_iob ( iobuf );
 
719
        return -ENOTSUP;
 
720
}
 
721
 
 
722
/**
 
723
 * Poll the network stack
 
724
 *
 
725
 * This polls all interfaces for received packets, and processes
 
726
 * packets from the RX queue.
 
727
 */
 
728
void net_poll ( void ) {
 
729
        struct net_device *netdev;
 
730
        struct io_buffer *iobuf;
 
731
        struct ll_protocol *ll_protocol;
 
732
        const void *ll_dest;
 
733
        const void *ll_source;
 
734
        uint16_t net_proto;
 
735
        unsigned int flags;
 
736
        int rc;
 
737
 
 
738
        /* Poll and process each network device */
 
739
        list_for_each_entry ( netdev, &net_devices, list ) {
 
740
 
 
741
                /* Poll for new packets */
 
742
                netdev_poll ( netdev );
 
743
 
 
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.
 
749
                 */
 
750
                if ( netdev_rx_frozen ( netdev ) )
 
751
                        continue;
 
752
 
 
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.
 
758
                 */
 
759
                if ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
 
760
 
 
761
                        DBGC2 ( netdev, "NETDEV %s processing %p (%p+%zx)\n",
 
762
                                netdev->name, iobuf, iobuf->data,
 
763
                                iob_len ( iobuf ) );
 
764
 
 
765
                        /* Remove link-layer header */
 
766
                        ll_protocol = netdev->ll_protocol;
 
767
                        if ( ( rc = ll_protocol->pull ( netdev, iobuf,
 
768
                                                        &ll_dest, &ll_source,
 
769
                                                        &net_proto,
 
770
                                                        &flags ) ) != 0 ) {
 
771
                                free_iob ( iobuf );
 
772
                                continue;
 
773
                        }
 
774
 
 
775
                        /* Hand packet to network layer */
 
776
                        if ( ( rc = net_rx ( iob_disown ( iobuf ), netdev,
 
777
                                             net_proto, ll_dest,
 
778
                                             ll_source, flags ) ) != 0 ) {
 
779
                                /* Record error for diagnosis */
 
780
                                netdev_rx_err ( netdev, NULL, rc );
 
781
                        }
 
782
                }
 
783
        }
 
784
}
 
785
 
 
786
/**
 
787
 * Single-step the network stack
 
788
 *
 
789
 * @v process           Network stack process
 
790
 */
 
791
static void net_step ( struct process *process __unused ) {
 
792
        net_poll();
 
793
}
 
794
 
 
795
/** Networking stack process */
 
796
PERMANENT_PROCESS ( net_process, net_step );