diff options
author | Michael Brown <mcb30@etherboot.org> | 2009-08-11 23:40:27 +0100 |
---|---|---|
committer | Michael Brown <mcb30@etherboot.org> | 2009-08-12 00:23:38 +0100 |
commit | 4eab5bc8ca6b66dc965cf188dd4577ad19c5b879 (patch) | |
tree | 840f354a2f0efa010368118729e8f16315abc1c4 | |
parent | 37a0aab4ff2c86f4d109d4cd479535be97d07a94 (diff) | |
download | ipxe-4eab5bc8ca6b66dc965cf188dd4577ad19c5b879.tar.gz |
[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).
-rw-r--r-- | src/arch/i386/interface/pxe/pxe_undi.c | 10 | ||||
-rw-r--r-- | src/drivers/net/ipoib.c | 24 | ||||
-rw-r--r-- | src/include/gpxe/ethernet.h | 1 | ||||
-rw-r--r-- | src/include/gpxe/netdevice.h | 22 | ||||
-rw-r--r-- | src/interface/efi/efi_snp.c | 9 | ||||
-rw-r--r-- | src/net/80211/net80211.c | 2 | ||||
-rw-r--r-- | src/net/ethernet.c | 12 | ||||
-rw-r--r-- | src/net/netdevice.c | 3 |
8 files changed, 66 insertions, 17 deletions
diff --git a/src/arch/i386/interface/pxe/pxe_undi.c b/src/arch/i386/interface/pxe/pxe_undi.c index 48c274b1..c9b67c06 100644 --- a/src/arch/i386/interface/pxe/pxe_undi.c +++ b/src/arch/i386/interface/pxe/pxe_undi.c @@ -412,6 +412,7 @@ PXENV_EXIT_t pxenv_undi_get_information ( struct s_PXENV_UNDI_GET_INFORMATION *undi_get_information ) { struct device *dev = pxe_netdev->dev; struct ll_protocol *ll_protocol = pxe_netdev->ll_protocol; + size_t ll_addr_len = ll_protocol->ll_addr_len; 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 */ undi_get_information->MaxTranUnit = ETH_MAX_MTU; 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, pxe_netdev->ll_addr, sizeof ( undi_get_information->CurrentNodeAddress ) ); - memcpy ( &undi_get_information->PermNodeAddress, - pxe_netdev->hw_addr, - sizeof ( undi_get_information->PermNodeAddress ) ); + ll_protocol->init_addr ( pxe_netdev->hw_addr, + &undi_get_information->PermNodeAddress ); undi_get_information->ROMAddress = 0; /* nic.rom_info->rom_segment; */ /* We only provide the ability to receive or transmit a single diff --git a/src/drivers/net/ipoib.c b/src/drivers/net/ipoib.c index c2a6d349..dde4ee5a 100644 --- a/src/drivers/net/ipoib.c +++ b/src/drivers/net/ipoib.c @@ -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 * @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 = { .name = "IPoIB", .ll_proto = htons ( ARPHRD_INFINIBAND ), + .hw_addr_len = sizeof ( struct ib_gid_half ), .ll_addr_len = IPOIB_ALEN, .ll_header_len = IPOIB_HLEN, .push = ipoib_push, .pull = ipoib_pull, + .init_addr = ipoib_init_addr, .ntoa = ipoib_ntoa, .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 ) { struct net_device *netdev; struct ipoib_device *ipoib; - struct ipoib_mac *mac; int rc; /* Allocate network device */ @@ -669,9 +684,8 @@ int ipoib_probe ( struct ib_device *ibdev ) { ipoib->ibdev = ibdev; /* Extract hardware address */ - mac = ( ( struct ipoib_mac * ) netdev->hw_addr ); - memcpy ( &mac->gid.u.half[1], &ibdev->gid.u.half[1], - sizeof ( mac->gid.u.half[1] ) ); + memcpy ( netdev->hw_addr, &ibdev->gid.u.half[1], + sizeof ( ibdev->gid.u.half[1] ) ); /* Set default broadcast address */ memcpy ( &ipoib->broadcast, &ipoib_broadcast, diff --git a/src/include/gpxe/ethernet.h b/src/include/gpxe/ethernet.h index 9bd3455c..bb82e0a4 100644 --- a/src/include/gpxe/ethernet.h +++ b/src/include/gpxe/ethernet.h @@ -11,6 +11,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #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 struct net_device * alloc_etherdev ( size_t priv_size ); diff --git a/src/include/gpxe/netdevice.h b/src/include/gpxe/netdevice.h index 5ac2f629..fd77d893 100644 --- a/src/include/gpxe/netdevice.h +++ b/src/include/gpxe/netdevice.h @@ -21,6 +21,12 @@ struct net_protocol; struct ll_protocol; 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 * * The longest currently-supported link-layer address is for IPoIB. @@ -113,6 +119,13 @@ struct ll_protocol { const void **ll_dest, const void **ll_source, 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 * * @v ll_addr Link-layer address @@ -124,7 +137,7 @@ struct ll_protocol { * The buffer used to hold the transcription is statically * allocated. */ - const char * ( * ntoa ) ( const void * ll_addr ); + const char * ( * ntoa ) ( const void *ll_addr ); /** * Hash multicast address * @@ -140,6 +153,8 @@ struct ll_protocol { * This is an ARPHRD_XXX constant, in network byte order. */ uint16_t ll_proto; + /** Hardware address length */ + uint8_t hw_addr_len; /** Link-layer address length */ uint8_t ll_addr_len; /** Link-layer header length */ @@ -258,8 +273,11 @@ struct net_device { * * This is an address which is an intrinsic property of the * 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 * * This is the current link-layer address assigned to the diff --git a/src/interface/efi/efi_snp.c b/src/interface/efi/efi_snp.c index 00830343..b5241e54 100644 --- a/src/interface/efi/efi_snp.c +++ b/src/interface/efi/efi_snp.c @@ -119,10 +119,11 @@ static EFI_GUID efi_pci_io_protocol_guid static void efi_snp_set_mode ( struct efi_snp_device *snpdev ) { struct net_device *netdev = snpdev->netdev; 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->MediaHeaderSize = netdev->ll_protocol->ll_header_len; + mode->MediaHeaderSize = ll_protocol->ll_header_len; mode->MaxPacketSize = netdev->max_pkt_len; mode->ReceiveFilterMask = ( EFI_SIMPLE_NETWORK_RECEIVE_UNICAST | 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 ) ); memcpy ( &mode->CurrentAddress, netdev->ll_addr, ll_addr_len ); memcpy ( &mode->BroadcastAddress, netdev->ll_broadcast, ll_addr_len ); - memcpy ( &mode->PermanentAddress, netdev->hw_addr, ll_addr_len ); - mode->IfType = ntohs ( netdev->ll_protocol->ll_proto ); + ll_protocol->init_addr ( netdev->hw_addr, &mode->PermanentAddress ); + mode->IfType = ntohs ( ll_protocol->ll_proto ); mode->MacAddressChangeable = TRUE; mode->MediaPresentSupported = TRUE; mode->MediaPresent = ( netdev_link_ok ( netdev ) ? TRUE : FALSE ); diff --git a/src/net/80211/net80211.c b/src/net/80211/net80211.c index f3612853..a07e2fab 100644 --- a/src/net/80211/net80211.c +++ b/src/net/80211/net80211.c @@ -602,9 +602,11 @@ static struct ll_protocol net80211_ll_protocol __ll_protocol = { .name = "802.11", .push = net80211_ll_push, .pull = net80211_ll_pull, + .init_addr = eth_init_addr, .ntoa = eth_ntoa, .mc_hash = net80211_ll_mc_hash, .ll_proto = htons ( ARPHRD_ETHER ), /* "encapsulated Ethernet" */ + .hw_addr_len = ETH_ALEN, .ll_addr_len = ETH_ALEN, .ll_header_len = IEEE80211_TYP_FRAME_HEADER_LEN + IEEE80211_LLC_HEADER_LEN, diff --git a/src/net/ethernet.c b/src/net/ethernet.c index 5e2793f9..dfeba7cd 100644 --- a/src/net/ethernet.c +++ b/src/net/ethernet.c @@ -97,6 +97,16 @@ static int eth_pull ( struct net_device *netdev __unused, } /** + * 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 * * @v ll_addr Link-layer address @@ -143,10 +153,12 @@ static int eth_mc_hash ( unsigned int af, const void *net_addr, struct ll_protocol ethernet_protocol __ll_protocol = { .name = "Ethernet", .ll_proto = htons ( ARPHRD_ETHER ), + .hw_addr_len = ETH_ALEN, .ll_addr_len = ETH_ALEN, .ll_header_len = ETH_HLEN, .push = eth_push, .pull = eth_pull, + .init_addr = eth_init_addr, .ntoa = eth_ntoa, .mc_hash = eth_mc_hash, }; diff --git a/src/net/netdevice.c b/src/net/netdevice.c index f43ca8a4..ee0d0b72 100644 --- a/src/net/netdevice.c +++ b/src/net/netdevice.c @@ -358,8 +358,7 @@ int register_netdev ( struct net_device *netdev ) { ifindex++ ); /* Set initial link-layer address */ - memcpy ( netdev->ll_addr, netdev->hw_addr, - netdev->ll_protocol->ll_addr_len ); + netdev->ll_protocol->init_addr ( netdev->hw_addr, netdev->ll_addr ); /* Register per-netdev configuration settings */ if ( ( rc = register_settings ( netdev_settings ( netdev ), |