Browse Source

Change semantics of network API so that packet-absorbing calls *always*

take ownership of the packet, rather than doing so only if they return
success.  This breaks semantic compatibility with Linux's
hard_start_xmit() method, but means that we don't have to worry so much
about error cases.

Split mechanism of processing received packets (net_rx_process()) out
from policy (net_step()), preparatory to putting net_step() in a separate
object.
tags/v0.9.3
Michael Brown 19 years ago
parent
commit
bac97eb979
4 changed files with 94 additions and 53 deletions
  1. 9
    10
      src/include/gpxe/netdevice.h
  2. 7
    7
      src/net/arp.c
  3. 2
    3
      src/net/ipv4.c
  4. 76
    33
      src/net/netdevice.c

+ 9
- 10
src/include/gpxe/netdevice.h View File

103
 	int ( * route ) ( const struct pk_buff *pkb,
103
 	int ( * route ) ( const struct pk_buff *pkb,
104
 			  struct net_header *nethdr );
104
 			  struct net_header *nethdr );
105
 	/**
105
 	/**
106
-	 * Handle received packets
106
+	 * Process received packet
107
 	 *
107
 	 *
108
 	 * @v pkb	Packet buffer
108
 	 * @v pkb	Packet buffer
109
 	 * @ret rc	Return status code
109
 	 * @ret rc	Return status code
110
 	 *
110
 	 *
111
-	 * If this method returns success, it has taken ownership of
112
-	 * the packet buffer.
111
+	 * This method takes ownership of the packet buffer.
113
 	 */
112
 	 */
114
-	int ( * rx ) ( struct pk_buff *pkb );
113
+	int ( * rx_process ) ( struct pk_buff *pkb );
115
 	/**
114
 	/**
116
 	 * Transcribe network-layer address
115
 	 * Transcribe network-layer address
117
 	 *
116
 	 *
240
 	 * This method should cause the hardware to initiate
239
 	 * This method should cause the hardware to initiate
241
 	 * transmission of the packet buffer.
240
 	 * transmission of the packet buffer.
242
 	 *
241
 	 *
243
-	 * If the method returns success, ownership of the packet
244
-	 * buffer is transferred to the @c net_device, which must
245
-	 * eventually call free_pkb() to release the buffer.
242
+	 * Ownership of the packet buffer is transferred to the @c
243
+	 * net_device, which must eventually call free_pkb() to
244
+	 * release the buffer.
246
 	 */
245
 	 */
247
 	int ( * transmit ) ( struct net_device *netdev, struct pk_buff *pkb );
246
 	int ( * transmit ) ( struct net_device *netdev, struct pk_buff *pkb );
248
 	/** Poll for received packet
247
 	/** Poll for received packet
332
  * @ret rc		Return status code
331
  * @ret rc		Return status code
333
  *
332
  *
334
  * Transmits the packet via the specified network device.  The
333
  * Transmits the packet via the specified network device.  The
335
- * link-layer header must already have been filled in.  If this
336
- * function returns success, it has taken ownership of the packet
337
- * buffer.
334
+ * link-layer header must already have been filled in.  This function
335
+ * takes ownership of the packet buffer.
338
  */
336
  */
339
 static inline int netdev_transmit ( struct net_device *netdev,
337
 static inline int netdev_transmit ( struct net_device *netdev,
340
 				    struct pk_buff *pkb ) {
338
 				    struct pk_buff *pkb ) {
375
 extern int net_transmit ( struct pk_buff *pkb );
373
 extern int net_transmit ( struct pk_buff *pkb );
376
 extern int net_poll ( void );
374
 extern int net_poll ( void );
377
 extern struct pk_buff * net_rx_dequeue ( void );
375
 extern struct pk_buff * net_rx_dequeue ( void );
376
+extern int net_rx_process ( struct pk_buff *pkb );
378
 
377
 
379
 #endif /* _GPXE_NETDEVICE_H */
378
 #endif /* _GPXE_NETDEVICE_H */

+ 7
- 7
src/net/arp.c View File

154
 		 nethdr->dest_net_addr, net_protocol->net_addr_len );
154
 		 nethdr->dest_net_addr, net_protocol->net_addr_len );
155
 
155
 
156
 	/* Transmit ARP request */
156
 	/* Transmit ARP request */
157
-	if ( ( rc = net_transmit_via ( pkb, netdev ) ) != 0 ) {
158
-		free_pkb ( pkb );
157
+	if ( ( rc = net_transmit_via ( pkb, netdev ) ) != 0 )
159
 		return rc;
158
 		return rc;
160
-	}
161
 
159
 
162
 	return -ENOENT;
160
 	return -ENOENT;
163
 }
161
 }
230
 	if ( arphdr->ar_op != htons ( ARPOP_REQUEST ) )
228
 	if ( arphdr->ar_op != htons ( ARPOP_REQUEST ) )
231
 		goto done;
229
 		goto done;
232
 
230
 
233
-	/* Change request to a reply, and send it */
231
+	/* Change request to a reply */
234
 	DBG ( "ARP reply: %s %s => %s %s\n", net_protocol->name,
232
 	DBG ( "ARP reply: %s %s => %s %s\n", net_protocol->name,
235
 	      net_protocol->ntoa ( arp_target_pa ( arphdr ) ),
233
 	      net_protocol->ntoa ( arp_target_pa ( arphdr ) ),
236
 	      ll_protocol->name, ll_protocol->ntoa ( netdev->ll_addr ) );
234
 	      ll_protocol->name, ll_protocol->ntoa ( netdev->ll_addr ) );
238
 	memswap ( arp_sender_ha ( arphdr ), arp_target_ha ( arphdr ),
236
 	memswap ( arp_sender_ha ( arphdr ), arp_target_ha ( arphdr ),
239
 		 arphdr->ar_hln + arphdr->ar_pln );
237
 		 arphdr->ar_hln + arphdr->ar_pln );
240
 	memcpy ( arp_target_ha ( arphdr ), netdev->ll_addr, arphdr->ar_hln );
238
 	memcpy ( arp_target_ha ( arphdr ), netdev->ll_addr, arphdr->ar_hln );
241
-	if ( net_transmit_via ( pkb, netdev ) == 0 )
242
-		pkb = NULL;
239
+
240
+	/* Send reply */
241
+	net_transmit_via ( pkb, netdev );
242
+	pkb = NULL;
243
 
243
 
244
  done:
244
  done:
245
 	free_pkb ( pkb );
245
 	free_pkb ( pkb );
286
 struct net_protocol arp_protocol = {
286
 struct net_protocol arp_protocol = {
287
 	.name = "ARP",
287
 	.name = "ARP",
288
 	.net_proto = htons ( ETH_P_ARP ),
288
 	.net_proto = htons ( ETH_P_ARP ),
289
-	.rx = arp_rx,
289
+	.rx_process = arp_rx,
290
 	.route = arp_route,
290
 	.route = arp_route,
291
 	.ntoa = arp_ntoa,
291
 	.ntoa = arp_ntoa,
292
 };
292
 };

+ 2
- 3
src/net/ipv4.c View File

163
 		pkb_empty ( pkb );
163
 		pkb_empty ( pkb );
164
 		pkb_put ( pkb, uip_len );
164
 		pkb_put ( pkb, uip_len );
165
 		memcpy ( pkb->data, uip_buf, uip_len );
165
 		memcpy ( pkb->data, uip_buf, uip_len );
166
-		if ( net_transmit ( pkb ) != 0 )
167
-			free_pkb ( pkb );
166
+		net_transmit ( pkb );
168
 	} else {
167
 	} else {
169
 		free_pkb ( pkb );
168
 		free_pkb ( pkb );
170
 	}
169
 	}
231
 	.name = "IP",
230
 	.name = "IP",
232
 	.net_proto = htons ( ETH_P_IP ),
231
 	.net_proto = htons ( ETH_P_IP ),
233
 	.net_addr_len = sizeof ( struct in_addr ),
232
 	.net_addr_len = sizeof ( struct in_addr ),
234
-	.rx = ipv4_rx,
233
+	.rx_process = ipv4_rx,
235
 	.route = ipv4_route,
234
 	.route = ipv4_route,
236
 	.ntoa = ipv4_ntoa,
235
 	.ntoa = ipv4_ntoa,
237
 };
236
 };

+ 76
- 33
src/net/netdevice.c View File

23
 #include <gpxe/if_ether.h>
23
 #include <gpxe/if_ether.h>
24
 #include <gpxe/pkbuff.h>
24
 #include <gpxe/pkbuff.h>
25
 #include <gpxe/tables.h>
25
 #include <gpxe/tables.h>
26
+#include <gpxe/process.h>
26
 #include <gpxe/netdevice.h>
27
 #include <gpxe/netdevice.h>
27
 
28
 
28
 /** @file
29
 /** @file
66
  * @v netdev		Network device
67
  * @v netdev		Network device
67
  * @v pkb		Packet buffer
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
 void netdev_rx ( struct net_device *netdev, struct pk_buff *pkb ) {
73
 void netdev_rx ( struct net_device *netdev, struct pk_buff *pkb ) {
74
 	DBG ( "Packet received\n" );
74
 	DBG ( "Packet received\n" );
137
  * Transmits the packet via the specified network device.  The packet
137
  * Transmits the packet via the specified network device.  The packet
138
  * must begin with a network-layer header, and the @c net_protocol
138
  * must begin with a network-layer header, and the @c net_protocol
139
  * field must have been filled in.  If @c netdev is NULL, the network
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
 int net_transmit_via ( struct pk_buff *pkb, struct net_device *netdev ) {
143
 int net_transmit_via ( struct pk_buff *pkb, struct net_device *netdev ) {
145
 	struct net_protocol *net_protocol;
144
 	struct net_protocol *net_protocol;
155
 		DBG ( "Could not route to %s address %s\n",
154
 		DBG ( "Could not route to %s address %s\n",
156
 		      net_protocol->name,
155
 		      net_protocol->name,
157
 		      net_protocol->ntoa ( nethdr.dest_net_addr ) );
156
 		      net_protocol->ntoa ( nethdr.dest_net_addr ) );
157
+		free_pkb ( pkb );
158
 		return rc;
158
 		return rc;
159
 	}
159
 	}
160
 
160
 
166
 			DBG ( "No network device for %s address %s\n",
166
 			DBG ( "No network device for %s address %s\n",
167
 			      net_protocol->name,
167
 			      net_protocol->name,
168
 			      net_protocol->ntoa ( nethdr.source_net_addr ) );
168
 			      net_protocol->ntoa ( nethdr.source_net_addr ) );
169
+			free_pkb ( pkb );
169
 			return -EHOSTUNREACH;
170
 			return -EHOSTUNREACH;
170
 		}
171
 		}
171
 	}
172
 	}
177
 		DBG ( "No link-layer route to %s address %s\n",
178
 		DBG ( "No link-layer route to %s address %s\n",
178
 		      net_protocol->name,
179
 		      net_protocol->name,
179
 		      net_protocol->ntoa ( nethdr.dest_net_addr ) );
180
 		      net_protocol->ntoa ( nethdr.dest_net_addr ) );
181
+		free_pkb ( pkb );
180
 		return rc;
182
 		return rc;
181
 	}
183
 	}
182
 
184
 
184
 	pkb_push ( pkb, ll_protocol->ll_header_len );
186
 	pkb_push ( pkb, ll_protocol->ll_header_len );
185
 	ll_protocol->fill_llh ( &llhdr, pkb );
187
 	ll_protocol->fill_llh ( &llhdr, pkb );
186
 
188
 
187
-	/* Transmit packet */
189
+	/* Hand off packet to network device */
188
 	if ( ( rc = netdev->transmit ( netdev, pkb ) ) != 0 ) {
190
 	if ( ( rc = netdev->transmit ( netdev, pkb ) ) != 0 ) {
189
 		DBG ( "Device failed to transmit packet\n" );
191
 		DBG ( "Device failed to transmit packet\n" );
190
 		return rc;
192
 		return rc;
200
  * @v pkb		Packet buffer
202
  * @v pkb		Packet buffer
201
  * @ret rc		Return status code
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
 int net_transmit ( struct pk_buff *pkb ) {
208
 int net_transmit ( struct pk_buff *pkb ) {
208
 	return net_transmit_via ( pkb, NULL );
209
 	return net_transmit_via ( pkb, NULL );
244
 	return NULL;
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
 	struct ll_protocol *ll_protocol;
259
 	struct ll_protocol *ll_protocol;
250
 	struct ll_header llhdr;
260
 	struct ll_header llhdr;
251
 	struct net_protocol *net_protocol;
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
 		DBG ( "Processed received packet\n" );
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 );

Loading…
Cancel
Save