Browse Source

[undi] Fill in ProtType correctly in PXENV_UNDI_ISR

Determine the network-layer packet type and fill it in for UNDI
clients.  This is required by some NBPs such as emBoot's winBoot/i.

This change requires refactoring the link-layer portions of the
gPXE netdevice API, so that it becomes possible to strip the
link-layer header without passing the packet up the network stack.
tags/v0.9.4
Michael Brown 16 years ago
parent
commit
30fb3b3810
5 changed files with 145 additions and 65 deletions
  1. 22
    21
      src/drivers/net/ipoib.c
  2. 15
    11
      src/include/gpxe/netdevice.h
  3. 61
    12
      src/interface/pxe/pxe_undi.c
  4. 21
    19
      src/net/ethernet.c
  5. 26
    2
      src/net/netdevice.c

+ 22
- 21
src/drivers/net/ipoib.c View File

153
 };
153
 };
154
 
154
 
155
 /**
155
 /**
156
- * Transmit IPoIB packet
156
+ * Add IPoIB link-layer header
157
  *
157
  *
158
  * @v iobuf		I/O buffer
158
  * @v iobuf		I/O buffer
159
  * @v netdev		Network device
159
  * @v netdev		Network device
160
  * @v net_protocol	Network-layer protocol
160
  * @v net_protocol	Network-layer protocol
161
  * @v ll_dest		Link-layer destination address
161
  * @v ll_dest		Link-layer destination address
162
- *
163
- * Prepends the IPoIB link-layer header and transmits the packet.
164
  */
162
  */
165
-static int ipoib_tx ( struct io_buffer *iobuf, struct net_device *netdev,
166
-		      struct net_protocol *net_protocol,
167
-		      const void *ll_dest ) {
163
+static int ipoib_push ( struct io_buffer *iobuf,
164
+			struct net_device *netdev __unused,
165
+			struct net_protocol *net_protocol,
166
+			const void *ll_dest ) {
168
 	struct ipoib_hdr *ipoib_hdr =
167
 	struct ipoib_hdr *ipoib_hdr =
169
 		iob_push ( iobuf, sizeof ( *ipoib_hdr ) );
168
 		iob_push ( iobuf, sizeof ( *ipoib_hdr ) );
170
 
169
 
174
 	ipoib_hdr->real.proto = net_protocol->net_proto;
173
 	ipoib_hdr->real.proto = net_protocol->net_proto;
175
 	ipoib_hdr->real.reserved = 0;
174
 	ipoib_hdr->real.reserved = 0;
176
 
175
 
177
-	/* Hand off to network device */
178
-	return netdev_tx ( netdev, iobuf );
176
+	return 0;
179
 }
177
 }
180
 
178
 
181
 /**
179
 /**
182
- * Process received IPoIB packet
183
- *
184
- * @v iobuf	I/O buffer
185
- * @v netdev	Network device
180
+ * Remove IPoIB link-layer header
186
  *
181
  *
187
- * Strips off the IPoIB link-layer header and passes up to the
188
- * network-layer protocol.
182
+ * @v iobuf		I/O buffer
183
+ * @v netdev		Network device
184
+ * @v net_proto		Network-layer protocol, in network-byte order
185
+ * @v ll_source		Source link-layer address
186
+ * @ret rc		Return status code
189
  */
187
  */
190
-static int ipoib_rx ( struct io_buffer *iobuf, struct net_device *netdev ) {
188
+static int ipoib_pull ( struct io_buffer *iobuf,
189
+			struct net_device *netdev __unused,
190
+			uint16_t *net_proto, const void **ll_source ) {
191
 	struct ipoib_hdr *ipoib_hdr = iobuf->data;
191
 	struct ipoib_hdr *ipoib_hdr = iobuf->data;
192
 
192
 
193
 	/* Sanity check */
193
 	/* Sanity check */
194
 	if ( iob_len ( iobuf ) < sizeof ( *ipoib_hdr ) ) {
194
 	if ( iob_len ( iobuf ) < sizeof ( *ipoib_hdr ) ) {
195
 		DBG ( "IPoIB packet too short for link-layer header\n" );
195
 		DBG ( "IPoIB packet too short for link-layer header\n" );
196
 		DBG_HD ( iobuf->data, iob_len ( iobuf ) );
196
 		DBG_HD ( iobuf->data, iob_len ( iobuf ) );
197
-		free_iob ( iobuf );
198
 		return -EINVAL;
197
 		return -EINVAL;
199
 	}
198
 	}
200
 
199
 
201
 	/* Strip off IPoIB header */
200
 	/* Strip off IPoIB header */
202
 	iob_pull ( iobuf, sizeof ( *ipoib_hdr ) );
201
 	iob_pull ( iobuf, sizeof ( *ipoib_hdr ) );
203
 
202
 
204
-	/* Hand off to network-layer protocol */
205
-	return net_rx ( iobuf, netdev, ipoib_hdr->real.proto,
206
-			&ipoib_hdr->pseudo.peer );
203
+	/* Fill in required fields */
204
+	*net_proto = ipoib_hdr->real.proto;
205
+	*ll_source = &ipoib_hdr->pseudo.peer;
206
+
207
+	return 0;
207
 }
208
 }
208
 
209
 
209
 /**
210
 /**
231
 	.ll_addr_len	= IPOIB_ALEN,
232
 	.ll_addr_len	= IPOIB_ALEN,
232
 	.ll_header_len	= IPOIB_HLEN,
233
 	.ll_header_len	= IPOIB_HLEN,
233
 	.ll_broadcast	= ( uint8_t * ) &ipoib_broadcast,
234
 	.ll_broadcast	= ( uint8_t * ) &ipoib_broadcast,
234
-	.tx		= ipoib_tx,
235
-	.rx		= ipoib_rx,
235
+	.push		= ipoib_push,
236
+	.pull		= ipoib_pull,
236
 	.ntoa		= ipoib_ntoa,
237
 	.ntoa		= ipoib_ntoa,
237
 };
238
 };
238
 
239
 

+ 15
- 11
src/include/gpxe/netdevice.h View File

76
 	/** Protocol name */
76
 	/** Protocol name */
77
 	const char *name;
77
 	const char *name;
78
 	/**
78
 	/**
79
-	 * Transmit network-layer packet via network device
79
+	 * Add link-layer header
80
 	 *
80
 	 *
81
 	 * @v iobuf		I/O buffer
81
 	 * @v iobuf		I/O buffer
82
 	 * @v netdev		Network device
82
 	 * @v netdev		Network device
85
 	 * @ret rc		Return status code
85
 	 * @ret rc		Return status code
86
 	 *
86
 	 *
87
 	 * This method should prepend in the link-layer header
87
 	 * This method should prepend in the link-layer header
88
-	 * (e.g. the Ethernet DIX header) and transmit the packet.
89
-	 * This method takes ownership of the I/O buffer.
88
+	 * (e.g. the Ethernet DIX header).
90
 	 */
89
 	 */
91
-	int ( * tx ) ( struct io_buffer *iobuf, struct net_device *netdev,
92
-		       struct net_protocol *net_protocol,
93
-		       const void *ll_dest );
90
+	int ( * push ) ( struct io_buffer *iobuf, struct net_device *netdev,
91
+			 struct net_protocol *net_protocol,
92
+			 const void *ll_dest );
94
 	/**
93
 	/**
95
-	 * Handle received packet
94
+	 * Remove link-layer header
96
 	 *
95
 	 *
97
 	 * @v iobuf	I/O buffer
96
 	 * @v iobuf	I/O buffer
98
 	 * @v netdev	Network device
97
 	 * @v netdev	Network device
98
+	 * @v net_proto	Network-layer protocol, in network-byte order
99
+	 * @v ll_source	Source link-layer address
100
+	 * @ret rc	Return status code
99
 	 *
101
 	 *
100
 	 * This method should strip off the link-layer header
102
 	 * This method should strip off the link-layer header
101
-	 * (e.g. the Ethernet DIX header) and pass the packet to
102
-	 * net_rx().  This method takes ownership of the packet
103
-	 * buffer.
103
+	 * (e.g. the Ethernet DIX header) and return the protocol and
104
+	 * source link-layer address.  The method must not alter the
105
+	 * packet content, and may return the link-layer address as a
106
+	 * pointer to data within the packet.
104
 	 */
107
 	 */
105
-	int ( * rx ) ( struct io_buffer *iobuf, struct net_device *netdev );
108
+	int ( * pull ) ( struct io_buffer *iobuf, struct net_device *netdev,
109
+			 uint16_t *net_proto, const void **ll_source );
106
 	/**
110
 	/**
107
 	 * Transcribe link-layer address
111
 	 * Transcribe link-layer address
108
 	 *
112
 	 *

+ 61
- 12
src/interface/pxe/pxe_undi.c View File

251
 				 datablk->TDDataLen );
251
 				 datablk->TDDataLen );
252
 	}
252
 	}
253
 
253
 
254
-	/* Transmit packet */
255
-	if ( net_protocol == NULL ) {
256
-		/* Link-layer header already present */
257
-		rc = netdev_tx ( pxe_netdev, iobuf );
258
-	} else {
254
+	/* Add link-layer header, if required to do so */
255
+	if ( net_protocol != NULL ) {
256
+
259
 		/* Calculate destination address */
257
 		/* Calculate destination address */
260
 		if ( undi_transmit->XmitFlag == XMT_DESTADDR ) {
258
 		if ( undi_transmit->XmitFlag == XMT_DESTADDR ) {
261
 			copy_from_real ( destaddr,
259
 			copy_from_real ( destaddr,
267
 			DBG ( " BCAST" );
265
 			DBG ( " BCAST" );
268
 			ll_dest = pxe_netdev->ll_protocol->ll_broadcast;
266
 			ll_dest = pxe_netdev->ll_protocol->ll_broadcast;
269
 		}
267
 		}
270
-		rc = net_tx ( iobuf, pxe_netdev, net_protocol, ll_dest );
268
+
269
+		/* Add link-layer header */
270
+		if ( ( rc = pxe_netdev->ll_protocol->push ( iobuf, pxe_netdev,
271
+							    net_protocol,
272
+							    ll_dest )) != 0 ){
273
+			free_iob ( iobuf );
274
+			undi_transmit->Status = PXENV_STATUS ( rc );
275
+			return PXENV_EXIT_FAILURE;
276
+		}
277
+	}
278
+
279
+	/* Transmit packet */
280
+	if ( ( rc = netdev_tx ( pxe_netdev, iobuf ) ) != 0 ) {
281
+		undi_transmit->Status = PXENV_STATUS ( rc );
282
+		return PXENV_EXIT_FAILURE;
271
 	}
283
 	}
272
 
284
 
273
 	/* Flag transmission as in-progress */
285
 	/* Flag transmission as in-progress */
274
 	undi_tx_count++;
286
 	undi_tx_count++;
275
 
287
 
276
-	undi_transmit->Status = PXENV_STATUS ( rc );
277
-	return ( ( rc == 0 ) ? PXENV_EXIT_SUCCESS : PXENV_EXIT_FAILURE );
288
+	undi_transmit->Status = PXENV_STATUS_SUCCESS;
289
+	return PXENV_EXIT_SUCCESS;
278
 }
290
 }
279
 
291
 
280
 /* PXENV_UNDI_SET_MCAST_ADDRESS
292
 /* PXENV_UNDI_SET_MCAST_ADDRESS
532
 PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
544
 PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
533
 	struct io_buffer *iobuf;
545
 	struct io_buffer *iobuf;
534
 	size_t len;
546
 	size_t len;
547
+	struct ll_protocol *ll_protocol;
548
+	const void *ll_source;
549
+	uint16_t net_proto;
550
+	size_t ll_hlen;
551
+	struct net_protocol *net_protocol;
552
+	unsigned int prottype;
553
+	int rc;
535
 
554
 
536
 	DBG ( "PXENV_UNDI_ISR" );
555
 	DBG ( "PXENV_UNDI_ISR" );
537
 
556
 
604
 		}
623
 		}
605
 		memcpy ( basemem_packet, iobuf->data, len );
624
 		memcpy ( basemem_packet, iobuf->data, len );
606
 
625
 
626
+		/* Strip link-layer header */
627
+		ll_protocol = pxe_netdev->ll_protocol;
628
+		if ( ( rc = ll_protocol->pull ( iobuf, pxe_netdev,
629
+						&net_proto,
630
+						&ll_source ) ) != 0 ) {
631
+			/* Assume unknown net_proto and no ll_source */
632
+			net_proto = 0;
633
+			ll_source = NULL;
634
+		}
635
+		ll_hlen = ( len - iob_len ( iobuf ) );
636
+
637
+		/* Determine network-layer protocol */
638
+		switch ( net_proto ) {
639
+		case htons ( ETH_P_IP ):
640
+			net_protocol = &ipv4_protocol;
641
+			prottype = P_IP;
642
+			break;
643
+		case htons ( ETH_P_ARP ):
644
+			net_protocol = &arp_protocol;
645
+			prottype = P_ARP;
646
+			break;
647
+		case htons ( ETH_P_RARP ):
648
+			net_protocol = &rarp_protocol;
649
+			prottype = P_RARP;
650
+			break;
651
+		default:
652
+			net_protocol = NULL;
653
+			prottype = P_UNKNOWN;
654
+			break;
655
+		}
656
+		DBG ( " %s", ( net_protocol ? net_protocol->name : "RAW" ) );
657
+
607
 		/* Fill in UNDI_ISR structure */
658
 		/* Fill in UNDI_ISR structure */
608
 		undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_RECEIVE;
659
 		undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_RECEIVE;
609
 		undi_isr->BufferLength = len;
660
 		undi_isr->BufferLength = len;
610
 		undi_isr->FrameLength = len;
661
 		undi_isr->FrameLength = len;
611
-		undi_isr->FrameHeaderLength =
612
-			pxe_netdev->ll_protocol->ll_header_len;
662
+		undi_isr->FrameHeaderLength = ll_hlen;
613
 		undi_isr->Frame.segment = rm_ds;
663
 		undi_isr->Frame.segment = rm_ds;
614
 		undi_isr->Frame.offset = __from_data16 ( basemem_packet );
664
 		undi_isr->Frame.offset = __from_data16 ( basemem_packet );
615
-		/* Probably ought to fill in packet type */
616
-		undi_isr->ProtType = P_UNKNOWN;
665
+		undi_isr->ProtType = prottype;
617
 		undi_isr->PktType = XMT_DESTADDR;
666
 		undi_isr->PktType = XMT_DESTADDR;
618
 
667
 
619
 		/* Free packet */
668
 		/* Free packet */

+ 21
- 19
src/net/ethernet.c View File

38
 static uint8_t eth_broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
38
 static uint8_t eth_broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
39
 
39
 
40
 /**
40
 /**
41
- * Transmit Ethernet packet
41
+ * Add Ethernet link-layer header
42
  *
42
  *
43
  * @v iobuf		I/O buffer
43
  * @v iobuf		I/O buffer
44
  * @v netdev		Network device
44
  * @v netdev		Network device
45
  * @v net_protocol	Network-layer protocol
45
  * @v net_protocol	Network-layer protocol
46
  * @v ll_dest		Link-layer destination address
46
  * @v ll_dest		Link-layer destination address
47
- *
48
- * Prepends the Ethernet link-layer header and transmits the packet.
49
  */
47
  */
50
-static int eth_tx ( struct io_buffer *iobuf, struct net_device *netdev,
51
-		    struct net_protocol *net_protocol, const void *ll_dest ) {
48
+static int eth_push ( struct io_buffer *iobuf, struct net_device *netdev,
49
+		      struct net_protocol *net_protocol,
50
+		      const void *ll_dest ) {
52
 	struct ethhdr *ethhdr = iob_push ( iobuf, sizeof ( *ethhdr ) );
51
 	struct ethhdr *ethhdr = iob_push ( iobuf, sizeof ( *ethhdr ) );
53
 
52
 
54
 	/* Build Ethernet header */
53
 	/* Build Ethernet header */
56
 	memcpy ( ethhdr->h_source, netdev->ll_addr, ETH_ALEN );
55
 	memcpy ( ethhdr->h_source, netdev->ll_addr, ETH_ALEN );
57
 	ethhdr->h_protocol = net_protocol->net_proto;
56
 	ethhdr->h_protocol = net_protocol->net_proto;
58
 
57
 
59
-	/* Hand off to network device */
60
-	return netdev_tx ( netdev, iobuf );
58
+	return 0;
61
 }
59
 }
62
 
60
 
63
 /**
61
 /**
64
- * Process received Ethernet packet
65
- *
66
- * @v iobuf	I/O buffer
67
- * @v netdev	Network device
62
+ * Remove Ethernet link-layer header
68
  *
63
  *
69
- * Strips off the Ethernet link-layer header and passes up to the
70
- * network-layer protocol.
64
+ * @v iobuf		I/O buffer
65
+ * @v netdev		Network device
66
+ * @v net_proto		Network-layer protocol, in network-byte order
67
+ * @v ll_source		Source link-layer address
68
+ * @ret rc		Return status code
71
  */
69
  */
72
-static int eth_rx ( struct io_buffer *iobuf, struct net_device *netdev ) {
70
+static int eth_pull ( struct io_buffer *iobuf,
71
+		      struct net_device *netdev __unused,
72
+		      uint16_t *net_proto, const void **ll_source ) {
73
 	struct ethhdr *ethhdr = iobuf->data;
73
 	struct ethhdr *ethhdr = iobuf->data;
74
 
74
 
75
 	/* Sanity check */
75
 	/* Sanity check */
76
 	if ( iob_len ( iobuf ) < sizeof ( *ethhdr ) ) {
76
 	if ( iob_len ( iobuf ) < sizeof ( *ethhdr ) ) {
77
 		DBG ( "Ethernet packet too short (%zd bytes)\n",
77
 		DBG ( "Ethernet packet too short (%zd bytes)\n",
78
 		      iob_len ( iobuf ) );
78
 		      iob_len ( iobuf ) );
79
-		free_iob ( iobuf );
80
 		return -EINVAL;
79
 		return -EINVAL;
81
 	}
80
 	}
82
 
81
 
83
 	/* Strip off Ethernet header */
82
 	/* Strip off Ethernet header */
84
 	iob_pull ( iobuf, sizeof ( *ethhdr ) );
83
 	iob_pull ( iobuf, sizeof ( *ethhdr ) );
85
 
84
 
86
-	/* Hand off to network-layer protocol */
87
-	return net_rx ( iobuf, netdev, ethhdr->h_protocol, ethhdr->h_source );
85
+	/* Fill in required fields */
86
+	*net_proto = ethhdr->h_protocol;
87
+	*ll_source = ethhdr->h_source;
88
+
89
+	return 0;
88
 }
90
 }
89
 
91
 
90
 /**
92
 /**
110
 	.ll_addr_len	= ETH_ALEN,
112
 	.ll_addr_len	= ETH_ALEN,
111
 	.ll_header_len	= ETH_HLEN,
113
 	.ll_header_len	= ETH_HLEN,
112
 	.ll_broadcast	= eth_broadcast,
114
 	.ll_broadcast	= eth_broadcast,
113
-	.tx		= eth_tx,
114
-	.rx		= eth_rx,
115
+	.push		= eth_push,
116
+	.pull		= eth_pull,
115
 	.ntoa		= eth_ntoa,
117
 	.ntoa		= eth_ntoa,
116
 };
118
 };

+ 26
- 2
src/net/netdevice.c View File

439
  */
439
  */
440
 int net_tx ( struct io_buffer *iobuf, struct net_device *netdev,
440
 int net_tx ( struct io_buffer *iobuf, struct net_device *netdev,
441
 	     struct net_protocol *net_protocol, const void *ll_dest ) {
441
 	     struct net_protocol *net_protocol, const void *ll_dest ) {
442
+	int rc;
442
 
443
 
443
 	/* Force a poll on the netdevice to (potentially) clear any
444
 	/* Force a poll on the netdevice to (potentially) clear any
444
 	 * backed-up TX completions.  This is needed on some network
445
 	 * backed-up TX completions.  This is needed on some network
447
 	 */
448
 	 */
448
 	netdev_poll ( netdev );
449
 	netdev_poll ( netdev );
449
 
450
 
450
-	return netdev->ll_protocol->tx ( iobuf, netdev, net_protocol, ll_dest );
451
+	/* Add link-layer header */
452
+	if ( ( rc = netdev->ll_protocol->push ( iobuf, netdev, net_protocol,
453
+						ll_dest ) ) != 0 ) {
454
+		free_iob ( iobuf );
455
+		return rc;
456
+	}
457
+
458
+	/* Transmit packet */
459
+	return netdev_tx ( netdev, iobuf );
451
 }
460
 }
452
 
461
 
453
 /**
462
 /**
485
 static void net_step ( struct process *process __unused ) {
494
 static void net_step ( struct process *process __unused ) {
486
 	struct net_device *netdev;
495
 	struct net_device *netdev;
487
 	struct io_buffer *iobuf;
496
 	struct io_buffer *iobuf;
497
+	struct ll_protocol *ll_protocol;
498
+	uint16_t net_proto;
499
+	const void *ll_source;
500
+	int rc;
488
 
501
 
489
 	/* Poll and process each network device */
502
 	/* Poll and process each network device */
490
 	list_for_each_entry ( netdev, &net_devices, list ) {
503
 	list_for_each_entry ( netdev, &net_devices, list ) {
499
 		 * NIC faster than they arrive.
512
 		 * NIC faster than they arrive.
500
 		 */
513
 		 */
501
 		if ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
514
 		if ( ( iobuf = netdev_rx_dequeue ( netdev ) ) ) {
515
+
502
 			DBGC ( netdev, "NETDEV %p processing %p (%p+%zx)\n",
516
 			DBGC ( netdev, "NETDEV %p processing %p (%p+%zx)\n",
503
 			       netdev, iobuf, iobuf->data,
517
 			       netdev, iobuf, iobuf->data,
504
 			       iob_len ( iobuf ) );
518
 			       iob_len ( iobuf ) );
505
-			netdev->ll_protocol->rx ( iobuf, netdev );
519
+
520
+			/* Remove link-layer header */
521
+			ll_protocol = netdev->ll_protocol;
522
+			if ( ( rc = ll_protocol->pull ( iobuf, netdev,
523
+							&net_proto,
524
+							&ll_source ) ) != 0 ) {
525
+				free_iob ( iobuf );
526
+				continue;
527
+			}
528
+
529
+			net_rx ( iobuf, netdev, net_proto, ll_source );
506
 		}
530
 		}
507
 	}
531
 	}
508
 }
532
 }

Loading…
Cancel
Save