d498d9f119d487068f4de9e3ddfd9c5885ce014e
[people/meteger/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/pkbuff.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 pkb               Packet buffer
53  * @ret rc              Return status code
54  *
55  * Transmits the packet via the specified network device.  This
56  * function takes ownership of the packet buffer.
57  */
58 int netdev_tx ( struct net_device *netdev, struct pk_buff *pkb ) {
59         int rc;
60
61         DBGC ( netdev, "NETDEV %p transmitting %p (%p+%zx)\n",
62                netdev, pkb, pkb->data, pkb_len ( pkb ) );
63
64         list_add_tail ( &pkb->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, pkb ) ) != 0 )
72                 goto err;
73
74         return 0;
75
76  err:
77         DBGC ( netdev, "NETDEV %p transmission %p failed: %s\n",
78                netdev, pkb, strerror ( rc ) );
79         netdev_tx_complete ( netdev, pkb );
80         return rc;
81 }
82
83 /**
84  * Complete network transmission
85  *
86  * @v netdev            Network device
87  * @v pkb               Packet buffer
88  *
89  * The packet must currently be in the network device's TX queue.
90  */
91 void netdev_tx_complete ( struct net_device *netdev, struct pk_buff *pkb ) {
92         DBGC ( netdev, "NETDEV %p transmission %p complete\n", netdev, pkb );
93
94         /* Catch data corruption as early as possible */
95         assert ( pkb->list.next != NULL );
96         assert ( pkb->list.prev != NULL );
97
98         list_del ( &pkb->list );
99         free_pkb ( pkb );
100 }
101
102 /**
103  * Complete network transmission
104  *
105  * @v netdev            Network device
106  *
107  * Completes the oldest outstanding packet in the TX queue.
108  */
109 void netdev_tx_complete_next ( struct net_device *netdev ) {
110         struct pk_buff *pkb;
111
112         list_for_each_entry ( pkb, &netdev->tx_queue, list ) {
113                 netdev_tx_complete ( netdev, pkb );
114                 return;
115         }
116 }
117
118 /**
119  * Add packet to receive queue
120  *
121  * @v netdev            Network device
122  * @v pkb               Packet buffer
123  *
124  * The packet is added to the network device's RX queue.  This
125  * function takes ownership of the packet buffer.
126  */
127 void netdev_rx ( struct net_device *netdev, struct pk_buff *pkb ) {
128         DBGC ( netdev, "NETDEV %p received %p (%p+%zx)\n",
129                netdev, pkb, pkb->data, pkb_len ( pkb ) );
130         list_add_tail ( &pkb->list, &netdev->rx_queue );
131 }
132
133 /**
134  * Poll for packet on network device
135  *
136  * @v netdev            Network device
137  * @v rx_quota          Maximum number of packets to receive
138  * @ret True            There are packets present in the receive queue
139  * @ret False           There are no packets present in the receive queue
140  *
141  * Polls the network device for received packets.  Any received
142  * packets will be added to the RX packet queue via netdev_rx().
143  */
144 int netdev_poll ( struct net_device *netdev, unsigned int rx_quota ) {
145
146         if ( netdev->state & NETDEV_OPEN )
147                 netdev->poll ( netdev, rx_quota );
148
149         return ( ! list_empty ( &netdev->rx_queue ) );
150 }
151
152 /**
153  * Remove packet from device's receive queue
154  *
155  * @v netdev            Network device
156  * @ret pkb             Packet buffer, or NULL
157  *
158  * Removes the first packet from the device's RX queue and returns it.
159  * Ownership of the packet is transferred to the caller.
160  */
161 struct pk_buff * netdev_rx_dequeue ( struct net_device *netdev ) {
162         struct pk_buff *pkb;
163
164         list_for_each_entry ( pkb, &netdev->rx_queue, list ) {
165                 list_del ( &pkb->list );
166                 return pkb;
167         }
168         return NULL;
169 }
170
171 /**
172  * Allocate network device
173  *
174  * @v priv_size         Size of private data area (net_device::priv)
175  * @ret netdev          Network device, or NULL
176  *
177  * Allocates space for a network device and its private data area.
178  */
179 struct net_device * alloc_netdev ( size_t priv_size ) {
180         struct net_device *netdev;
181         size_t total_len;
182
183         total_len = ( sizeof ( *netdev ) + priv_size );
184         netdev = malloc ( total_len );
185         if ( netdev ) {
186                 memset ( netdev, 0, total_len );
187                 INIT_LIST_HEAD ( &netdev->references );
188                 INIT_LIST_HEAD ( &netdev->tx_queue );
189                 INIT_LIST_HEAD ( &netdev->rx_queue );
190                 netdev->priv = ( ( ( void * ) netdev ) + sizeof ( *netdev ) );
191         }
192         return netdev;
193 }
194
195 /**
196  * Register network device
197  *
198  * @v netdev            Network device
199  * @ret rc              Return status code
200  *
201  * Gives the network device a name and adds it to the list of network
202  * devices.
203  */
204 int register_netdev ( struct net_device *netdev ) {
205         static unsigned int ifindex = 0;
206
207         /* Create device name */
208         snprintf ( netdev->name, sizeof ( netdev->name ), "net%d",
209                    ifindex++ );
210
211         /* Add to device list */
212         list_add_tail ( &netdev->list, &net_devices );
213         DBGC ( netdev, "NETDEV %p registered as %s (phys %s hwaddr %s)\n",
214                netdev, netdev->name, netdev->dev->name,
215                netdev_hwaddr ( netdev ) );
216
217         return 0;
218 }
219
220 /**
221  * Open network device
222  *
223  * @v netdev            Network device
224  * @ret rc              Return status code
225  */
226 int netdev_open ( struct net_device *netdev ) {
227         int rc;
228
229         /* Do nothing if device is already open */
230         if ( netdev->state & NETDEV_OPEN )
231                 return 0;
232
233         DBGC ( netdev, "NETDEV %p opening\n", netdev );
234
235         /* Open the device */
236         if ( ( rc = netdev->open ( netdev ) ) != 0 )
237                 return rc;
238
239         /* Mark as opened */
240         netdev->state |= NETDEV_OPEN;
241         return 0;
242 }
243
244 /**
245  * Close network device
246  *
247  * @v netdev            Network device
248  */
249 void netdev_close ( struct net_device *netdev ) {
250         struct pk_buff *pkb;
251
252         /* Do nothing if device is already closed */
253         if ( ! ( netdev->state & NETDEV_OPEN ) )
254                 return;
255
256         DBGC ( netdev, "NETDEV %p closing\n", netdev );
257
258         /* Close the device */
259         netdev->close ( netdev );
260
261         /* Discard any packets in the TX queue */
262         while ( ! list_empty ( &netdev->tx_queue ) ) {
263                 netdev_tx_complete_next ( netdev );
264         }
265
266         /* Discard any packets in the RX queue */
267         while ( ( pkb = netdev_rx_dequeue ( netdev ) ) ) {
268                 DBGC ( netdev, "NETDEV %p discarding received %p\n",
269                        netdev, pkb );
270                 free_pkb ( pkb );
271         }
272
273         /* Mark as closed */
274         netdev->state &= ~NETDEV_OPEN;
275 }
276
277 /**
278  * Unregister network device
279  *
280  * @v netdev            Network device
281  *
282  * Removes the network device from the list of network devices.
283  */
284 void unregister_netdev ( struct net_device *netdev ) {
285
286         /* Ensure device is closed */
287         netdev_close ( netdev );
288
289         /* Kill off any persistent references to this device */
290         forget_references ( &netdev->references );
291
292         /* Remove from device list */
293         list_del ( &netdev->list );
294         DBGC ( netdev, "NETDEV %p unregistered\n", netdev );
295 }
296
297 /**
298  * Free network device
299  *
300  * @v netdev            Network device
301  */
302 void free_netdev ( struct net_device *netdev ) {
303         free ( netdev );
304 }
305
306 /**
307  * Get network device by name
308  *
309  * @v name              Network device name
310  * @ret netdev          Network device, or NULL
311  */
312 struct net_device * find_netdev ( const char *name ) {
313         struct net_device *netdev;
314
315         list_for_each_entry ( netdev, &net_devices, list ) {
316                 if ( strcmp ( netdev->name, name ) == 0 )
317                         return netdev;
318         }
319
320         return NULL;
321 }
322
323 /**
324  * Get network device by PCI bus:dev.fn address
325  *
326  * @v busdevfn          PCI bus:dev.fn address
327  * @ret netdev          Network device, or NULL
328  */
329 struct net_device * find_pci_netdev ( unsigned int busdevfn ) {
330         struct net_device *netdev;
331
332         list_for_each_entry ( netdev, &net_devices, list ) {
333                 if ( ( netdev->dev->desc.bus_type == BUS_TYPE_PCI ) &&
334                      ( netdev->dev->desc.location == busdevfn ) )
335                         return netdev;
336         }
337
338         return NULL;    
339 }
340
341 /**
342  * Transmit network-layer packet
343  *
344  * @v pkb               Packet buffer
345  * @v netdev            Network device
346  * @v net_protocol      Network-layer protocol
347  * @v ll_dest           Destination link-layer address
348  * @ret rc              Return status code
349  *
350  * Prepends link-layer headers to the packet buffer and transmits the
351  * packet via the specified network device.  This function takes
352  * ownership of the packet buffer.
353  */
354 int net_tx ( struct pk_buff *pkb, struct net_device *netdev,
355              struct net_protocol *net_protocol, const void *ll_dest ) {
356         return netdev->ll_protocol->tx ( pkb, netdev, net_protocol, ll_dest );
357 }
358
359 /**
360  * Process received network-layer packet
361  *
362  * @v pkb               Packet buffer
363  * @v netdev            Network device
364  * @v net_proto         Network-layer protocol, in network-byte order
365  * @v ll_source         Source link-layer address
366  * @ret rc              Return status code
367  */
368 int net_rx ( struct pk_buff *pkb, struct net_device *netdev,
369              uint16_t net_proto, const void *ll_source ) {
370         struct net_protocol *net_protocol;
371
372         /* Hand off to network-layer protocol, if any */
373         for ( net_protocol = net_protocols ; net_protocol < net_protocols_end ;
374               net_protocol++ ) {
375                 if ( net_protocol->net_proto == net_proto ) {
376                         return net_protocol->rx ( pkb, netdev, ll_source );
377                 }
378         }
379         free_pkb ( pkb );
380         return 0;
381 }
382
383 /**
384  * Single-step the network stack
385  *
386  * @v process           Network stack process
387  *
388  * This polls all interfaces for received packets, and processes
389  * packets from the RX queue.
390  */
391 static void net_step ( struct process *process ) {
392         struct net_device *netdev;
393         struct pk_buff *pkb;
394
395         /* Poll and process each network device */
396         list_for_each_entry ( netdev, &net_devices, list ) {
397
398                 /* Poll for new packets */
399                 netdev_poll ( netdev, -1U );
400
401                 /* Process at most one received packet.  Give priority
402                  * to getting packets out of the NIC over processing
403                  * the received packets, because we advertise a window
404                  * that assumes that we can receive packets from the
405                  * NIC faster than they arrive.
406                  */
407                 if ( ( pkb = netdev_rx_dequeue ( netdev ) ) ) {
408                         DBGC ( netdev, "NETDEV %p processing %p\n",
409                                netdev, pkb );
410                         netdev->ll_protocol->rx ( pkb, netdev );
411                 }
412         }
413
414         /* Re-schedule ourself */
415         schedule ( process );
416 }
417
418 /** Networking stack process */
419 static struct process net_process = {
420         .step = net_step,
421 };
422
423 /** Initialise the networking stack process */
424 static void init_net ( void ) {
425         schedule ( &net_process );
426 }
427
428 INIT_FN ( INIT_PROCESS, init_net, NULL, NULL );