[netdevice] Allow the hardware and link-layer addresses to differ in size

IPoIB has a 20-byte link-layer address, of which only eight bytes
represent anything relating to a "hardware address".

The PXE and EFI SNP APIs expect the permanent address to be the same
size as the link-layer address, so fill in the "permanent address"
field with the initial link layer address (as generated by
register_netdev() based upon the real hardware address).
This commit is contained in:
Michael Brown
2009-08-11 23:40:27 +01:00
parent 37a0aab4ff
commit 4eab5bc8ca
8 changed files with 66 additions and 17 deletions

View File

@@ -412,6 +412,7 @@ PXENV_EXIT_t pxenv_undi_get_information ( struct s_PXENV_UNDI_GET_INFORMATION
*undi_get_information ) { *undi_get_information ) {
struct device *dev = pxe_netdev->dev; struct device *dev = pxe_netdev->dev;
struct ll_protocol *ll_protocol = pxe_netdev->ll_protocol; struct ll_protocol *ll_protocol = pxe_netdev->ll_protocol;
size_t ll_addr_len = ll_protocol->ll_addr_len;
DBG ( "PXENV_UNDI_GET_INFORMATION" ); DBG ( "PXENV_UNDI_GET_INFORMATION" );
@@ -420,13 +421,14 @@ PXENV_EXIT_t pxenv_undi_get_information ( struct s_PXENV_UNDI_GET_INFORMATION
/* Cheat: assume all cards can cope with this */ /* Cheat: assume all cards can cope with this */
undi_get_information->MaxTranUnit = ETH_MAX_MTU; undi_get_information->MaxTranUnit = ETH_MAX_MTU;
undi_get_information->HwType = ntohs ( ll_protocol->ll_proto ); undi_get_information->HwType = ntohs ( ll_protocol->ll_proto );
undi_get_information->HwAddrLen = ll_protocol->ll_addr_len; undi_get_information->HwAddrLen = ll_addr_len;
assert ( ll_addr_len <=
sizeof ( undi_get_information->CurrentNodeAddress ) );
memcpy ( &undi_get_information->CurrentNodeAddress, memcpy ( &undi_get_information->CurrentNodeAddress,
pxe_netdev->ll_addr, pxe_netdev->ll_addr,
sizeof ( undi_get_information->CurrentNodeAddress ) ); sizeof ( undi_get_information->CurrentNodeAddress ) );
memcpy ( &undi_get_information->PermNodeAddress, ll_protocol->init_addr ( pxe_netdev->hw_addr,
pxe_netdev->hw_addr, &undi_get_information->PermNodeAddress );
sizeof ( undi_get_information->PermNodeAddress ) );
undi_get_information->ROMAddress = 0; undi_get_information->ROMAddress = 0;
/* nic.rom_info->rom_segment; */ /* nic.rom_info->rom_segment; */
/* We only provide the ability to receive or transmit a single /* We only provide the ability to receive or transmit a single

View File

@@ -250,7 +250,21 @@ static int ipoib_pull ( struct net_device *netdev,
} }
/** /**
* Transcribe IPoIB address * Initialise IPoIB link-layer address
*
* @v hw_addr Hardware address
* @v ll_addr Link-layer address
*/
static void ipoib_init_addr ( const void *hw_addr, void *ll_addr ) {
const struct ib_gid_half *guid = hw_addr;
struct ipoib_mac *mac = ll_addr;
memset ( mac, 0, sizeof ( *mac ) );
memcpy ( &mac->gid.u.half[1], guid, sizeof ( mac->gid.u.half[1] ) );
}
/**
* Transcribe IPoIB link-layer address
* *
* @v ll_addr Link-layer address * @v ll_addr Link-layer address
* @ret string Link-layer address in human-readable format * @ret string Link-layer address in human-readable format
@@ -286,10 +300,12 @@ static int ipoib_mc_hash ( unsigned int af __unused,
struct ll_protocol ipoib_protocol __ll_protocol = { struct ll_protocol ipoib_protocol __ll_protocol = {
.name = "IPoIB", .name = "IPoIB",
.ll_proto = htons ( ARPHRD_INFINIBAND ), .ll_proto = htons ( ARPHRD_INFINIBAND ),
.hw_addr_len = sizeof ( struct ib_gid_half ),
.ll_addr_len = IPOIB_ALEN, .ll_addr_len = IPOIB_ALEN,
.ll_header_len = IPOIB_HLEN, .ll_header_len = IPOIB_HLEN,
.push = ipoib_push, .push = ipoib_push,
.pull = ipoib_pull, .pull = ipoib_pull,
.init_addr = ipoib_init_addr,
.ntoa = ipoib_ntoa, .ntoa = ipoib_ntoa,
.mc_hash = ipoib_mc_hash, .mc_hash = ipoib_mc_hash,
}; };
@@ -653,7 +669,6 @@ void ipoib_link_state_changed ( struct ib_device *ibdev ) {
int ipoib_probe ( struct ib_device *ibdev ) { int ipoib_probe ( struct ib_device *ibdev ) {
struct net_device *netdev; struct net_device *netdev;
struct ipoib_device *ipoib; struct ipoib_device *ipoib;
struct ipoib_mac *mac;
int rc; int rc;
/* Allocate network device */ /* Allocate network device */
@@ -669,9 +684,8 @@ int ipoib_probe ( struct ib_device *ibdev ) {
ipoib->ibdev = ibdev; ipoib->ibdev = ibdev;
/* Extract hardware address */ /* Extract hardware address */
mac = ( ( struct ipoib_mac * ) netdev->hw_addr ); memcpy ( netdev->hw_addr, &ibdev->gid.u.half[1],
memcpy ( &mac->gid.u.half[1], &ibdev->gid.u.half[1], sizeof ( ibdev->gid.u.half[1] ) );
sizeof ( mac->gid.u.half[1] ) );
/* Set default broadcast address */ /* Set default broadcast address */
memcpy ( &ipoib->broadcast, &ipoib_broadcast, memcpy ( &ipoib->broadcast, &ipoib_broadcast,

View File

@@ -11,6 +11,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <stdint.h> #include <stdint.h>
extern void eth_init_addr ( const void *hw_addr, void *ll_addr );
extern const char * eth_ntoa ( const void *ll_addr ); extern const char * eth_ntoa ( const void *ll_addr );
extern struct net_device * alloc_etherdev ( size_t priv_size ); extern struct net_device * alloc_etherdev ( size_t priv_size );

View File

@@ -21,6 +21,12 @@ struct net_protocol;
struct ll_protocol; struct ll_protocol;
struct device; struct device;
/** Maximum length of a hardware address
*
* The longest currently-supported link-layer address is for IPoIB.
*/
#define MAX_HW_ADDR_LEN 8
/** Maximum length of a link-layer address /** Maximum length of a link-layer address
* *
* The longest currently-supported link-layer address is for IPoIB. * The longest currently-supported link-layer address is for IPoIB.
@@ -112,6 +118,13 @@ struct ll_protocol {
int ( * pull ) ( struct net_device *netdev, struct io_buffer *iobuf, int ( * pull ) ( struct net_device *netdev, struct io_buffer *iobuf,
const void **ll_dest, const void **ll_source, const void **ll_dest, const void **ll_source,
uint16_t *net_proto ); uint16_t *net_proto );
/**
* Initialise link-layer address
*
* @v hw_addr Hardware address
* @v ll_addr Link-layer address to fill in
*/
void ( * init_addr ) ( const void *hw_addr, void *ll_addr );
/** /**
* Transcribe link-layer address * Transcribe link-layer address
* *
@@ -124,7 +137,7 @@ struct ll_protocol {
* The buffer used to hold the transcription is statically * The buffer used to hold the transcription is statically
* allocated. * allocated.
*/ */
const char * ( * ntoa ) ( const void * ll_addr ); const char * ( * ntoa ) ( const void *ll_addr );
/** /**
* Hash multicast address * Hash multicast address
* *
@@ -140,6 +153,8 @@ struct ll_protocol {
* This is an ARPHRD_XXX constant, in network byte order. * This is an ARPHRD_XXX constant, in network byte order.
*/ */
uint16_t ll_proto; uint16_t ll_proto;
/** Hardware address length */
uint8_t hw_addr_len;
/** Link-layer address length */ /** Link-layer address length */
uint8_t ll_addr_len; uint8_t ll_addr_len;
/** Link-layer header length */ /** Link-layer header length */
@@ -258,8 +273,11 @@ struct net_device {
* *
* This is an address which is an intrinsic property of the * This is an address which is an intrinsic property of the
* hardware, e.g. an address held in EEPROM. * hardware, e.g. an address held in EEPROM.
*
* Note that the hardware address may not be the same length
* as the link-layer address.
*/ */
uint8_t hw_addr[MAX_LL_ADDR_LEN]; uint8_t hw_addr[MAX_HW_ADDR_LEN];
/** Link-layer address /** Link-layer address
* *
* This is the current link-layer address assigned to the * This is the current link-layer address assigned to the

View File

@@ -119,10 +119,11 @@ static EFI_GUID efi_pci_io_protocol_guid
static void efi_snp_set_mode ( struct efi_snp_device *snpdev ) { static void efi_snp_set_mode ( struct efi_snp_device *snpdev ) {
struct net_device *netdev = snpdev->netdev; struct net_device *netdev = snpdev->netdev;
EFI_SIMPLE_NETWORK_MODE *mode = &snpdev->mode; EFI_SIMPLE_NETWORK_MODE *mode = &snpdev->mode;
unsigned int ll_addr_len = netdev->ll_protocol->ll_addr_len; struct ll_protocol *ll_protocol = netdev->ll_protocol;
unsigned int ll_addr_len = ll_protocol->ll_addr_len;
mode->HwAddressSize = ll_addr_len; mode->HwAddressSize = ll_addr_len;
mode->MediaHeaderSize = netdev->ll_protocol->ll_header_len; mode->MediaHeaderSize = ll_protocol->ll_header_len;
mode->MaxPacketSize = netdev->max_pkt_len; mode->MaxPacketSize = netdev->max_pkt_len;
mode->ReceiveFilterMask = ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST | mode->ReceiveFilterMask = ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST | EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST |
@@ -130,8 +131,8 @@ static void efi_snp_set_mode ( struct efi_snp_device *snpdev ) {
assert ( ll_addr_len <= sizeof ( mode->CurrentAddress ) ); assert ( ll_addr_len <= sizeof ( mode->CurrentAddress ) );
memcpy ( &mode->CurrentAddress, netdev->ll_addr, ll_addr_len ); memcpy ( &mode->CurrentAddress, netdev->ll_addr, ll_addr_len );
memcpy ( &mode->BroadcastAddress, netdev->ll_broadcast, ll_addr_len ); memcpy ( &mode->BroadcastAddress, netdev->ll_broadcast, ll_addr_len );
memcpy ( &mode->PermanentAddress, netdev->hw_addr, ll_addr_len ); ll_protocol->init_addr ( netdev->hw_addr, &mode->PermanentAddress );
mode->IfType = ntohs ( netdev->ll_protocol->ll_proto ); mode->IfType = ntohs ( ll_protocol->ll_proto );
mode->MacAddressChangeable = TRUE; mode->MacAddressChangeable = TRUE;
mode->MediaPresentSupported = TRUE; mode->MediaPresentSupported = TRUE;
mode->MediaPresent = ( netdev_link_ok ( netdev ) ? TRUE : FALSE ); mode->MediaPresent = ( netdev_link_ok ( netdev ) ? TRUE : FALSE );

View File

@@ -602,9 +602,11 @@ static struct ll_protocol net80211_ll_protocol __ll_protocol = {
.name = "802.11", .name = "802.11",
.push = net80211_ll_push, .push = net80211_ll_push,
.pull = net80211_ll_pull, .pull = net80211_ll_pull,
.init_addr = eth_init_addr,
.ntoa = eth_ntoa, .ntoa = eth_ntoa,
.mc_hash = net80211_ll_mc_hash, .mc_hash = net80211_ll_mc_hash,
.ll_proto = htons ( ARPHRD_ETHER ), /* "encapsulated Ethernet" */ .ll_proto = htons ( ARPHRD_ETHER ), /* "encapsulated Ethernet" */
.hw_addr_len = ETH_ALEN,
.ll_addr_len = ETH_ALEN, .ll_addr_len = ETH_ALEN,
.ll_header_len = IEEE80211_TYP_FRAME_HEADER_LEN + .ll_header_len = IEEE80211_TYP_FRAME_HEADER_LEN +
IEEE80211_LLC_HEADER_LEN, IEEE80211_LLC_HEADER_LEN,

View File

@@ -96,6 +96,16 @@ static int eth_pull ( struct net_device *netdev __unused,
return 0; return 0;
} }
/**
* Initialise Ethernet address
*
* @v hw_addr Hardware address
* @v ll_addr Link-layer address
*/
void eth_init_addr ( const void *hw_addr, void *ll_addr ) {
memcpy ( ll_addr, hw_addr, ETH_ALEN );
}
/** /**
* Transcribe Ethernet address * Transcribe Ethernet address
* *
@@ -143,10 +153,12 @@ static int eth_mc_hash ( unsigned int af, const void *net_addr,
struct ll_protocol ethernet_protocol __ll_protocol = { struct ll_protocol ethernet_protocol __ll_protocol = {
.name = "Ethernet", .name = "Ethernet",
.ll_proto = htons ( ARPHRD_ETHER ), .ll_proto = htons ( ARPHRD_ETHER ),
.hw_addr_len = ETH_ALEN,
.ll_addr_len = ETH_ALEN, .ll_addr_len = ETH_ALEN,
.ll_header_len = ETH_HLEN, .ll_header_len = ETH_HLEN,
.push = eth_push, .push = eth_push,
.pull = eth_pull, .pull = eth_pull,
.init_addr = eth_init_addr,
.ntoa = eth_ntoa, .ntoa = eth_ntoa,
.mc_hash = eth_mc_hash, .mc_hash = eth_mc_hash,
}; };

View File

@@ -358,8 +358,7 @@ int register_netdev ( struct net_device *netdev ) {
ifindex++ ); ifindex++ );
/* Set initial link-layer address */ /* Set initial link-layer address */
memcpy ( netdev->ll_addr, netdev->hw_addr, netdev->ll_protocol->init_addr ( netdev->hw_addr, netdev->ll_addr );
netdev->ll_protocol->ll_addr_len );
/* Register per-netdev configuration settings */ /* Register per-netdev configuration settings */
if ( ( rc = register_settings ( netdev_settings ( netdev ), if ( ( rc = register_settings ( netdev_settings ( netdev ),