diff options
author | Christian Iversen <ci@iversenit.dk> | 2021-01-26 22:56:42 +0100 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2021-01-29 00:13:46 +0000 |
commit | 699b9f1d1b0338272dc4871ec3348ff3281784a3 (patch) | |
tree | 003db7c9d74b216755a5d42945c47e11ccf255fe | |
parent | 6cb12ee2b02dac4455bc60aebdcd326436dff743 (diff) | |
download | ipxe-699b9f1d1b0338272dc4871ec3348ff3281784a3.zip ipxe-699b9f1d1b0338272dc4871ec3348ff3281784a3.tar.gz ipxe-699b9f1d1b0338272dc4871ec3348ff3281784a3.tar.bz2 |
[hermon] Use Ethernet MAC as eIPoIB local EMAC
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>
-rw-r--r-- | src/drivers/infiniband/hermon.c | 26 | ||||
-rw-r--r-- | src/drivers/infiniband/hermon.h | 11 |
2 files changed, 20 insertions, 17 deletions
diff --git a/src/drivers/infiniband/hermon.c b/src/drivers/infiniband/hermon.c index e818b4d..d766ed5 100644 --- a/src/drivers/infiniband/hermon.c +++ b/src/drivers/infiniband/hermon.c @@ -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 ) { diff --git a/src/drivers/infiniband/hermon.h b/src/drivers/infiniband/hermon.h index 8ac3562..381e2e4 100644 --- a/src/drivers/infiniband/hermon.h +++ b/src/drivers/infiniband/hermon.h @@ -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 */ |