Allow recording of TX and RX errors to aid in end-user debugging.
[people/xl0/gpxe-arm.git] / src / net / netdevice.c
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 #include <stdint.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <byteswap.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <gpxe/if_ether.h>
26 #include <gpxe/iobuf.h>
27 #include <gpxe/tables.h>
28 #include <gpxe/process.h>
29 #include <gpxe/init.h>
30 #include <gpxe/device.h>
31 #include <gpxe/netdevice.h>
32
33 /** @file
34  *
35  * Network device management
36  *
37  */
38
39 /** Registered network-layer protocols */
40 static struct net_protocol net_protocols[0]
41         __table_start ( struct net_protocol, net_protocols );
42 static struct net_protocol net_protocols_end[0]
43         __table_end ( struct net_protocol, net_protocols );
44
45 /** List of network devices */
46 struct list_head net_devices = LIST_HEAD_INIT ( net_devices );
47
48 /**
49  * Transmit raw packet via network device
50  *
51  * @v netdev            Network device
52  * @v iobuf             I/O buffer
53  * @ret rc              Return status code
54  *
55  * Transmits the packet via the specified network device.  This
56  * function takes ownership of the I/O buffer.
57  */
58 int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf ) {
59         int rc;
60
61         DBGC ( netdev, "NETDEV %p transmitting %p (%p+%zx)\n",
62                netdev, iobuf, iobuf->data, iob_len ( iobuf ) );
63
64         list_add_tail ( &iobuf->list, &netdev->tx_queue );
65
66         if ( ! ( netdev->state & NETDEV_OPEN ) ) {
67                 rc = -ENETUNREACH;
68                 goto err;
69         }
70                 
71         if ( ( rc = netdev->transmit ( netdev, iobuf ) ) != 0 )
72                 goto err;
73
74         return 0;
75
76  err:
77         netdev_tx_complete_err ( netdev, iobuf, rc );
78         return rc;
79 }
80
81 /**
82  * Complete network transmission
83  *
84  * @v netdev            Network device
85  * @v iobuf             I/O buffer
86  * @v rc                Packet status code
87  *
88  * The packet must currently be in the network device's TX queue.
89  */
90 void netdev_tx_complete_err ( struct net_device *netdev,
91                               struct io_buffer *iobuf, int rc ) {
92
93         /* Update statistics counter */
94         if ( rc == 0 ) {
95                 netdev->stats.tx_ok++;
96                 DBGC ( netdev, "NETDEV %p transmission %p complete\n",
97                        netdev, iobuf );
98         } else {
99                 netdev->stats.tx_err++;
100                 DBGC ( netdev, "NETDEV %p transmission %p failed: %s\n",
101                        netdev, iobuf, strerror ( rc ) );
102         }
103
104         /* Catch data corruption as early as possible */
105         assert ( iobuf->list.next != NULL );
106         assert ( iobuf->list.prev != NULL );
107
108         /* Dequeue and free I/O buffer */
109         list_del ( &iobuf->list );
110         free_iob ( iobuf );
111 }
112
113 /**
114  * Complete network transmission
115  *
116  * @v netdev            Network device
117  * @v rc                Packet status code
118  *
119  * Completes the oldest outstanding packet in the TX queue.
120  */
121 void netdev_tx_complete_next_err ( struct net_device *netdev, int rc ) {
122         struct io_buffer *iobuf;
123
124         list_for_each_entry ( iobuf, &netdev->tx_queue, list ) {
125                 netdev_tx_complete_err ( netdev, iobuf, rc );
126                 return;
127         }
128 }
129
130 /**
131  * Flush device's transmit queue
132  *
133  * @v netdev            Network device
134  */
135 static void netdev_tx_flush ( struct net_device *netdev ) {
136
137         /* Discard any packets in the TX queue */
138         while ( ! list_empty ( &netdev->tx_queue ) ) {
139                 netdev_tx_complete_next_err ( netdev, -ECANCELED );
140         }
141 }
142
143 /**
144  * Add packet to receive queue
145  *
146  * @v netdev            Network device
147  * @v iobuf             I/O buffer, or NULL
148  *
149  * The packet is added to the network device's RX queue.  This
150  * function takes ownership of the I/O buffer.
151  */
152 void netdev_rx ( struct net_device *netdev, struct io_buffer *iobuf ) {
153
154         DBGC ( netdev, "NETDEV %p received %p (%p+%zx)\n",
155                netdev, iobuf, iobuf->data, iob_len ( iobuf ) );
156
157         /* Enqueue packet */
158         list_add_tail ( &iobuf->list, &netdev->rx_queue );
159
160         /* Update statistics counter */
161         netdev->stats.rx_ok++;
162 }
163
164 /**
165  * Discard received packet
166  *
167  * @v netdev            Network device
168  * @v iobuf             I/O buffer, or NULL
169  * @v rc                Packet status code
170  *
171  * The packet is discarded and an RX error is recorded.  This function
172  * takes ownership of the I/O buffer.  @c iobuf may be NULL if, for
173  * example, the net device wishes to report an error due to being
174  * unable to allocate an I/O buffer.
175  */
176 void netdev_rx_err ( struct net_device *netdev,
177                      struct io_buffer *iobuf, int rc ) {
178
179         DBGC ( netdev, "NETDEV %p failed to receive %p: %s\n",
180                netdev, iobuf, strerror ( rc ) );
181
182         /* Discard packet */
183         free_iob ( iobuf );
184
185         /* Update statistics counter */
186         netdev->stats.rx_err++;
187 }
188
189 /**
190  * Poll for packet on network device
191  *
192  * @v netdev            Network device
193  * @v rx_quota          Maximum number of packets to receive
194  * @ret True            There are packets present in the receive queue
195  * @ret False           There are no packets present in the receive queue
196  *
197  * Polls the network device for received packets.  Any received
198  * packets will be added to the RX packet queue via netdev_rx().
199  */
200 int netdev_poll ( struct net_device *netdev, unsigned int rx_quota ) {
201
202         if ( netdev->state & NETDEV_OPEN )
203                 netdev->poll ( netdev, rx_quota );
204
205         return ( ! list_empty ( &netdev->rx_queue ) );
206 }
207
208 /**
209  * Remove packet from device's receive queue
210  *
211  * @v netdev            Network device
212  * @ret iobuf           I/O buffer, or NULL
213  *
214  * Removes the first packet from the device's RX queue and returns it.
215  * Ownership of the packet is transferred to the caller.
216  */
217 struct io_buffer * netdev_rx_dequeue ( struct net_device *netdev ) {
218         struct io_buffer *iobuf;
219
220         list_for_each_entry ( iobuf, &netdev->rx_queue, list ) {
221                 list_del ( &iobuf->list );
222                 return iobuf;
223         }
224         return NULL;
225 }
226
227 /**
228  * Flush device's receive queue
229  *
230  * @v netdev            Network device
231  */
232 static void netdev_rx_flush ( struct net_device *netdev ) {
233         struct io_buffer *iobuf;
234
235         /* Discard any packets in the RX queue */
236         while ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
237                 netdev_rx_err ( netdev, iobuf, -ECANCELED );
238         }
239 }
240
241 /**
242  * Free network device
243  *
244  * @v refcnt            Network device reference counter
245  */
246 static void free_netdev ( struct refcnt *refcnt ) {
247         struct net_device *netdev =
248                 container_of ( refcnt, struct net_device, refcnt );
249         
250         netdev_tx_flush ( netdev );
251         netdev_rx_flush ( netdev );
252         free ( netdev );
253 }
254
255 /**
256  * Allocate network device
257  *
258  * @v priv_size         Size of private data area (net_device::priv)
259  * @ret netdev          Network device, or NULL
260  *
261  * Allocates space for a network device and its private data area.
262  */
263 struct net_device * alloc_netdev ( size_t priv_size ) {
264         struct net_device *netdev;
265         size_t total_len;
266
267         total_len = ( sizeof ( *netdev ) + priv_size );
268         netdev = malloc ( total_len );
269         if ( netdev ) {
270                 memset ( netdev, 0, total_len );
271                 netdev->refcnt.free = free_netdev;
272                 INIT_LIST_HEAD ( &netdev->tx_queue );
273                 INIT_LIST_HEAD ( &netdev->rx_queue );
274                 netdev->priv = ( ( ( void * ) netdev ) + sizeof ( *netdev ) );
275         }
276         return netdev;
277 }
278
279 /**
280  * Register network device
281  *
282  * @v netdev            Network device
283  * @ret rc              Return status code
284  *
285  * Gives the network device a name and adds it to the list of network
286  * devices.
287  */
288 int register_netdev ( struct net_device *netdev ) {
289         static unsigned int ifindex = 0;
290
291         /* Create device name */
292         snprintf ( netdev->name, sizeof ( netdev->name ), "net%d",
293                    ifindex++ );
294
295         /* Add to device list */
296         netdev_get ( netdev );
297         list_add_tail ( &netdev->list, &net_devices );
298         DBGC ( netdev, "NETDEV %p registered as %s (phys %s hwaddr %s)\n",
299                netdev, netdev->name, netdev->dev->name,
300                netdev_hwaddr ( netdev ) );
301
302         return 0;
303 }
304
305 /**
306  * Open network device
307  *
308  * @v netdev            Network device
309  * @ret rc              Return status code
310  */
311 int netdev_open ( struct net_device *netdev ) {
312         int rc;
313
314         /* Do nothing if device is already open */
315         if ( netdev->state & NETDEV_OPEN )
316                 return 0;
317
318         DBGC ( netdev, "NETDEV %p opening\n", netdev );
319
320         /* Open the device */
321         if ( ( rc = netdev->open ( netdev ) ) != 0 )
322                 return rc;
323
324         /* Mark as opened */
325         netdev->state |= NETDEV_OPEN;
326         return 0;
327 }
328
329 /**
330  * Close network device
331  *
332  * @v netdev            Network device
333  */
334 void netdev_close ( struct net_device *netdev ) {
335
336         /* Do nothing if device is already closed */
337         if ( ! ( netdev->state & NETDEV_OPEN ) )
338                 return;
339
340         DBGC ( netdev, "NETDEV %p closing\n", netdev );
341
342         /* Close the device */
343         netdev->close ( netdev );
344
345         /* Flush TX and RX queues */
346         netdev_tx_flush ( netdev );
347         netdev_rx_flush ( netdev );
348
349         /* Mark as closed */
350         netdev->state &= ~NETDEV_OPEN;
351 }
352
353 /**
354  * Unregister network device
355  *
356  * @v netdev            Network device
357  *
358  * Removes the network device from the list of network devices.
359  */
360 void unregister_netdev ( struct net_device *netdev ) {
361
362         /* Ensure device is closed */
363         netdev_close ( netdev );
364
365         /* Remove from device list */
366         list_del ( &netdev->list );
367         netdev_put ( netdev );
368         DBGC ( netdev, "NETDEV %p unregistered\n", netdev );
369 }
370
371 /**
372  * Get network device by name
373  *
374  * @v name              Network device name
375  * @ret netdev          Network device, or NULL
376  */
377 struct net_device * find_netdev ( const char *name ) {
378         struct net_device *netdev;
379
380         list_for_each_entry ( netdev, &net_devices, list ) {
381                 if ( strcmp ( netdev->name, name ) == 0 )
382                         return netdev;
383         }
384
385         return NULL;
386 }
387
388 /**
389  * Get network device by PCI bus:dev.fn address
390  *
391  * @v bus_type          Bus type
392  * @v location          Bus location
393  * @ret netdev          Network device, or NULL
394  */
395 struct net_device * find_netdev_by_location ( unsigned int bus_type,
396                                               unsigned int location ) {
397         struct net_device *netdev;
398
399         list_for_each_entry ( netdev, &net_devices, list ) {
400                 if ( ( netdev->dev->desc.bus_type == bus_type ) &&
401                      ( netdev->dev->desc.location == location ) )
402                         return netdev;
403         }
404
405         return NULL;    
406 }
407
408 /**
409  * Transmit network-layer packet
410  *
411  * @v iobuf             I/O buffer
412  * @v netdev            Network device
413  * @v net_protocol      Network-layer protocol
414  * @v ll_dest           Destination link-layer address
415  * @ret rc              Return status code
416  *
417  * Prepends link-layer headers to the I/O buffer and transmits the
418  * packet via the specified network device.  This function takes
419  * ownership of the I/O buffer.
420  */
421 int net_tx ( struct io_buffer *iobuf, struct net_device *netdev,
422              struct net_protocol *net_protocol, const void *ll_dest ) {
423         return netdev->ll_protocol->tx ( iobuf, netdev, net_protocol, ll_dest );
424 }
425
426 /**
427  * Process received network-layer packet
428  *
429  * @v iobuf             I/O buffer
430  * @v netdev            Network device
431  * @v net_proto         Network-layer protocol, in network-byte order
432  * @v ll_source         Source link-layer address
433  * @ret rc              Return status code
434  */
435 int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
436              uint16_t net_proto, const void *ll_source ) {
437         struct net_protocol *net_protocol;
438
439         /* Hand off to network-layer protocol, if any */
440         for ( net_protocol = net_protocols ; net_protocol < net_protocols_end ;
441               net_protocol++ ) {
442                 if ( net_protocol->net_proto == net_proto ) {
443                         return net_protocol->rx ( iobuf, netdev, ll_source );
444                 }
445         }
446         free_iob ( iobuf );
447         return 0;
448 }
449
450 /**
451  * Single-step the network stack
452  *
453  * @v process           Network stack process
454  *
455  * This polls all interfaces for received packets, and processes
456  * packets from the RX queue.
457  */
458 static void net_step ( struct process *process __unused ) {
459         struct net_device *netdev;
460         struct io_buffer *iobuf;
461
462         /* Poll and process each network device */
463         list_for_each_entry ( netdev, &net_devices, list ) {
464
465                 /* Poll for new packets */
466                 netdev_poll ( netdev, -1U );
467
468                 /* Process at most one received packet.  Give priority
469                  * to getting packets out of the NIC over processing
470                  * the received packets, because we advertise a window
471                  * that assumes that we can receive packets from the
472                  * NIC faster than they arrive.
473                  */
474                 if ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
475                         DBGC ( netdev, "NETDEV %p processing %p\n",
476                                netdev, iobuf );
477                         netdev->ll_protocol->rx ( iobuf, netdev );
478                 }
479         }
480 }
481
482 /** Networking stack process */
483 struct process net_process __permanent_process = {
484         .step = net_step,
485 };