ソースを参照

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 18年前
コミット
bac97eb979
4個のファイルの変更94行の追加53行の削除
  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 ファイルの表示

@@ -103,15 +103,14 @@ struct net_protocol {
103 103
 	int ( * route ) ( const struct pk_buff *pkb,
104 104
 			  struct net_header *nethdr );
105 105
 	/**
106
-	 * Handle received packets
106
+	 * Process received packet
107 107
 	 *
108 108
 	 * @v pkb	Packet buffer
109 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 115
 	 * Transcribe network-layer address
117 116
 	 *
@@ -240,9 +239,9 @@ struct net_device {
240 239
 	 * This method should cause the hardware to initiate
241 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 246
 	int ( * transmit ) ( struct net_device *netdev, struct pk_buff *pkb );
248 247
 	/** Poll for received packet
@@ -332,9 +331,8 @@ free_netdev ( struct net_device *netdev __attribute__ (( unused )) ) {
332 331
  * @ret rc		Return status code
333 332
  *
334 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 337
 static inline int netdev_transmit ( struct net_device *netdev,
340 338
 				    struct pk_buff *pkb ) {
@@ -375,5 +373,6 @@ extern int net_transmit_via ( struct pk_buff *pkb, struct net_device *netdev );
375 373
 extern int net_transmit ( struct pk_buff *pkb );
376 374
 extern int net_poll ( void );
377 375
 extern struct pk_buff * net_rx_dequeue ( void );
376
+extern int net_rx_process ( struct pk_buff *pkb );
378 377
 
379 378
 #endif /* _GPXE_NETDEVICE_H */

+ 7
- 7
src/net/arp.c ファイルの表示

@@ -154,10 +154,8 @@ int arp_resolve ( struct net_device *netdev, const struct net_header *nethdr,
154 154
 		 nethdr->dest_net_addr, net_protocol->net_addr_len );
155 155
 
156 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 158
 		return rc;
160
-	}
161 159
 
162 160
 	return -ENOENT;
163 161
 }
@@ -230,7 +228,7 @@ static int arp_rx ( struct pk_buff *pkb ) {
230 228
 	if ( arphdr->ar_op != htons ( ARPOP_REQUEST ) )
231 229
 		goto done;
232 230
 
233
-	/* Change request to a reply, and send it */
231
+	/* Change request to a reply */
234 232
 	DBG ( "ARP reply: %s %s => %s %s\n", net_protocol->name,
235 233
 	      net_protocol->ntoa ( arp_target_pa ( arphdr ) ),
236 234
 	      ll_protocol->name, ll_protocol->ntoa ( netdev->ll_addr ) );
@@ -238,8 +236,10 @@ static int arp_rx ( struct pk_buff *pkb ) {
238 236
 	memswap ( arp_sender_ha ( arphdr ), arp_target_ha ( arphdr ),
239 237
 		 arphdr->ar_hln + arphdr->ar_pln );
240 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 244
  done:
245 245
 	free_pkb ( pkb );
@@ -286,7 +286,7 @@ arp_ntoa ( const void *net_addr __attribute__ (( unused )) ) {
286 286
 struct net_protocol arp_protocol = {
287 287
 	.name = "ARP",
288 288
 	.net_proto = htons ( ETH_P_ARP ),
289
-	.rx = arp_rx,
289
+	.rx_process = arp_rx,
290 290
 	.route = arp_route,
291 291
 	.ntoa = arp_ntoa,
292 292
 };

+ 2
- 3
src/net/ipv4.c ファイルの表示

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

+ 76
- 33
src/net/netdevice.c ファイルの表示

@@ -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 );

読み込み中…
キャンセル
保存