diff --git a/sysinv/sysinv/sysinv/sysinv/common/device.py b/sysinv/sysinv/sysinv/sysinv/common/device.py index 74cd1684e4..499d55b2ec 100644 --- a/sysinv/sysinv/sysinv/sysinv/common/device.py +++ b/sysinv/sysinv/sysinv/sysinv/common/device.py @@ -32,6 +32,7 @@ PCI_DEVICE_VENDOR_INTEL = "8086" # Device Ids PCI_DEVICE_ID_FPGA_INTEL_5GNR_FEC_PF = "0d8f" PCI_DEVICE_ID_FPGA_INTEL_5GNR_FEC_VF = "0d90" +PCI_DEVICE_ID_FPGA_INTEL_I40_PF = "0d58" PCI_DEVICE_ID_ACC100_INTEL_5GNR_FEC_PF = "0d5c" PCI_DEVICE_ID_ACC100_INTEL_5GNR_FEC_VF = "0d5d" diff --git a/sysinv/sysinv/sysinv/sysinv/common/interface.py b/sysinv/sysinv/sysinv/sysinv/common/interface.py index e2c10fc5e7..1e05ce4e71 100644 --- a/sysinv/sysinv/sysinv/sysinv/common/interface.py +++ b/sysinv/sysinv/sysinv/sysinv/common/interface.py @@ -127,6 +127,22 @@ def get_lower_interface(context, iface): return context['interfaces'][lower_ifname] +def get_pci_device_id(port): + """ + Determine the PCI device id of given port. + """ + # The device id can be found by inspecting the '[xxxx]' at the + # end of the port's pdevice field + if not port or not port.get('pdevice', None): + return None + device_id = re.search(r'\[([0-9a-fA-F]{1,4})\]$', port['pdevice']) + if device_id: + device_id = device_id.group(1) + return str(device_id) + + return None + + def get_sriov_interface_port(context, iface): """ Determine the underlying port of the SR-IOV interface. @@ -143,15 +159,10 @@ def get_sriov_interface_device_id(context, iface): """ Determine the underlying PCI device id of the SR-IOV interface. """ - # The device id can be found by inspecting the '[xxxx]' at the - # end of the port's pdevice field - device_id = None port = get_sriov_interface_port(context, iface) - if port: - device_id = re.search(r'\[([0-9a-fA-F]{1,4})\]$', port['pdevice']) - if device_id: - device_id = device_id.group(1) - return device_id + if not port: + return None + return get_pci_device_id(port) def get_sriov_interface_vf_addrs(context, iface, vf_addr_list): diff --git a/sysinv/sysinv/sysinv/sysinv/puppet/interface.py b/sysinv/sysinv/sysinv/sysinv/puppet/interface.py index 4dd4019ec7..4b9778c825 100644 --- a/sysinv/sysinv/sysinv/sysinv/puppet/interface.py +++ b/sysinv/sysinv/sysinv/sysinv/puppet/interface.py @@ -14,6 +14,7 @@ from netaddr import IPNetwork from oslo_log import log from sysinv._i18n import _ from sysinv.common import constants +from sysinv.common import device as dconstants from sysinv.common import exception from sysinv.common import interface from sysinv.common import utils @@ -53,6 +54,7 @@ DHCP_METHOD = 'dhcp' NETWORK_CONFIG_RESOURCE = 'platform::interfaces::network_config' SRIOV_CONFIG_RESOURCE = 'platform::interfaces::sriov::sriov_config' +FPGA_CONFIG_RESOURCE = 'platform::interfaces::fpga::fpga_config' ADDRESS_CONFIG_RESOURCE = 'platform::network::addresses::address_config' ROUTE_CONFIG_RESOURCE = 'platform::network::routes::route_config' @@ -89,6 +91,7 @@ class InterfacePuppet(base.BasePuppet): ROUTE_CONFIG_RESOURCE: {}, ADDRESS_CONFIG_RESOURCE: {}, SRIOV_CONFIG_RESOURCE: {}, + FPGA_CONFIG_RESOURCE: {}, DATA_IFACE_LIST_RESOURCE: [], } @@ -457,6 +460,28 @@ def is_a_mellanox_cx3_device(context, iface): return False +def is_an_n3000_i40_device(context, iface): + """ + Determine if the underlying device is onboard an N3000 FPGA. + """ + if iface['iftype'] != constants.INTERFACE_TYPE_ETHERNET: + # We only care about configuring specific settings for related ethernet + # devices. + return False + + port = get_interface_port(context, iface) + if not port: + return False + + device_id = interface.get_pci_device_id(port) + if not device_id: + return False + + if device_id == dconstants.PCI_DEVICE_ID_FPGA_INTEL_I40_PF: + return True + return False + + def get_master_interface(context, iface): """ Get the interface name of the given interface's master (if any). The @@ -1116,6 +1141,34 @@ def get_sriov_config(context, iface): return config +def get_n3000_config(context, iface): + config = {} + if is_an_n3000_i40_device(context, iface): + port = get_interface_port(context, iface) + if not port: + return {} + + device_id = interface.get_pci_device_id(port) + if not device_id: + return {} + + config = { + 'ifname': port['name'], + 'device_id': device_id, + 'used_by': iface['used_by'] or [] + } + return config + + +def get_fpga_config(context, iface): + """ + Returns an FPGA interface config dictionary. + """ + config = {} + config.update(get_n3000_config(context, iface)) + return config + + def get_common_network_config(context, iface, config, network_id=None): """ Augments a basic config dictionary with the attributes specific to an upper @@ -1253,6 +1306,12 @@ def generate_network_config(context, config, iface): sriov_config['ifname']: format_sriov_config(sriov_config) }) + fpga_config = get_fpga_config(context, iface) + if fpga_config: + config[FPGA_CONFIG_RESOURCE].update({ + fpga_config['ifname']: format_fpga_config(fpga_config) + }) + def find_network_by_pool_uuid(context, pool_uuid): for networktype, network in six.iteritems(context['networks']): @@ -1489,3 +1548,13 @@ def format_sriov_config(config): sriov_config = copy.copy(config) del sriov_config['ifname'] return sriov_config + + +def format_fpga_config(config): + """ + Converts a fpga_config resource dictionary to the equivalent puppet + resource definition parameters. + """ + fpga_config = copy.copy(config) + del fpga_config['ifname'] + return fpga_config