[netdevice] Separate out the concept of hardware and link-layer addresses
authorMichael Brown <mcb30@etherboot.org>
Tue, 11 Aug 2009 19:19:53 +0000 (20:19 +0100)
committerMichael Brown <mcb30@etherboot.org>
Tue, 11 Aug 2009 23:19:14 +0000 (00:19 +0100)
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().

22 files changed:
src/arch/i386/drivers/net/undinet.c
src/arch/i386/interface/pxe/pxe_undi.c
src/drivers/net/3c90x.c
src/drivers/net/b44.c
src/drivers/net/e1000/e1000.c
src/drivers/net/etherfabric.c
src/drivers/net/ipoib.c
src/drivers/net/legacy.c
src/drivers/net/mtnic.c
src/drivers/net/natsemi.c
src/drivers/net/phantom/phantom.c
src/drivers/net/pnic.c
src/drivers/net/r8169.c
src/drivers/net/rtl8139.c
src/drivers/net/rtl818x/rtl818x.c
src/drivers/net/sky2.c
src/include/gpxe/netdevice.h
src/interface/efi/efi_snp.c
src/net/80211/net80211.c
src/net/netdevice.c
src/usr/dhcpmgmt.c
src/usr/ifmgmt.c

index 6c28b24..0c7f669 100644 (file)
@@ -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 ) );
index ddaae84..48c274b 100644 (file)
@@ -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; */
index 83b7083..aeed633 100644 (file)
@@ -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;
index 38c4746..c48b314 100644 (file)
@@ -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;
index faca1e0..af8e093 100644 (file)
@@ -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 */
        {
index ca4af50..c4296b9 100644 (file)
@@ -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 );
index 3f14924..c2a6d34 100644 (file)
@@ -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 )
index c4bfc96..79b3580 100644 (file)
@@ -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 ) ) {
index 7fe4b96..d7ee8d2 100644 (file)
@@ -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;
                }
 
index 13adf2a..8ca6271 100644 (file)
@@ -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;
        }
 
index 85949c2..4c3f22f 100644 (file)
@@ -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 )
index 4b728f4..cbc6790 100644 (file)
@@ -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 );
index 08c44a2..b468782 100644 (file)
@@ -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 );
 
index a4ee969..754ce60 100644 (file)
@@ -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 );
index 672ff9c..167409d 100644 (file)
@@ -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;
 
index 59b0faf..00940af 100644 (file)
@@ -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
index 0f191dd..5ac2f62 100644 (file)
@@ -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 );
 }
 
index f96984f..0083034 100644 (file)
@@ -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;
index c46870c..f361285 100644 (file)
@@ -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,
index f019eeb..f43ca8a 100644 (file)
@@ -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;
 }
index c1cc36e..d98aa9f 100644 (file)
@@ -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 ( "" );
 
index 97cde4a..d4cc5a5 100644 (file)
@@ -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,