Browse Source

[netdevice] Add the concept of an "Ethernet-compatible" MAC address

The iBFT is Ethernet-centric in providing only six bytes for a MAC
address.  This is most probably an indirect consequence of a similar
design flaw in the Windows NDIS stack.  (The WinOF IPoIB stack
performs all sorts of contortions in order to pretend to the NDIS
layer that it is dealing with six-byte MAC addresses.)

There is no sensible way in which to extend the iBFT without breaking
compatibility with programs that expect to parse it.  Add the notion
of an "Ethernet-compatible" MAC address to our link layer abstraction,
so that link layers can provide their own workarounds for this
limitation.
tags/v1.0.0-rc1
Michael Brown 16 years ago
parent
commit
1b1e63d54d

+ 57
- 0
src/drivers/net/ipoib.c View File

296
 	return -ENOTSUP;
296
 	return -ENOTSUP;
297
 }
297
 }
298
 
298
 
299
+/**
300
+ * Generate Mellanox Ethernet-compatible compressed link-layer address
301
+ *
302
+ * @v ll_addr		Link-layer address
303
+ * @v eth_addr		Ethernet-compatible address to fill in
304
+ */
305
+static int ipoib_mlx_eth_addr ( const struct ib_gid_half *guid,
306
+				uint8_t *eth_addr ) {
307
+	eth_addr[0] = ( ( guid->u.bytes[3] == 2 ) ? 0x00 : 0x02 );
308
+	eth_addr[1] = guid->u.bytes[1];
309
+	eth_addr[2] = guid->u.bytes[2];
310
+	eth_addr[3] = guid->u.bytes[5];
311
+	eth_addr[4] = guid->u.bytes[6];
312
+	eth_addr[5] = guid->u.bytes[7];
313
+	return 0;
314
+}
315
+
316
+/** An IPoIB Ethernet-compatible compressed link-layer address generator */
317
+struct ipoib_eth_addr_handler {
318
+	/** GUID byte 1 */
319
+	uint8_t byte1;
320
+	/** GUID byte 2 */
321
+	uint8_t byte2;
322
+	/** Handler */
323
+	int ( * eth_addr ) ( const struct ib_gid_half *guid,
324
+			     uint8_t *eth_addr );
325
+};
326
+
327
+/** IPoIB Ethernet-compatible compressed link-layer address generators */
328
+static struct ipoib_eth_addr_handler ipoib_eth_addr_handlers[] = {
329
+	{ 0x02, 0xc9, ipoib_mlx_eth_addr },
330
+};
331
+
332
+/**
333
+ * Generate Ethernet-compatible compressed link-layer address
334
+ *
335
+ * @v ll_addr		Link-layer address
336
+ * @v eth_addr		Ethernet-compatible address to fill in
337
+ */
338
+static int ipoib_eth_addr ( const void *ll_addr, void *eth_addr ) {
339
+	const struct ipoib_mac *ipoib_addr = ll_addr;
340
+	const struct ib_gid_half *guid = &ipoib_addr->gid.u.half[1];
341
+	struct ipoib_eth_addr_handler *handler;
342
+	unsigned int i;
343
+
344
+	for ( i = 0 ; i < ( sizeof ( ipoib_eth_addr_handlers ) /
345
+			    sizeof ( ipoib_eth_addr_handlers[0] ) ) ; i++ ) {
346
+		handler = &ipoib_eth_addr_handlers[i];
347
+		if ( ( handler->byte1 == guid->u.bytes[1] ) &&
348
+		     ( handler->byte2 == guid->u.bytes[2] ) ) {
349
+			return handler->eth_addr ( guid, eth_addr );
350
+		}
351
+	}
352
+	return -ENOTSUP;
353
+}
354
+
299
 /** IPoIB protocol */
355
 /** IPoIB protocol */
300
 struct ll_protocol ipoib_protocol __ll_protocol = {
356
 struct ll_protocol ipoib_protocol __ll_protocol = {
301
 	.name		= "IPoIB",
357
 	.name		= "IPoIB",
308
 	.init_addr	= ipoib_init_addr,
364
 	.init_addr	= ipoib_init_addr,
309
 	.ntoa		= ipoib_ntoa,
365
 	.ntoa		= ipoib_ntoa,
310
 	.mc_hash	= ipoib_mc_hash,
366
 	.mc_hash	= ipoib_mc_hash,
367
+	.eth_addr	= ipoib_eth_addr,
311
 };
368
 };
312
 
369
 
313
 /**
370
 /**

+ 1
- 0
src/include/gpxe/ethernet.h View File

15
 extern const char * eth_ntoa ( const void *ll_addr );
15
 extern const char * eth_ntoa ( const void *ll_addr );
16
 extern int eth_mc_hash ( unsigned int af, const void *net_addr,
16
 extern int eth_mc_hash ( unsigned int af, const void *net_addr,
17
 			 void *ll_addr );
17
 			 void *ll_addr );
18
+extern int eth_eth_addr ( const void *ll_addr, void *eth_addr );
18
 extern struct net_device * alloc_etherdev ( size_t priv_size );
19
 extern struct net_device * alloc_etherdev ( size_t priv_size );
19
 
20
 
20
 #endif /* _GPXE_ETHERNET_H */
21
 #endif /* _GPXE_ETHERNET_H */

+ 13
- 6
src/include/gpxe/netdevice.h View File

128
 	/**
128
 	/**
129
 	 * Transcribe link-layer address
129
 	 * Transcribe link-layer address
130
 	 *
130
 	 *
131
-	 * @v ll_addr	Link-layer address
132
-	 * @ret string	Human-readable transcription of address
131
+	 * @v ll_addr		Link-layer address
132
+	 * @ret string		Human-readable transcription of address
133
 	 *
133
 	 *
134
 	 * This method should convert the link-layer address into a
134
 	 * This method should convert the link-layer address into a
135
 	 * human-readable format.
135
 	 * human-readable format.
141
 	/**
141
 	/**
142
 	 * Hash multicast address
142
 	 * Hash multicast address
143
 	 *
143
 	 *
144
-	 * @v af	Address family
145
-	 * @v net_addr	Network-layer address
146
-	 * @v ll_addr	Link-layer address to fill in
147
-	 * @ret rc	Return status code
144
+	 * @v af		Address family
145
+	 * @v net_addr		Network-layer address
146
+	 * @v ll_addr		Link-layer address to fill in
147
+	 * @ret rc		Return status code
148
 	 */
148
 	 */
149
 	int ( * mc_hash ) ( unsigned int af, const void *net_addr,
149
 	int ( * mc_hash ) ( unsigned int af, const void *net_addr,
150
 			    void *ll_addr );
150
 			    void *ll_addr );
151
+	/**
152
+	 * Generate Ethernet-compatible compressed link-layer address
153
+	 *
154
+	 * @v ll_addr		Link-layer address
155
+	 * @v eth_addr		Ethernet-compatible address to fill in
156
+	 */
157
+	int ( * eth_addr ) ( const void *ll_addr, void *eth_addr );
151
 	/** Link-layer protocol
158
 	/** Link-layer protocol
152
 	 *
159
 	 *
153
 	 * This is an ARPHRD_XXX constant, in network byte order.
160
 	 * This is an ARPHRD_XXX constant, in network byte order.

+ 1
- 0
src/net/80211/net80211.c View File

586
 	.init_addr = eth_init_addr,
586
 	.init_addr = eth_init_addr,
587
 	.ntoa = eth_ntoa,
587
 	.ntoa = eth_ntoa,
588
 	.mc_hash = eth_mc_hash,
588
 	.mc_hash = eth_mc_hash,
589
+	.eth_addr = eth_eth_addr,
589
 	.ll_proto = htons ( ARPHRD_ETHER ),	/* "encapsulated Ethernet" */
590
 	.ll_proto = htons ( ARPHRD_ETHER ),	/* "encapsulated Ethernet" */
590
 	.hw_addr_len = ETH_ALEN,
591
 	.hw_addr_len = ETH_ALEN,
591
 	.ll_addr_len = ETH_ALEN,
592
 	.ll_addr_len = ETH_ALEN,

+ 12
- 0
src/net/ethernet.c View File

148
 	}
148
 	}
149
 }
149
 }
150
 
150
 
151
+/**
152
+ * Generate Ethernet-compatible compressed link-layer address
153
+ *
154
+ * @v ll_addr		Link-layer address
155
+ * @v eth_addr		Ethernet-compatible address to fill in
156
+ */
157
+int eth_eth_addr ( const void *ll_addr, void *eth_addr ) {
158
+	memcpy ( eth_addr, ll_addr, ETH_ALEN );
159
+	return 0;
160
+}
161
+
151
 /** Ethernet protocol */
162
 /** Ethernet protocol */
152
 struct ll_protocol ethernet_protocol __ll_protocol = {
163
 struct ll_protocol ethernet_protocol __ll_protocol = {
153
 	.name		= "Ethernet",
164
 	.name		= "Ethernet",
160
 	.init_addr	= eth_init_addr,
171
 	.init_addr	= eth_init_addr,
161
 	.ntoa		= eth_ntoa,
172
 	.ntoa		= eth_ntoa,
162
 	.mc_hash	= eth_mc_hash,
173
 	.mc_hash	= eth_mc_hash,
174
+	.eth_addr	= eth_eth_addr,
163
 };
175
 };
164
 
176
 
165
 /**
177
 /**

Loading…
Cancel
Save