]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[hermon] Use Ethernet MAC as eIPoIB local EMAC
authorChristian Iversen <ci@iversenit.dk>
Tue, 26 Jan 2021 21:56:42 +0000 (22:56 +0100)
committerMichael Brown <mcb30@ipxe.org>
Fri, 29 Jan 2021 00:13:46 +0000 (00:13 +0000)
The eIPoIB local Ethernet MAC is currently constructed from the port
GUID.  Given a base GUID/MAC value of N, Mellanox seems to populate:

  Node GUID:   N + 0
  Port 1 GUID: N + 1
  Port 2 GUID: N + 2

and

  Port 1 MAC:  N + 0
  Port 2 MAC:  N + 1

This causes a duplicate local MAC address when port 1 is configured as
Infiniband and port 2 as Ethernet, since both will derive their MAC
address as (N + 1).

Fix by using the port's Ethernet MAC as the eIPoIB local EMAC.  This
is a behavioural change that could potentially break configurations
that rely on the local EMAC value, such as a DHCP server relying on
the chaddr field for DHCP reservations.

Signed-off-by: Christian Iversen <ci@iversenit.dk>
Modified-by: Michael Brown <mcb30@ipxe.org>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/drivers/infiniband/hermon.c
src/drivers/infiniband/hermon.h

index e818b4d29a0176dd2f22406fe72c03af58279781..d766ed585dedc5e171c52804ac58eb0b877bdc67 100644 (file)
@@ -3179,6 +3179,9 @@ static int hermon_register_ibdev ( struct hermon *hermon,
        struct ib_device *ibdev = port->ibdev;
        int rc;
 
+       /* Use Ethernet MAC as eIPoIB local EMAC */
+       memcpy ( ibdev->lemac, port->eth_mac.raw, ETH_ALEN );
+
        /* Initialise parameters using SMC */
        ib_smc_init ( ibdev, hermon_mad );
 
@@ -3495,24 +3498,10 @@ static int hermon_register_netdev ( struct hermon *hermon,
                                    struct hermon_port *port ) {
        struct net_device *netdev = port->netdev;
        struct ib_device *ibdev = port->ibdev;
-       struct hermonprm_query_port_cap query_port;
-       union {
-               uint8_t bytes[8];
-               uint32_t dwords[2];
-       } mac;
        int rc;
 
-       /* Retrieve MAC address */
-       if ( ( rc = hermon_cmd_query_port ( hermon, ibdev->port,
-                                           &query_port ) ) != 0 ) {
-               DBGC ( hermon, "Hermon %p port %d could not query port: %s\n",
-                      hermon, ibdev->port, strerror ( rc ) );
-               goto err_query_port;
-       }
-       mac.dwords[0] = htonl ( MLX_GET ( &query_port, mac_47_32 ) );
-       mac.dwords[1] = htonl ( MLX_GET ( &query_port, mac_31_0 ) );
-       memcpy ( netdev->hw_addr,
-                &mac.bytes[ sizeof ( mac.bytes ) - ETH_ALEN ], ETH_ALEN );
+       /* Set MAC address */
+       memcpy ( netdev->hw_addr, port->eth_mac.raw, ETH_ALEN );
 
        /* Register network device */
        if ( ( rc = register_netdev ( netdev ) ) != 0 ) {
@@ -3536,7 +3525,6 @@ static int hermon_register_netdev ( struct hermon *hermon,
  err_register_nvo:
        unregister_netdev ( netdev );
  err_register_netdev:
- err_query_port:
        return rc;
 }
 
@@ -3674,6 +3662,10 @@ static int hermon_set_port_type ( struct hermon *hermon,
               ( ( ib_supported && eth_supported ) ? " and" : "" ),
               ( eth_supported ? " Ethernet" : "" ) );
 
+       /* Record Ethernet MAC address */
+       port->eth_mac.part.h = htons ( MLX_GET ( &query_port, mac_47_32 ) );
+       port->eth_mac.part.l = htonl ( MLX_GET ( &query_port, mac_31_0 ) );
+
        /* Sense network, if applicable */
        if ( ib_supported && eth_supported ) {
 
index 8ac35620ccaebec7eed4f37d147ea72178950ff2..381e2e462f090f69caa93abda8d8345a8445ae61 100644 (file)
@@ -822,6 +822,15 @@ struct hermon_port_type {
                                    struct hermon_port *port );
 };
 
+/** A Hermon port Ethernet MAC address */
+union hermon_port_mac {
+       struct {
+               uint16_t h;
+               uint32_t l;
+       } __attribute__ (( packed )) part;
+       uint8_t raw[ETH_ALEN];
+};
+
 /** A Hermon port */
 struct hermon_port {
        /** Infiniband device */
@@ -832,6 +841,8 @@ struct hermon_port {
        struct ib_completion_queue *eth_cq;
        /** Ethernet queue pair */
        struct ib_queue_pair *eth_qp;
+       /** Ethernet MAC */
+       union hermon_port_mac eth_mac;
        /** Port type */
        struct hermon_port_type *type;
        /** Non-volatile option storage */