Merge "netutils: Use ethtool ioctl to get permanent mac address"
This commit is contained in:
3 changed files with 118 additions and 14 deletions
@@ -34,6 +34,13 @@ LLDP_ETHERTYPE = 0x88cc
IFF_PROMISC = 0x100
SIOCGIFFLAGS = 0x8913
SIOCSIFFLAGS = 0x8914
# SIOCETHTOOL from linux/sockios.h
SIOCETHTOOL = 0x8946
# ETHTOOL_GPERMADDR from linux/ethtool.h
ETHTOOL_GPERMADDR = 0x00000020
# MAX_ADDR_LEN from linux/netdevice.h
MAX_ADDR_LEN = 32
INFINIBAND_ADDR_LEN = 59
# LLDP definitions needed to extract vlan information
@@ -45,10 +52,25 @@ dot1_VLAN_NAME = "03"
VLAN_ID_LEN = len(LLDP_802dot1_OUI + dot1_VLAN_NAME)
class ethtoolPermAddr(ctypes.Structure):
"""Class for getting interface permanent MAC address"""
_fields_ = [("cmd", ctypes.c_uint32),
("size", ctypes.c_uint32),
("data", ctypes.c_uint8 * MAX_ADDR_LEN)]
class ifreq_data(ctypes.Union):
_fields_ = [("ifr_flags", ctypes.c_short),
(
"ifr_data_ethtool_perm_addr",
ctypes.POINTER(ethtoolPermAddr))]
class ifreq(ctypes.Structure):
"""Class for setting flags on a socket."""
"""Class for ioctl on socket."""
_anonymous_ = ("ifr_data",)
_fields_ = [("ifr_ifrn", ctypes.c_char * 16),
("ifr_flags", ctypes.c_short)]
("ifr_data", ifreq_data)]
class RawPromiscuousSockets(object):
@@ -236,6 +258,23 @@ def get_ipv6_addr(interface_id):
def get_mac_addr(interface_id):
"""Retrieve permanent mac address, if unable to fallback to default one"""
try:
data = ethtoolPermAddr(cmd=ETHTOOL_GPERMADDR, size=MAX_ADDR_LEN)
ifr = ifreq(ifr_ifrn=interface_id.encode())
ifr.ifr_data_ethtool_perm_addr = ctypes.pointer(data)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)
fcntl.ioctl(sock.fileno(), SIOCETHTOOL, ifr)
# if not full of zeros
if any(data.data[:data.size]):
# kernel updates size to actual address size during ioctl call
permaddr = [f'{b:02x}' for b in data.data[:data.size]]
return ':'.join(permaddr)
except OSError:
pass
LOG.warning("Failed to get permanent mac address for interface %s, "
"falling back to default mac address",
interface_id)
return get_default_ip_addr(socket.AF_PACKET, interface_id)
@@ -6279,6 +6279,7 @@ class TestCollectSystemLogs(base.IronicAgentTest):
FakeAddr = namedtuple('FakeAddr', ('family', 'address'))
@mock.patch.object(netutils, 'get_mac_addr', autospec=True)
@mock.patch.object(hardware.GenericHardwareManager, '_get_system_lshw_dict',
autospec=True, return_value={'id': 'host'})
@mock.patch.object(hardware, 'get_managers', autospec=True,
@@ -6303,7 +6304,8 @@ class TestListNetworkInterfaces(base.IronicAgentTest):
mocked_listdir,
mocked_net_if_addrs,
mockedget_managers,
mocked_lshw):
mocked_lshw,
mocked_get_mac_addr):
mocked_lshw.return_value = json.loads(hws.LSHW_JSON_OUTPUT_V2[0])
mocked_listdir.return_value = ['lo', 'eth0', 'foobar']
mocked_exists.side_effect = [False, False, True, True]
@@ -6327,6 +6329,10 @@ class TestListNetworkInterfaces(base.IronicAgentTest):
FakeAddr(socket.AF_INET6, 'fd00:1000::101')
]
}
mocked_get_mac_addr.side_effect = lambda iface: {
'lo': '00:00:00:00:00:00',
'eth0': '00:0c:29:8c:11:b1',
}.get(iface)
mocked_execute.return_value = ('em0\n', '')
mock_has_carrier.return_value = True
interfaces = self.hardware.list_network_interfaces()
@@ -6348,7 +6354,8 @@ class TestListNetworkInterfaces(base.IronicAgentTest):
mocked_listdir,
mocked_net_if_addrs,
mockedget_managers,
mocked_lshw):
mocked_lshw,
mocked_get_mac_addr):
mocked_listdir.return_value = ['lo', 'eth0']
mocked_exists.side_effect = [False, False, True]
mocked_open.return_value.__enter__ = lambda s: s
@@ -6367,6 +6374,10 @@ class TestListNetworkInterfaces(base.IronicAgentTest):
FakeAddr(socket.AF_PACKET, '00:0c:29:8c:11:b1')
]
}
mocked_get_mac_addr.side_effect = lambda iface: {
'lo': '00:00:00:00:00:00',
'eth0': '00:0c:29:8c:11:b1',
}.get(iface)
mocked_execute.return_value = ('em0\n', '')
mock_has_carrier.return_value = True
interfaces = self.hardware.list_network_interfaces()
@@ -6390,7 +6401,8 @@ class TestListNetworkInterfaces(base.IronicAgentTest):
mocked_listdir,
mocked_net_if_addrs,
mockedget_managers,
mocked_lshw):
mocked_lshw,
mocked_get_mac_addr):
CONF.set_override('collect_lldp', True)
mocked_listdir.return_value = ['lo', 'eth0']
mocked_exists.side_effect = [False, False, True]
@@ -6410,6 +6422,10 @@ class TestListNetworkInterfaces(base.IronicAgentTest):
FakeAddr(socket.AF_PACKET, '00:0c:29:8c:11:b1')
]
}
mocked_get_mac_addr.side_effect = lambda iface: {
'lo': '00:00:00:00:00:00',
'eth0': '00:0c:29:8c:11:b1',
}.get(iface)
mocked_lldp_info.return_value = {'eth0': [
(0, b''),
(1, b'\x04\x88Z\x92\xecTY'),
@@ -6444,7 +6460,8 @@ class TestListNetworkInterfaces(base.IronicAgentTest):
mocked_listdir,
mocked_net_if_addrs,
mockedget_managers,
mocked_lshw):
mocked_lshw,
mocked_get_mac_addr):
CONF.set_override('collect_lldp', True)
mocked_listdir.return_value = ['lo', 'eth0']
mocked_exists.side_effect = [False, False, True]
@@ -6464,6 +6481,10 @@ class TestListNetworkInterfaces(base.IronicAgentTest):
FakeAddr(socket.AF_PACKET, '00:0c:29:8c:11:b1')
]
}
mocked_get_mac_addr.side_effect = lambda iface: {
'lo': '00:00:00:00:00:00',
'eth0': '00:0c:29:8c:11:b1',
}.get(iface)
mocked_lldp_info.side_effect = Exception('Boom!')
mocked_execute.return_value = ('em0\n', '')
mock_has_carrier.return_value = True
@@ -6485,7 +6506,8 @@ class TestListNetworkInterfaces(base.IronicAgentTest):
mocked_listdir,
mocked_net_if_addrs,
mockedget_managers,
mocked_lshw):
mocked_lshw,
mocked_get_mac_addr):
mockedget_managers.return_value = [hardware.GenericHardwareManager()]
mocked_listdir.return_value = ['lo', 'eth0']
@@ -6506,6 +6528,10 @@ class TestListNetworkInterfaces(base.IronicAgentTest):
FakeAddr(socket.AF_PACKET, '00:0c:29:8c:11:b1')
]
}
mocked_get_mac_addr.side_effect = lambda iface: {
'lo': '00:00:00:00:00:00',
'eth0': '00:0c:29:8c:11:b1',
}.get(iface)
mocked_execute.return_value = ('em0\n', '')
mock_has_carrier.return_value = False
interfaces = self.hardware.list_network_interfaces()
@@ -6526,7 +6552,8 @@ class TestListNetworkInterfaces(base.IronicAgentTest):
mocked_listdir,
mocked_net_if_addrs,
mockedget_managers,
mocked_lshw):
mocked_lshw,
mocked_get_mac_addr):
mocked_listdir.return_value = ['lo', 'eth0']
mocked_exists.side_effect = [False, False, True]
mocked_open.return_value.__enter__ = lambda s: s
@@ -6546,6 +6573,10 @@ class TestListNetworkInterfaces(base.IronicAgentTest):
FakeAddr(socket.AF_PACKET, '00:0c:29:8c:11:b1')
]
}
mocked_get_mac_addr.side_effect = lambda iface: {
'lo': '00:00:00:00:00:00',
'eth0': '00:0c:29:8c:11:b1',
}.get(iface)
mocked_execute.return_value = ('em0\n', '')
mock_has_carrier.return_value = True
interfaces = self.hardware.list_network_interfaces()
@@ -6567,7 +6598,8 @@ class TestListNetworkInterfaces(base.IronicAgentTest):
mocked_listdir,
mocked_net_if_addrs,
mockedget_managers,
mocked_lshw):
mocked_lshw,
mocked_get_mac_addr):
mocked_listdir.return_value = ['lo', 'bond0']
mocked_exists.side_effect = [False, False, True]
mocked_open.return_value.__enter__ = lambda s: s
@@ -6586,6 +6618,10 @@ class TestListNetworkInterfaces(base.IronicAgentTest):
FakeAddr(socket.AF_PACKET, '00:0c:29:8c:11:b1')
]
}
mocked_get_mac_addr.side_effect = lambda iface: {
'lo': '00:00:00:00:00:00',
'bond0': '00:0c:29:8c:11:b1',
}.get(iface)
mocked_execute.return_value = ('\n', '')
mock_has_carrier.return_value = True
interfaces = self.hardware.list_network_interfaces()
@@ -6610,7 +6646,8 @@ class TestListNetworkInterfaces(base.IronicAgentTest):
mocked_listdir,
mocked_net_if_addrs,
mockedget_managers,
mocked_lshw):
mocked_lshw,
mocked_get_mac_addr):
mocked_listdir.return_value = ['lo', 'eth0']
mocked_exists.side_effect = [False, False, True]
mocked_open.return_value.__enter__ = lambda s: s
@@ -6629,6 +6666,10 @@ class TestListNetworkInterfaces(base.IronicAgentTest):
FakeAddr(socket.AF_PACKET, '00:0c:29:8c:11:b1')
]
}
mocked_get_mac_addr.side_effect = lambda iface: {
'lo': '00:00:00:00:00:00',
'eth0': '00:0c:29:8c:11:b1',
}.get(iface)
mocked_execute.return_value = ('em0\n', '')
mock_has_carrier.return_value = True
mock_get_pci.return_value = '.&checktime(0000,02,00,':').0'
@@ -6654,7 +6695,8 @@ class TestListNetworkInterfaces(base.IronicAgentTest):
mocked_listdir,
mocked_net_if_addrs,
mockedget_managers,
mocked_lshw):
mocked_lshw,
mocked_get_mac_addr):
CONF.set_override('enable_vlan_interfaces', 'eth0.100')
mocked_listdir.return_value = ['lo', 'eth0']
mocked_exists.side_effect = [False, False, True]
@@ -6679,6 +6721,11 @@ class TestListNetworkInterfaces(base.IronicAgentTest):
FakeAddr(socket.AF_PACKET, '00:0c:29:8c:11:b1')
]
}
mocked_get_mac_addr.side_effect = lambda iface: {
'lo': '00:00:00:00:00:00',
'eth0': '00:0c:29:8c:11:b1',
'eth0.100': '00:0c:29:8c:11:b1',
}.get(iface)
mocked_execute.return_value = ('em0\n', '')
mock_has_carrier.return_value = True
interfaces = self.hardware.list_network_interfaces()
@@ -6702,7 +6749,8 @@ class TestListNetworkInterfaces(base.IronicAgentTest):
mocked_listdir,
mocked_net_if_addrs,
mockedget_managers,
mocked_lshw):
mocked_lshw,
mocked_get_mac_addr):
CONF.set_override('collect_lldp', True)
CONF.set_override('enable_vlan_interfaces', 'eth0')
mocked_listdir.return_value = ['lo', 'eth0']
@@ -6734,6 +6782,12 @@ class TestListNetworkInterfaces(base.IronicAgentTest):
FakeAddr(socket.AF_PACKET, '00:0c:29:8c:11:c2')
]
}
mocked_get_mac_addr.side_effect = lambda iface: {
'lo': '00:00:00:00:00:00',
'eth0': '00:0c:29:8c:11:b1',
'eth0.100': '00:0c:29:8c:11:c1',
'eth0.101': '00:0c:29:8c:11:c2',
}.get(iface)
mocked_lldp_info.return_value = {'eth0': [
(0, b''),
(127, b'\x00\x80\xc2\x03\x00d\x08vlan-100'),
@@ -6767,7 +6821,8 @@ class TestListNetworkInterfaces(base.IronicAgentTest):
mocked_listdir,
mocked_net_if_addrs,
mockedget_managers,
mocked_lshw):
mocked_lshw,
mocked_get_mac_addr):
CONF.set_override('collect_lldp', True)
CONF.set_override('enable_vlan_interfaces', 'enp0s1')
mocked_listdir.return_value = ['lo', 'eth0']
@@ -6805,7 +6860,8 @@ class TestListNetworkInterfaces(base.IronicAgentTest):
mocked_listdir,
mocked_net_if_addrs,
mockedget_managers,
mocked_lshw):
mocked_lshw,
mocked_get_mac_addr):
CONF.set_override('collect_lldp', True)
CONF.set_override('enable_vlan_interfaces', 'all')
mocked_listdir.return_value = ['lo', 'eth0', 'eth1']
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.