d72392ca0a959fa9eb492af70b2588dd89aa9c34
[people/sha0/gpxe.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 = zalloc ( total_len );
269         if ( netdev ) {
270                 netdev->refcnt.free = free_netdev;
271                 INIT_LIST_HEAD ( &netdev->tx_queue );
272                 INIT_LIST_HEAD ( &netdev->rx_queue );
273                 netdev->priv = ( ( ( void * ) netdev ) + sizeof ( *netdev ) );
274         }
275         return netdev;
276 }
277
278 /**
279  * Register network device
280  *
281  * @v netdev            Network device
282  * @ret rc              Return status code
283  *
284  * Gives the network device a name and adds it to the list of network
285  * devices.
286  */
287 int register_netdev ( struct net_device *netdev ) {
288         static unsigned int ifindex = 0;
289
290         /* Create device name */
291         snprintf ( netdev->name, sizeof ( netdev->name ), "net%d",
292                    ifindex++ );
293
294         /* Add to device list */
295         netdev_get ( netdev );
296         list_add_tail ( &netdev->list, &net_devices );
297         DBGC ( netdev, "NETDEV %p registered as %s (phys %s hwaddr %s)\n",
298                netdev, netdev->name, netdev->dev->name,
299                netdev_hwaddr ( netdev ) );
300
301         return 0;
302 }
303
304 /**
305  * Open network device
306  *
307  * @v netdev            Network device
308  * @ret rc              Return status code
309  */
310 int netdev_open ( struct net_device *netdev ) {
311         int rc;
312
313         /* Do nothing if device is already open */
314         if ( netdev->state & NETDEV_OPEN )
315                 return 0;
316
317         DBGC ( netdev, "NETDEV %p opening\n", netdev );
318
319         /* Open the device */
320         if ( ( rc = netdev->open ( netdev ) ) != 0 )
321                 return rc;
322
323         /* Mark as opened */
324         netdev->state |= NETDEV_OPEN;
325         return 0;
326 }
327
328 /**
329  * Close network device
330  *
331  * @v netdev            Network device
332  */
333 void netdev_close ( struct net_device *netdev ) {
334
335         /* Do nothing if device is already closed */
336         if ( ! ( netdev->state & NETDEV_OPEN ) )
337                 return;
338
339         DBGC ( netdev, "NETDEV %p closing\n", netdev );
340
341         /* Close the device */
342         netdev->close ( netdev );
343
344         /* Flush TX and RX queues */
345         netdev_tx_flush ( netdev );
346         netdev_rx_flush ( netdev );
347
348         /* Mark as closed */
349         netdev->state &= ~NETDEV_OPEN;
350 }
351
352 /**
353  * Unregister network device
354  *
355  * @v netdev            Network device
356  *
357  * Removes the network device from the list of network devices.
358  */
359 void unregister_netdev ( struct net_device *netdev ) {
360
361         /* Ensure device is closed */
362         netdev_close ( netdev );
363
364         /* Remove from device list */
365         list_del ( &netdev->list );
366         netdev_put ( netdev );
367         DBGC ( netdev, "NETDEV %p unregistered\n", netdev );
368 }
369
370 /**
371  * Get network device by name
372  *
373  * @v name              Network device name
374  * @ret netdev          Network device, or NULL
375  */
376 struct net_device * find_netdev ( const char *name ) {
377         struct net_device *netdev;
378
379         list_for_each_entry ( netdev, &net_devices, list ) {
380                 if ( strcmp ( netdev->name, name ) == 0 )
381                         return netdev;
382         }
383
384         return NULL;
385 }
386
387 /**
388  * Get network device by PCI bus:dev.fn address
389  *
390  * @v bus_type          Bus type
391  * @v location          Bus location
392  * @ret netdev          Network device, or NULL
393  */
394 struct net_device * find_netdev_by_location ( unsigned int bus_type,
395                                               unsigned int location ) {
396         struct net_device *netdev;
397
398         list_for_each_entry ( netdev, &net_devices, list ) {
399                 if ( ( netdev->dev->desc.bus_type == bus_type ) &&
400                      ( netdev->dev->desc.location == location ) )
401                         return netdev;
402         }
403
404         return NULL;    
405 }
406
407 /**
408  * Transmit network-layer packet
409  *
410  * @v iobuf             I/O buffer
411  * @v netdev            Network device
412  * @v net_protocol      Network-layer protocol
413  * @v ll_dest           Destination link-layer address
414  * @ret rc              Return status code
415  *
416  * Prepends link-layer headers to the I/O buffer and transmits the
417  * packet via the specified network device.  This function takes
418  * ownership of the I/O buffer.
419  */
420 int net_tx ( struct io_buffer *iobuf, struct net_device *netdev,
421              struct net_protocol *net_protocol, const void *ll_dest ) {
422         return netdev->ll_protocol->tx ( iobuf, netdev, net_protocol, ll_dest );
423 }
424
425 /**
426  * Process received network-layer packet
427  *
428  * @v iobuf             I/O buffer
429  * @v netdev            Network device
430  * @v net_proto         Network-layer protocol, in network-byte order
431  * @v ll_source         Source link-layer address
432  * @ret rc              Return status code
433  */
434 int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
435              uint16_t net_proto, const void *ll_source ) {
436         struct net_protocol *net_protocol;
437
438         /* Hand off to network-layer protocol, if any */
439         for ( net_protocol = net_protocols ; net_protocol < net_protocols_end ;
440               net_protocol++ ) {
441                 if ( net_protocol->net_proto == net_proto ) {
442                         return net_protocol->rx ( iobuf, netdev, ll_source );
443                 }
444         }
445         free_iob ( iobuf );
446         return 0;
447 }
448
449 /**
450  * Single-step the network stack
451  *
452  * @v process           Network stack process
453  *
454  * This polls all interfaces for received packets, and processes
455  * packets from the RX queue.
456  */
457 static void net_step ( struct process *process __unused ) {
458         struct net_device *netdev;
459         struct io_buffer *iobuf;
460
461         /* Poll and process each network device */
462         list_for_each_entry ( netdev, &net_devices, list ) {
463
464                 /* Poll for new packets */
465                 netdev_poll ( netdev, -1U );
466
467                 /* Process at most one received packet.  Give priority
468                  * to getting packets out of the NIC over processing
469                  * the received packets, because we advertise a window
470                  * that assumes that we can receive packets from the
471                  * NIC faster than they arrive.
472                  */
473                 if ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
474                         DBGC ( netdev, "NETDEV %p processing %p\n",
475                                netdev, iobuf );
476                         netdev->ll_protocol->rx ( iobuf, netdev );
477                 }
478         }
479 }
480
481 /** Networking stack process */
482 struct process net_process __permanent_process = {
483         .step = net_step,
484 };