From 14b66dbc92fbae3bd7fc8be4bba476dd1bbb5795 Mon Sep 17 00:00:00 2001 From: Timo Rothenpieler Date: Mon, 26 Oct 2020 14:09:13 +0100 Subject: dhcp4: fix DHCP on InfiniBand interfaces With these patches applied, networkd is successfully able to get an address from a DHCP server on an IPoIB interface. 1) Makes networkd pass the actual interface type to the dhcp client, instead of hardcoding it to Ethernet. 2) Fixes some issues in handling the larger (20 Byte) IB MAC addresses in the dhcp code. 3) Add a new field to networkds Link struct, which holds the interface broadcast address. 3.1) Modify the DHCP code to also expect the broadcast address as parameter. On an Ethernet-Interface the Broadcast address never changes and is always all 6 bytes set to 0xFF. On an IB one however it is not neccesarily always the same, thus fetching the actual address from the interface is neccesary. 4) Only the last 8 bytes of an IB MAC are stable, so when using an IB MAC to generate a client ID, only pass those 8 bytes. --- src/network/networkd-dhcp4.c | 25 +++++++++++++++++++------ src/network/networkd-dhcp6.c | 2 +- src/network/networkd-link.c | 4 ++++ src/network/networkd-link.h | 1 + 4 files changed, 25 insertions(+), 7 deletions(-) (limited to 'src/network') diff --git a/src/network/networkd-dhcp4.c b/src/network/networkd-dhcp4.c index 5255ec3e1c..319ef61593 100644 --- a/src/network/networkd-dhcp4.c +++ b/src/network/networkd-dhcp4.c @@ -1271,14 +1271,24 @@ static int dhcp4_set_client_identifier(Link *link) { return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set DUID: %m"); break; } - case DHCP_CLIENT_ID_MAC: + case DHCP_CLIENT_ID_MAC: { + const uint8_t *hw_addr = link->hw_addr.addr.bytes; + size_t hw_addr_len = link->hw_addr.length; + + if (link->iftype == ARPHRD_INFINIBAND && hw_addr_len == INFINIBAND_ALEN) { + /* set_client_id expects only last 8 bytes of an IB address */ + hw_addr += INFINIBAND_ALEN - 8; + hw_addr_len -= INFINIBAND_ALEN - 8; + } + r = sd_dhcp_client_set_client_id(link->dhcp_client, - ARPHRD_ETHER, - link->hw_addr.addr.bytes, - link->hw_addr.length); + link->iftype, + hw_addr, + hw_addr_len); if (r < 0) return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set client ID: %m"); break; + } default: assert_not_reached("Unknown client identifier type."); } @@ -1326,7 +1336,8 @@ int dhcp4_configure(Link *link) { r = sd_dhcp_client_set_mac(link->dhcp_client, link->hw_addr.addr.bytes, - link->hw_addr.length, ARPHRD_ETHER); + link->bcast_addr.length > 0 ? link->bcast_addr.addr.bytes : NULL, + link->hw_addr.length, link->iftype); if (r < 0) return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set MAC address: %m"); @@ -1484,7 +1495,9 @@ int dhcp4_update_mac(Link *link) { if (!link->dhcp_client) return 0; - r = sd_dhcp_client_set_mac(link->dhcp_client, link->hw_addr.addr.bytes, link->hw_addr.length, ARPHRD_ETHER); + r = sd_dhcp_client_set_mac(link->dhcp_client, link->hw_addr.addr.bytes, + link->bcast_addr.length > 0 ? link->bcast_addr.addr.bytes : NULL, + link->hw_addr.length, link->iftype); if (r < 0) return r; diff --git a/src/network/networkd-dhcp6.c b/src/network/networkd-dhcp6.c index afff1dfc15..e7dc10c2be 100644 --- a/src/network/networkd-dhcp6.c +++ b/src/network/networkd-dhcp6.c @@ -1357,7 +1357,7 @@ static int dhcp6_set_identifier(Link *link, sd_dhcp6_client *client) { assert(link->network); assert(client); - r = sd_dhcp6_client_set_mac(client, link->hw_addr.addr.bytes, link->hw_addr.length, ARPHRD_ETHER); + r = sd_dhcp6_client_set_mac(client, link->hw_addr.addr.bytes, link->hw_addr.length, link->iftype); if (r < 0) return r; diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 09622de868..1eca07771a 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -425,6 +425,10 @@ static int link_new(Manager *manager, sd_netlink_message *message, Link **ret) { if (r < 0) log_link_debug_errno(link, r, "Hardware address not found for new device, continuing without"); + r = netlink_message_read_hw_addr(message, IFLA_BROADCAST, &link->bcast_addr); + if (r < 0) + log_link_debug_errno(link, r, "Broadcast address not found for new device, continuing without"); + r = ethtool_get_permanent_macaddr(&manager->ethtool_fd, link->ifname, &link->permanent_mac); if (r < 0) log_link_debug_errno(link, r, "Permanent MAC address not found for new device, continuing without: %m"); diff --git a/src/network/networkd-link.h b/src/network/networkd-link.h index bdeee0fe85..159e7e705b 100644 --- a/src/network/networkd-link.h +++ b/src/network/networkd-link.h @@ -54,6 +54,7 @@ typedef struct Link { unsigned short iftype; char *state_file; hw_addr_data hw_addr; + hw_addr_data bcast_addr; struct ether_addr permanent_mac; struct in6_addr ipv6ll_address; uint32_t mtu; -- cgit v1.2.1