|
@@ -23,6 +23,7 @@
|
23
|
23
|
#include <gpxe/if_ether.h>
|
24
|
24
|
#include <gpxe/pkbuff.h>
|
25
|
25
|
#include <gpxe/tables.h>
|
|
26
|
+#include <gpxe/process.h>
|
26
|
27
|
#include <gpxe/netdevice.h>
|
27
|
28
|
|
28
|
29
|
/** @file
|
|
@@ -66,9 +67,8 @@ static LIST_HEAD ( rx_queue );
|
66
|
67
|
* @v netdev Network device
|
67
|
68
|
* @v pkb Packet buffer
|
68
|
69
|
*
|
69
|
|
- * The packet is added to the RX queue. Ownership of the packet is
|
70
|
|
- * transferred to the RX queue; the caller must not touch the packet
|
71
|
|
- * buffer after calling netdev_rx().
|
|
70
|
+ * The packet is added to the RX queue. This function takes ownership
|
|
71
|
+ * of the packet buffer.
|
72
|
72
|
*/
|
73
|
73
|
void netdev_rx ( struct net_device *netdev, struct pk_buff *pkb ) {
|
74
|
74
|
DBG ( "Packet received\n" );
|
|
@@ -137,9 +137,8 @@ find_netdev_by_net_addr ( struct net_protocol *net_protocol,
|
137
|
137
|
* Transmits the packet via the specified network device. The packet
|
138
|
138
|
* must begin with a network-layer header, and the @c net_protocol
|
139
|
139
|
* field must have been filled in. If @c netdev is NULL, the network
|
140
|
|
- * device is identified via the packet contents, if possible. If this
|
141
|
|
- * function returns success, it has taken ownership of the packet
|
142
|
|
- * buffer.
|
|
140
|
+ * device is identified via the packet contents, if possible. This
|
|
141
|
+ * function takes ownership of the packet buffer.
|
143
|
142
|
*/
|
144
|
143
|
int net_transmit_via ( struct pk_buff *pkb, struct net_device *netdev ) {
|
145
|
144
|
struct net_protocol *net_protocol;
|
|
@@ -155,6 +154,7 @@ int net_transmit_via ( struct pk_buff *pkb, struct net_device *netdev ) {
|
155
|
154
|
DBG ( "Could not route to %s address %s\n",
|
156
|
155
|
net_protocol->name,
|
157
|
156
|
net_protocol->ntoa ( nethdr.dest_net_addr ) );
|
|
157
|
+ free_pkb ( pkb );
|
158
|
158
|
return rc;
|
159
|
159
|
}
|
160
|
160
|
|
|
@@ -166,6 +166,7 @@ int net_transmit_via ( struct pk_buff *pkb, struct net_device *netdev ) {
|
166
|
166
|
DBG ( "No network device for %s address %s\n",
|
167
|
167
|
net_protocol->name,
|
168
|
168
|
net_protocol->ntoa ( nethdr.source_net_addr ) );
|
|
169
|
+ free_pkb ( pkb );
|
169
|
170
|
return -EHOSTUNREACH;
|
170
|
171
|
}
|
171
|
172
|
}
|
|
@@ -177,6 +178,7 @@ int net_transmit_via ( struct pk_buff *pkb, struct net_device *netdev ) {
|
177
|
178
|
DBG ( "No link-layer route to %s address %s\n",
|
178
|
179
|
net_protocol->name,
|
179
|
180
|
net_protocol->ntoa ( nethdr.dest_net_addr ) );
|
|
181
|
+ free_pkb ( pkb );
|
180
|
182
|
return rc;
|
181
|
183
|
}
|
182
|
184
|
|
|
@@ -184,7 +186,7 @@ int net_transmit_via ( struct pk_buff *pkb, struct net_device *netdev ) {
|
184
|
186
|
pkb_push ( pkb, ll_protocol->ll_header_len );
|
185
|
187
|
ll_protocol->fill_llh ( &llhdr, pkb );
|
186
|
188
|
|
187
|
|
- /* Transmit packet */
|
|
189
|
+ /* Hand off packet to network device */
|
188
|
190
|
if ( ( rc = netdev->transmit ( netdev, pkb ) ) != 0 ) {
|
189
|
191
|
DBG ( "Device failed to transmit packet\n" );
|
190
|
192
|
return rc;
|
|
@@ -200,9 +202,8 @@ int net_transmit_via ( struct pk_buff *pkb, struct net_device *netdev ) {
|
200
|
202
|
* @v pkb Packet buffer
|
201
|
203
|
* @ret rc Return status code
|
202
|
204
|
*
|
203
|
|
- * Transmits the packet via the appropriate network device. If this
|
204
|
|
- * function returns success, it has taken ownership of the packet
|
205
|
|
- * buffer.
|
|
205
|
+ * Transmits the packet via the appropriate network device. This
|
|
206
|
+ * function takes ownership of the packet buffer.
|
206
|
207
|
*/
|
207
|
208
|
int net_transmit ( struct pk_buff *pkb ) {
|
208
|
209
|
return net_transmit_via ( pkb, NULL );
|
|
@@ -244,41 +245,83 @@ struct pk_buff * net_rx_dequeue ( void ) {
|
244
|
245
|
return NULL;
|
245
|
246
|
}
|
246
|
247
|
|
247
|
|
-void net_run ( void ) {
|
248
|
|
- struct pk_buff *pkb;
|
|
248
|
+/**
|
|
249
|
+ * Process received packet
|
|
250
|
+ *
|
|
251
|
+ * @v pkb Packet buffer
|
|
252
|
+ * @ret rc Return status code
|
|
253
|
+ *
|
|
254
|
+ * Processes a packet received from the network (and, usually, removed
|
|
255
|
+ * from the RX queue by net_rx_dequeue()). This call takes ownership
|
|
256
|
+ * of the packet buffer.
|
|
257
|
+ */
|
|
258
|
+int net_rx_process ( struct pk_buff *pkb ) {
|
249
|
259
|
struct ll_protocol *ll_protocol;
|
250
|
260
|
struct ll_header llhdr;
|
251
|
261
|
struct net_protocol *net_protocol;
|
|
262
|
+ int rc;
|
252
|
263
|
|
253
|
|
- while ( ( pkb = net_rx_dequeue () ) ) {
|
|
264
|
+ /* Parse link-layer header */
|
|
265
|
+ ll_protocol = pkb->ll_protocol;
|
|
266
|
+ ll_protocol->parse_llh ( pkb, &llhdr );
|
|
267
|
+
|
|
268
|
+ /* Identify network-layer protocol */
|
|
269
|
+ net_protocol = find_net_protocol ( llhdr.net_proto );
|
|
270
|
+ if ( ! net_protocol ) {
|
|
271
|
+ DBG ( "Unknown network-layer protocol %x\n",
|
|
272
|
+ ntohs ( llhdr.net_proto ) );
|
|
273
|
+ free_pkb ( pkb );
|
|
274
|
+ return -EPROTONOSUPPORT;
|
|
275
|
+ }
|
|
276
|
+ pkb->net_protocol = net_protocol;
|
|
277
|
+
|
|
278
|
+ /* Strip off link-layer header */
|
|
279
|
+ pkb_pull ( pkb, ll_protocol->ll_header_len );
|
|
280
|
+
|
|
281
|
+ /* Hand off to network layer */
|
|
282
|
+ if ( ( rc = net_protocol->rx_process ( pkb ) ) != 0 ) {
|
|
283
|
+ DBG ( "Network-layer protocol dropped packet\n" );
|
|
284
|
+ return rc;
|
|
285
|
+ }
|
254
|
286
|
|
255
|
|
- /* Parse link-layer header */
|
256
|
|
- ll_protocol = pkb->ll_protocol;
|
257
|
|
- ll_protocol->parse_llh ( pkb, &llhdr );
|
|
287
|
+ return 0;
|
|
288
|
+}
|
258
|
289
|
|
259
|
|
- /* Identify network-layer protocol */
|
260
|
|
- net_protocol = find_net_protocol ( llhdr.net_proto );
|
261
|
|
- if ( ! net_protocol ) {
|
262
|
|
- DBG ( "Unknown network-layer protocol %x\n",
|
263
|
|
- ntohs ( llhdr.net_proto ) );
|
264
|
|
- free_pkb ( pkb );
|
265
|
|
- continue;
|
266
|
|
- }
|
267
|
|
- pkb->net_protocol = net_protocol;
|
268
|
290
|
|
269
|
|
- /* Strip off link-layer header */
|
270
|
|
- pkb_pull ( pkb, ll_protocol->ll_header_len );
|
271
|
291
|
|
272
|
|
- /* Hand off to network layer */
|
273
|
|
- if ( net_protocol->rx ( pkb ) != 0 ) {
|
274
|
|
- DBG ( "Network-layer protocol refused packet\n" );
|
275
|
|
- free_pkb ( pkb );
|
276
|
|
- continue;
|
277
|
|
- }
|
|
292
|
+/**
|
|
293
|
+ * Single-step the network stack
|
|
294
|
+ *
|
|
295
|
+ * @v process Network stack process
|
|
296
|
+ *
|
|
297
|
+ * This polls all interfaces for any received packets, and processes
|
|
298
|
+ * any packets that are received during this poll.
|
|
299
|
+ */
|
|
300
|
+static void net_step ( struct process *process ) {
|
|
301
|
+ struct pk_buff *pkb;
|
|
302
|
+
|
|
303
|
+ /* Poll for new packets */
|
|
304
|
+ net_poll();
|
278
|
305
|
|
|
306
|
+ /* Handle any received packets */
|
|
307
|
+ while ( ( pkb = net_rx_dequeue () ) ) {
|
|
308
|
+ net_rx_process ( pkb );
|
279
|
309
|
DBG ( "Processed received packet\n" );
|
280
|
310
|
}
|
|
311
|
+
|
|
312
|
+ /* Re-schedule ourself */
|
|
313
|
+ schedule ( process );
|
281
|
314
|
}
|
282
|
315
|
|
|
316
|
+/** Networking stack process */
|
|
317
|
+static struct process net_process = {
|
|
318
|
+ .step = net_step,
|
|
319
|
+};
|
|
320
|
+
|
|
321
|
+static void init_net ( void ) {
|
|
322
|
+ schedule ( &net_process );
|
|
323
|
+}
|
283
|
324
|
|
|
325
|
+#include <init.h>
|
284
|
326
|
|
|
327
|
+INIT_FN ( INIT_RPC, init_net, NULL, NULL );
|