summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/drivers/net/ipoib.c57
-rw-r--r--src/include/gpxe/ethernet.h1
-rw-r--r--src/include/gpxe/netdevice.h19
-rw-r--r--src/net/80211/net80211.c1
-rw-r--r--src/net/ethernet.c12
5 files changed, 84 insertions, 6 deletions
diff --git a/src/drivers/net/ipoib.c b/src/drivers/net/ipoib.c
index dde4ee5a..260d2d0e 100644
--- a/src/drivers/net/ipoib.c
+++ b/src/drivers/net/ipoib.c
@@ -296,6 +296,62 @@ static int ipoib_mc_hash ( unsigned int af __unused,
return -ENOTSUP;
}
+/**
+ * Generate Mellanox Ethernet-compatible compressed link-layer address
+ *
+ * @v ll_addr Link-layer address
+ * @v eth_addr Ethernet-compatible address to fill in
+ */
+static int ipoib_mlx_eth_addr ( const struct ib_gid_half *guid,
+ uint8_t *eth_addr ) {
+ eth_addr[0] = ( ( guid->u.bytes[3] == 2 ) ? 0x00 : 0x02 );
+ eth_addr[1] = guid->u.bytes[1];
+ eth_addr[2] = guid->u.bytes[2];
+ eth_addr[3] = guid->u.bytes[5];
+ eth_addr[4] = guid->u.bytes[6];
+ eth_addr[5] = guid->u.bytes[7];
+ return 0;
+}
+
+/** An IPoIB Ethernet-compatible compressed link-layer address generator */
+struct ipoib_eth_addr_handler {
+ /** GUID byte 1 */
+ uint8_t byte1;
+ /** GUID byte 2 */
+ uint8_t byte2;
+ /** Handler */
+ int ( * eth_addr ) ( const struct ib_gid_half *guid,
+ uint8_t *eth_addr );
+};
+
+/** IPoIB Ethernet-compatible compressed link-layer address generators */
+static struct ipoib_eth_addr_handler ipoib_eth_addr_handlers[] = {
+ { 0x02, 0xc9, ipoib_mlx_eth_addr },
+};
+
+/**
+ * Generate Ethernet-compatible compressed link-layer address
+ *
+ * @v ll_addr Link-layer address
+ * @v eth_addr Ethernet-compatible address to fill in
+ */
+static int ipoib_eth_addr ( const void *ll_addr, void *eth_addr ) {
+ const struct ipoib_mac *ipoib_addr = ll_addr;
+ const struct ib_gid_half *guid = &ipoib_addr->gid.u.half[1];
+ struct ipoib_eth_addr_handler *handler;
+ unsigned int i;
+
+ for ( i = 0 ; i < ( sizeof ( ipoib_eth_addr_handlers ) /
+ sizeof ( ipoib_eth_addr_handlers[0] ) ) ; i++ ) {
+ handler = &ipoib_eth_addr_handlers[i];
+ if ( ( handler->byte1 == guid->u.bytes[1] ) &&
+ ( handler->byte2 == guid->u.bytes[2] ) ) {
+ return handler->eth_addr ( guid, eth_addr );
+ }
+ }
+ return -ENOTSUP;
+}
+
/** IPoIB protocol */
struct ll_protocol ipoib_protocol __ll_protocol = {
.name = "IPoIB",
@@ -308,6 +364,7 @@ struct ll_protocol ipoib_protocol __ll_protocol = {
.init_addr = ipoib_init_addr,
.ntoa = ipoib_ntoa,
.mc_hash = ipoib_mc_hash,
+ .eth_addr = ipoib_eth_addr,
};
/**
diff --git a/src/include/gpxe/ethernet.h b/src/include/gpxe/ethernet.h
index 8cf6b1be..4dfc24d3 100644
--- a/src/include/gpxe/ethernet.h
+++ b/src/include/gpxe/ethernet.h
@@ -15,6 +15,7 @@ extern void eth_init_addr ( const void *hw_addr, void *ll_addr );
extern const char * eth_ntoa ( const void *ll_addr );
extern int eth_mc_hash ( unsigned int af, const void *net_addr,
void *ll_addr );
+extern int eth_eth_addr ( const void *ll_addr, void *eth_addr );
extern struct net_device * alloc_etherdev ( size_t priv_size );
#endif /* _GPXE_ETHERNET_H */
diff --git a/src/include/gpxe/netdevice.h b/src/include/gpxe/netdevice.h
index fd77d893..858d8e97 100644
--- a/src/include/gpxe/netdevice.h
+++ b/src/include/gpxe/netdevice.h
@@ -128,8 +128,8 @@ struct ll_protocol {
/**
* Transcribe link-layer address
*
- * @v ll_addr Link-layer address
- * @ret string Human-readable transcription of address
+ * @v ll_addr Link-layer address
+ * @ret string Human-readable transcription of address
*
* This method should convert the link-layer address into a
* human-readable format.
@@ -141,13 +141,20 @@ struct ll_protocol {
/**
* Hash multicast address
*
- * @v af Address family
- * @v net_addr Network-layer address
- * @v ll_addr Link-layer address to fill in
- * @ret rc Return status code
+ * @v af Address family
+ * @v net_addr Network-layer address
+ * @v ll_addr Link-layer address to fill in
+ * @ret rc Return status code
*/
int ( * mc_hash ) ( unsigned int af, const void *net_addr,
void *ll_addr );
+ /**
+ * Generate Ethernet-compatible compressed link-layer address
+ *
+ * @v ll_addr Link-layer address
+ * @v eth_addr Ethernet-compatible address to fill in
+ */
+ int ( * eth_addr ) ( const void *ll_addr, void *eth_addr );
/** Link-layer protocol
*
* This is an ARPHRD_XXX constant, in network byte order.
diff --git a/src/net/80211/net80211.c b/src/net/80211/net80211.c
index 1fc983a0..c3d9fc61 100644
--- a/src/net/80211/net80211.c
+++ b/src/net/80211/net80211.c
@@ -586,6 +586,7 @@ static struct ll_protocol net80211_ll_protocol __ll_protocol = {
.init_addr = eth_init_addr,
.ntoa = eth_ntoa,
.mc_hash = eth_mc_hash,
+ .eth_addr = eth_eth_addr,
.ll_proto = htons ( ARPHRD_ETHER ), /* "encapsulated Ethernet" */
.hw_addr_len = ETH_ALEN,
.ll_addr_len = ETH_ALEN,
diff --git a/src/net/ethernet.c b/src/net/ethernet.c
index e8daf9f9..79ed1dc6 100644
--- a/src/net/ethernet.c
+++ b/src/net/ethernet.c
@@ -148,6 +148,17 @@ int eth_mc_hash ( unsigned int af, const void *net_addr, void *ll_addr ) {
}
}
+/**
+ * Generate Ethernet-compatible compressed link-layer address
+ *
+ * @v ll_addr Link-layer address
+ * @v eth_addr Ethernet-compatible address to fill in
+ */
+int eth_eth_addr ( const void *ll_addr, void *eth_addr ) {
+ memcpy ( eth_addr, ll_addr, ETH_ALEN );
+ return 0;
+}
+
/** Ethernet protocol */
struct ll_protocol ethernet_protocol __ll_protocol = {
.name = "Ethernet",
@@ -160,6 +171,7 @@ struct ll_protocol ethernet_protocol __ll_protocol = {
.init_addr = eth_init_addr,
.ntoa = eth_ntoa,
.mc_hash = eth_mc_hash,
+ .eth_addr = eth_eth_addr,
};
/**