From 37a0aab4ff2c86f4d109d4cd479535be97d07a94 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 11 Aug 2009 20:19:53 +0100 Subject: [netdevice] Separate out the concept of hardware and link-layer addresses The hardware address is an intrinsic property of the hardware, while the link-layer address can be changed at runtime. This separation is exposed via APIs such as PXE and EFI, but is currently elided by gPXE. Expose the hardware and link-layer addresses as separate properties within a net device. Drivers should now fill in hw_addr, which will be used to initialise ll_addr at the time of calling register_netdev(). --- src/arch/i386/drivers/net/undinet.c | 4 +-- src/arch/i386/interface/pxe/pxe_undi.c | 6 +--- src/drivers/net/3c90x.c | 2 +- src/drivers/net/b44.c | 12 +++---- src/drivers/net/e1000/e1000.c | 2 +- src/drivers/net/etherfabric.c | 2 +- src/drivers/net/ipoib.c | 66 +++++++++++++--------------------- src/drivers/net/legacy.c | 2 +- src/drivers/net/mtnic.c | 2 +- src/drivers/net/natsemi.c | 2 +- src/drivers/net/phantom/phantom.c | 10 +++--- src/drivers/net/pnic.c | 2 +- src/drivers/net/r8169.c | 4 +-- src/drivers/net/rtl8139.c | 2 +- src/drivers/net/rtl818x/rtl818x.c | 2 +- src/drivers/net/sky2.c | 4 +-- src/include/gpxe/netdevice.h | 15 +++++--- src/interface/efi/efi_snp.c | 2 +- src/net/80211/net80211.c | 2 +- src/net/netdevice.c | 6 +++- src/usr/dhcpmgmt.c | 2 +- src/usr/ifmgmt.c | 2 +- 22 files changed, 71 insertions(+), 82 deletions(-) diff --git a/src/arch/i386/drivers/net/undinet.c b/src/arch/i386/drivers/net/undinet.c index 6c28b247..0c7f6697 100644 --- a/src/arch/i386/drivers/net/undinet.c +++ b/src/arch/i386/drivers/net/undinet.c @@ -689,7 +689,7 @@ int undinet_probe ( struct undi_device *undi ) { if ( ( rc = undinet_call ( undinic, PXENV_UNDI_GET_INFORMATION, &undi_info, sizeof ( undi_info ) ) ) != 0 ) goto err_undi_get_information; - memcpy ( netdev->ll_addr, undi_info.PermNodeAddress, ETH_ALEN ); + memcpy ( netdev->hw_addr, undi_info.PermNodeAddress, ETH_ALEN ); undinic->irq = undi_info.IntNumber; if ( undinic->irq > IRQ_MAX ) { DBGC ( undinic, "UNDINIC %p invalid IRQ %d\n", @@ -697,7 +697,7 @@ int undinet_probe ( struct undi_device *undi ) { goto err_bad_irq; } DBGC ( undinic, "UNDINIC %p is %s on IRQ %d\n", - undinic, eth_ntoa ( netdev->ll_addr ), undinic->irq ); + undinic, eth_ntoa ( netdev->hw_addr ), undinic->irq ); /* Get interface information */ memset ( &undi_iface, 0, sizeof ( undi_iface ) ); diff --git a/src/arch/i386/interface/pxe/pxe_undi.c b/src/arch/i386/interface/pxe/pxe_undi.c index ddaae844..48c274b1 100644 --- a/src/arch/i386/interface/pxe/pxe_undi.c +++ b/src/arch/i386/interface/pxe/pxe_undi.c @@ -421,15 +421,11 @@ PXENV_EXIT_t pxenv_undi_get_information ( struct s_PXENV_UNDI_GET_INFORMATION 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; - /* Cheat: assume card is always configured with its permanent - * node address. This is a valid assumption within Etherboot - * at the time of writing. - */ memcpy ( &undi_get_information->CurrentNodeAddress, pxe_netdev->ll_addr, sizeof ( undi_get_information->CurrentNodeAddress ) ); memcpy ( &undi_get_information->PermNodeAddress, - pxe_netdev->ll_addr, + pxe_netdev->hw_addr, sizeof ( undi_get_information->PermNodeAddress ) ); undi_get_information->ROMAddress = 0; /* nic.rom_info->rom_segment; */ diff --git a/src/drivers/net/3c90x.c b/src/drivers/net/3c90x.c index 83b70832..aeed6332 100644 --- a/src/drivers/net/3c90x.c +++ b/src/drivers/net/3c90x.c @@ -928,7 +928,7 @@ static int a3c90x_probe(struct pci_device *pci, /* load eeprom contents to inf_3c90x->eeprom */ a3c90x_internal_ReadEepromContents(inf_3c90x); - HWAddr = netdev->ll_addr; + HWAddr = netdev->hw_addr; /* Retrieve the Hardware address */ HWAddr[0] = inf_3c90x->eeprom[eepromHwAddrOffset + 0] >> 8; diff --git a/src/drivers/net/b44.c b/src/drivers/net/b44.c index 38c4746d..c48b3144 100644 --- a/src/drivers/net/b44.c +++ b/src/drivers/net/b44.c @@ -594,12 +594,12 @@ static void b44_load_mac_and_phy_addr(struct b44_private *bp) /* Load MAC address, note byteswapping */ b44_read_eeprom(bp, &eeprom[0]); - bp->netdev->ll_addr[0] = eeprom[79]; - bp->netdev->ll_addr[1] = eeprom[78]; - bp->netdev->ll_addr[2] = eeprom[81]; - bp->netdev->ll_addr[3] = eeprom[80]; - bp->netdev->ll_addr[4] = eeprom[83]; - bp->netdev->ll_addr[5] = eeprom[82]; + bp->netdev->hw_addr[0] = eeprom[79]; + bp->netdev->hw_addr[1] = eeprom[78]; + bp->netdev->hw_addr[2] = eeprom[81]; + bp->netdev->hw_addr[3] = eeprom[80]; + bp->netdev->hw_addr[4] = eeprom[83]; + bp->netdev->hw_addr[5] = eeprom[82]; /* Load PHY address */ bp->phy_addr = eeprom[90] & 0x1f; diff --git a/src/drivers/net/e1000/e1000.c b/src/drivers/net/e1000/e1000.c index faca1e07..af8e0936 100644 --- a/src/drivers/net/e1000/e1000.c +++ b/src/drivers/net/e1000/e1000.c @@ -853,7 +853,7 @@ e1000_probe ( struct pci_device *pdev, if ( e1000_read_mac_addr ( &adapter->hw ) ) DBG ( "EEPROM Read Error\n" ); - memcpy ( netdev->ll_addr, adapter->hw.mac_addr, ETH_ALEN ); + memcpy ( netdev->hw_addr, adapter->hw.mac_addr, ETH_ALEN ); /* print bus type/speed/width info */ { diff --git a/src/drivers/net/etherfabric.c b/src/drivers/net/etherfabric.c index ca4af502..c4296b9c 100644 --- a/src/drivers/net/etherfabric.c +++ b/src/drivers/net/etherfabric.c @@ -4181,7 +4181,7 @@ efab_probe ( struct pci_device *pci, if ( rc ) goto fail3; - memcpy ( netdev->ll_addr, efab->mac_addr, ETH_ALEN ); + memcpy ( netdev->hw_addr, efab->mac_addr, ETH_ALEN ); netdev_link_up ( netdev ); rc = register_netdev ( netdev ); diff --git a/src/drivers/net/ipoib.c b/src/drivers/net/ipoib.c index 3f149247..c2a6d349 100644 --- a/src/drivers/net/ipoib.c +++ b/src/drivers/net/ipoib.c @@ -607,38 +607,6 @@ static struct net_device_operations ipoib_operations = { .irq = ipoib_irq, }; -/** - * Update IPoIB dynamic Infiniband parameters - * - * @v ipoib IPoIB device - * - * The Infiniband port GID and partition key will change at runtime, - * when the link is established (or lost). The MAC address is based - * on the port GID, and the broadcast GID is based on the partition - * key. This function recalculates these IPoIB device parameters. - */ -static void ipoib_set_ib_params ( struct ipoib_device *ipoib ) { - struct ib_device *ibdev = ipoib->ibdev; - struct net_device *netdev = ipoib->netdev; - struct ipoib_mac *mac; - - /* Calculate GID portion of MAC address based on port GID */ - mac = ( ( struct ipoib_mac * ) netdev->ll_addr ); - memcpy ( &mac->gid, &ibdev->gid, sizeof ( mac->gid ) ); - - /* Calculate broadcast GID based on partition key */ - memcpy ( &ipoib->broadcast, &ipoib_broadcast, - sizeof ( ipoib->broadcast ) ); - ipoib->broadcast.gid.u.words[2] = htons ( ibdev->pkey ); - - /* Set net device link state to reflect Infiniband link state */ - if ( ib_link_ok ( ibdev ) ) { - netdev_link_up ( netdev ); - } else { - netdev_link_down ( netdev ); - } -} - /** * Handle link status change * @@ -647,15 +615,25 @@ static void ipoib_set_ib_params ( struct ipoib_device *ipoib ) { void ipoib_link_state_changed ( struct ib_device *ibdev ) { struct net_device *netdev = ib_get_ownerdata ( ibdev ); struct ipoib_device *ipoib = netdev->priv; + struct ipoib_mac *mac = ( ( struct ipoib_mac * ) netdev->ll_addr ); int rc; /* Leave existing broadcast group */ ipoib_leave_broadcast_group ( ipoib ); - /* Update MAC address and broadcast GID based on new port GID - * and partition key. - */ - ipoib_set_ib_params ( ipoib ); + /* Update MAC address based on potentially-new GID prefix */ + memcpy ( &mac->gid.u.half[0], &ibdev->gid.u.half[0], + sizeof ( mac->gid.u.half[0] ) ); + + /* Update broadcast GID based on potentially-new partition key */ + ipoib->broadcast.gid.u.words[2] = htons ( ibdev->pkey ); + + /* Set net device link state to reflect Infiniband link state */ + if ( ib_link_ok ( ibdev ) ) { + netdev_link_up ( netdev ); + } else { + netdev_link_down ( netdev ); + } /* Join new broadcast group */ if ( ib_link_ok ( ibdev ) && @@ -675,6 +653,7 @@ 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 */ @@ -685,16 +664,19 @@ int ipoib_probe ( struct ib_device *ibdev ) { ipoib = netdev->priv; ib_set_ownerdata ( ibdev, netdev ); netdev->dev = ibdev->dev; - netdev->ll_broadcast = ( ( uint8_t * ) &ipoib->broadcast ); memset ( ipoib, 0, sizeof ( *ipoib ) ); ipoib->netdev = netdev; ipoib->ibdev = ibdev; - /* Calculate as much of the broadcast GID and the MAC address - * as we can. We won't know either of these in full until we - * have link-up. - */ - ipoib_set_ib_params ( ipoib ); + /* 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] ) ); + + /* Set default broadcast address */ + memcpy ( &ipoib->broadcast, &ipoib_broadcast, + sizeof ( ipoib->broadcast ) ); + netdev->ll_broadcast = ( ( uint8_t * ) &ipoib->broadcast ); /* Register network device */ if ( ( rc = register_netdev ( netdev ) ) != 0 ) diff --git a/src/drivers/net/legacy.c b/src/drivers/net/legacy.c index c4bfc96a..79b3580a 100644 --- a/src/drivers/net/legacy.c +++ b/src/drivers/net/legacy.c @@ -99,7 +99,7 @@ int legacy_probe ( void *hwdev, set_drvdata ( hwdev, netdev ); netdev->dev = dev; - nic.node_addr = netdev->ll_addr; + nic.node_addr = netdev->hw_addr; nic.irqno = dev->desc.irq; if ( ! probe ( &nic, hwdev ) ) { diff --git a/src/drivers/net/mtnic.c b/src/drivers/net/mtnic.c index 7fe4b96f..d7ee8d2b 100644 --- a/src/drivers/net/mtnic.c +++ b/src/drivers/net/mtnic.c @@ -1814,7 +1814,7 @@ mtnic_probe(struct pci_device *pci, /* Program the MAC address */ mac = priv->mtnic->fw.mac[port_index]; for (mac_idx = 0; mac_idx < MAC_ADDRESS_SIZE; ++mac_idx) { - mtnic->netdev[port_index]->ll_addr[MAC_ADDRESS_SIZE - mac_idx - 1] = mac & 0xFF; + mtnic->netdev[port_index]->hw_addr[MAC_ADDRESS_SIZE - mac_idx - 1] = mac & 0xFF; mac = mac >> 8; } diff --git a/src/drivers/net/natsemi.c b/src/drivers/net/natsemi.c index 13adf2a7..8ca6271c 100644 --- a/src/drivers/net/natsemi.c +++ b/src/drivers/net/natsemi.c @@ -204,7 +204,7 @@ static int natsemi_probe (struct pci_device *pci, last = prev_bytes[1] >> 7; for ( i = 0 ; i < ETH_ALEN ; i++ ) { last1 = ll_addr_encoded[i] >> 7; - netdev->ll_addr[i] = ll_addr_encoded[i] << 1 | last; + netdev->hw_addr[i] = ll_addr_encoded[i] << 1 | last; last = last1; } diff --git a/src/drivers/net/phantom/phantom.c b/src/drivers/net/phantom/phantom.c index 85949c29..4c3f22f6 100644 --- a/src/drivers/net/phantom/phantom.c +++ b/src/drivers/net/phantom/phantom.c @@ -1897,10 +1897,10 @@ static int phantom_init_cmdpeg ( struct phantom_nic *phantom ) { * Read Phantom MAC address * * @v phanton_port Phantom NIC - * @v ll_addr Buffer to fill with MAC address + * @v hw_addr Buffer to fill with MAC address */ static void phantom_get_macaddr ( struct phantom_nic *phantom, - uint8_t *ll_addr ) { + uint8_t *hw_addr ) { union { uint8_t mac_addr[2][ETH_ALEN]; uint32_t dwords[3]; @@ -1917,11 +1917,11 @@ static void phantom_get_macaddr ( struct phantom_nic *phantom, /* Copy out the relevant MAC address */ for ( i = 0 ; i < ETH_ALEN ; i++ ) { - ll_addr[ ETH_ALEN - i - 1 ] = + hw_addr[ ETH_ALEN - i - 1 ] = u.mac_addr[ phantom->port & 1 ][i]; } DBGC ( phantom, "Phantom %p MAC address is %s\n", - phantom, eth_ntoa ( ll_addr ) ); + phantom, eth_ntoa ( hw_addr ) ); } /** @@ -2045,7 +2045,7 @@ static int phantom_probe ( struct pci_device *pci, goto err_init_rcvpeg; /* Read MAC addresses */ - phantom_get_macaddr ( phantom, netdev->ll_addr ); + phantom_get_macaddr ( phantom, netdev->hw_addr ); /* Skip if boot disabled on NIC */ if ( ( rc = phantom_check_boot_enable ( phantom ) ) != 0 ) diff --git a/src/drivers/net/pnic.c b/src/drivers/net/pnic.c index 4b728f4e..cbc67906 100644 --- a/src/drivers/net/pnic.c +++ b/src/drivers/net/pnic.c @@ -250,7 +250,7 @@ static int pnic_probe ( struct pci_device *pci, /* Get MAC address */ status = pnic_command ( pnic, PNIC_CMD_READ_MAC, NULL, 0, - netdev->ll_addr, ETH_ALEN, NULL ); + netdev->hw_addr, ETH_ALEN, NULL ); /* Mark as link up; PNIC has no concept of link state */ netdev_link_up ( netdev ); diff --git a/src/drivers/net/r8169.c b/src/drivers/net/r8169.c index 08c44a28..b4687820 100644 --- a/src/drivers/net/r8169.c +++ b/src/drivers/net/r8169.c @@ -2209,9 +2209,9 @@ rtl8169_probe ( struct pci_device *pdev, const struct pci_device_id *ent ) /* Get MAC address */ for ( i = 0; i < MAC_ADDR_LEN; i++ ) - netdev->ll_addr[i] = RTL_R8 ( MAC0 + i ); + netdev->hw_addr[i] = RTL_R8 ( MAC0 + i ); - DBG ( "%s\n", eth_ntoa ( netdev->ll_addr ) ); + DBG ( "%s\n", eth_ntoa ( netdev->hw_addr ) ); rtl8169_init_phy ( netdev, tp ); diff --git a/src/drivers/net/rtl8139.c b/src/drivers/net/rtl8139.c index a4ee9692..754ce60b 100644 --- a/src/drivers/net/rtl8139.c +++ b/src/drivers/net/rtl8139.c @@ -525,7 +525,7 @@ static int rtl_probe ( struct pci_device *pci, /* Reset the NIC, set up EEPROM access and read MAC address */ rtl_reset ( netdev ); rtl_init_eeprom ( netdev ); - nvs_read ( &rtl->eeprom.nvs, EE_MAC, netdev->ll_addr, ETH_ALEN ); + nvs_read ( &rtl->eeprom.nvs, EE_MAC, netdev->hw_addr, ETH_ALEN ); /* Mark as link up; we don't yet handle link state */ netdev_link_up ( netdev ); diff --git a/src/drivers/net/rtl818x/rtl818x.c b/src/drivers/net/rtl818x/rtl818x.c index 672ff9c2..167409d8 100644 --- a/src/drivers/net/rtl818x/rtl818x.c +++ b/src/drivers/net/rtl818x/rtl818x.c @@ -813,7 +813,7 @@ static int rtl818x_probe(struct pci_device *pdev, free(hwinfo); DBG("rtl818x: Realtek RTL818%s (RF chip %s) with address %s\n", - chip_name, priv->rf->name, netdev_hwaddr(dev->netdev)); + chip_name, priv->rf->name, netdev_addr(dev->netdev)); return 0; diff --git a/src/drivers/net/sky2.c b/src/drivers/net/sky2.c index 59b0fafb..00940afe 100644 --- a/src/drivers/net/sky2.c +++ b/src/drivers/net/sky2.c @@ -2210,14 +2210,14 @@ static struct net_device *sky2_init_netdev(struct sky2_hw *hw, sky2->port = port; /* read the mac address */ - memcpy(dev->ll_addr, (void *)(hw->regs + B2_MAC_1 + port * 8), ETH_ALEN); + memcpy(dev->hw_addr, (void *)(hw->regs + B2_MAC_1 + port * 8), ETH_ALEN); return dev; } static void sky2_show_addr(struct net_device *dev) { - DBG2(PFX "%s: addr %s\n", dev->name, netdev_hwaddr(dev)); + DBG2(PFX "%s: addr %s\n", dev->name, netdev_addr(dev)); } #if DBGLVL_MAX diff --git a/src/include/gpxe/netdevice.h b/src/include/gpxe/netdevice.h index 0f191dd6..5ac2f629 100644 --- a/src/include/gpxe/netdevice.h +++ b/src/include/gpxe/netdevice.h @@ -254,9 +254,16 @@ struct net_device { /** Link-layer protocol */ struct ll_protocol *ll_protocol; + /** Hardware address + * + * This is an address which is an intrinsic property of the + * hardware, e.g. an address held in EEPROM. + */ + uint8_t hw_addr[MAX_LL_ADDR_LEN]; /** Link-layer address * - * For Ethernet, this is the MAC address. + * This is the current link-layer address assigned to the + * device. It can be changed at runtime. */ uint8_t ll_addr[MAX_LL_ADDR_LEN]; /** Link-layer broadcast address */ @@ -337,12 +344,12 @@ static inline void netdev_nullify ( struct net_device *netdev ) { } /** - * Get printable network device hardware address + * Get printable network device link-layer address * * @v netdev Network device - * @ret name Hardware address + * @ret name Link-layer address */ -static inline const char * netdev_hwaddr ( struct net_device *netdev ) { +static inline const char * netdev_addr ( struct net_device *netdev ) { return netdev->ll_protocol->ntoa ( netdev->ll_addr ); } diff --git a/src/interface/efi/efi_snp.c b/src/interface/efi/efi_snp.c index f96984fa..00830343 100644 --- a/src/interface/efi/efi_snp.c +++ b/src/interface/efi/efi_snp.c @@ -130,7 +130,7 @@ 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->ll_addr, ll_addr_len ); + memcpy ( &mode->PermanentAddress, netdev->hw_addr, ll_addr_len ); mode->IfType = ntohs ( netdev->ll_protocol->ll_proto ); mode->MacAddressChangeable = TRUE; mode->MediaPresentSupported = TRUE; diff --git a/src/net/80211/net80211.c b/src/net/80211/net80211.c index c46870c4..f3612853 100644 --- a/src/net/80211/net80211.c +++ b/src/net/80211/net80211.c @@ -792,7 +792,7 @@ int net80211_register ( struct net80211_device *dev, return -ENOMEM; memcpy ( dev->hw, hw, sizeof ( *hw ) ); - memcpy ( dev->netdev->ll_addr, hw->hwaddr, ETH_ALEN ); + memcpy ( dev->netdev->hw_addr, hw->hwaddr, ETH_ALEN ); /* Set some sensible channel defaults for driver's open() function */ memcpy ( dev->channels, dev->hw->channels, diff --git a/src/net/netdevice.c b/src/net/netdevice.c index f019eeb2..f43ca8a4 100644 --- a/src/net/netdevice.c +++ b/src/net/netdevice.c @@ -357,6 +357,10 @@ int register_netdev ( struct net_device *netdev ) { snprintf ( netdev->name, sizeof ( netdev->name ), "net%d", ifindex++ ); + /* Set initial link-layer address */ + memcpy ( netdev->ll_addr, netdev->hw_addr, + netdev->ll_protocol->ll_addr_len ); + /* Register per-netdev configuration settings */ if ( ( rc = register_settings ( netdev_settings ( netdev ), NULL ) ) != 0 ) { @@ -370,7 +374,7 @@ int register_netdev ( struct net_device *netdev ) { list_add_tail ( &netdev->list, &net_devices ); DBGC ( netdev, "NETDEV %p registered as %s (phys %s hwaddr %s)\n", netdev, netdev->name, netdev->dev->name, - netdev_hwaddr ( netdev ) ); + netdev_addr ( netdev ) ); return 0; } diff --git a/src/usr/dhcpmgmt.c b/src/usr/dhcpmgmt.c index c1cc36ef..d98aa9f4 100644 --- a/src/usr/dhcpmgmt.c +++ b/src/usr/dhcpmgmt.c @@ -48,7 +48,7 @@ int dhcp ( struct net_device *netdev ) { return rc; /* Perform DHCP */ - printf ( "DHCP (%s %s)", netdev->name, netdev_hwaddr ( netdev ) ); + printf ( "DHCP (%s %s)", netdev->name, netdev_addr ( netdev ) ); if ( ( rc = start_dhcp ( &monojob, netdev ) ) == 0 ) rc = monojob_wait ( "" ); diff --git a/src/usr/ifmgmt.c b/src/usr/ifmgmt.c index 97cde4a0..d4cc5a5b 100644 --- a/src/usr/ifmgmt.c +++ b/src/usr/ifmgmt.c @@ -89,7 +89,7 @@ static void ifstat_errors ( struct net_device_stats *stats, void ifstat ( struct net_device *netdev ) { printf ( "%s: %s on %s (%s)\n" " [Link:%s, TX:%d TXE:%d RX:%d RXE:%d]\n", - netdev->name, netdev_hwaddr ( netdev ), netdev->dev->name, + netdev->name, netdev_addr ( netdev ), netdev->dev->name, ( ( netdev->state & NETDEV_OPEN ) ? "open" : "closed" ), ( netdev_link_ok ( netdev ) ? "up" : "down" ), netdev->tx_stats.good, netdev->tx_stats.bad, -- cgit v1.2.3-55-g7522