def test_resolve_dpdk_bridges(self):
     self.test_config.set('data-port', DPDK_DATA_PORTS)
     _pci_devices = Mock()
     _pci_devices.get_device_from_mac.side_effect = PCI_DEVICE_MAP.get
     self.PCINetDevices.return_value = _pci_devices
     self.assertEqual(context.resolve_dpdk_bridges(),
                      {'0000:00:1c.0': 'br-phynet1',
                       '0000:00:1d.0': 'br-phynet3'})
 def test_resolve_dpdk_bridges(self):
     self.test_config.set('data-port', DPDK_DATA_PORTS)
     _pci_devices = Mock()
     _pci_devices.get_device_from_mac.side_effect = PCI_DEVICE_MAP.get
     self.PCINetDevices.return_value = _pci_devices
     self.assertEqual(context.resolve_dpdk_bridges(),
                      {'0000:00:1c.0': 'br-phynet1',
                       '0000:00:1d.0': 'br-phynet3'})
def configure_ovs():
    status_set('maintenance', 'Configuring ovs')
    if not service_running('openvswitch-switch'):
        full_restart()
    datapath_type = determine_datapath_type()
    add_bridge(INT_BRIDGE, datapath_type)
    add_bridge(EXT_BRIDGE, datapath_type)
    ext_port_ctx = None
    if use_dvr():
        ext_port_ctx = ExternalPortContext()()
    if ext_port_ctx and ext_port_ctx['ext_port']:
        add_bridge_port(EXT_BRIDGE, ext_port_ctx['ext_port'])

    modern_ovs = ovs_has_late_dpdk_init()

    bridgemaps = None
    if not use_dpdk():
        portmaps = DataPortContext()()
        bridgemaps = parse_bridge_mappings(config('bridge-mappings'))
        for br in bridgemaps.values():
            add_bridge(br, datapath_type)
            if not portmaps:
                continue

            for port, _br in portmaps.items():
                if _br == br:
                    if not is_linuxbridge_interface(port):
                        add_bridge_port(br, port, promisc=True)
                    else:
                        add_ovsbridge_linuxbridge(br, port)
    else:
        # NOTE: when in dpdk mode, add based on pci bus order
        #       with type 'dpdk'
        bridgemaps = neutron_ovs_context.resolve_dpdk_bridges()
        device_index = 0
        for pci_address, br in bridgemaps.items():
            add_bridge(br, datapath_type)
            if modern_ovs:
                portname = 'dpdk-{}'.format(
                    hashlib.sha1(pci_address.encode('UTF-8')).hexdigest()[:7]
                )
            else:
                portname = 'dpdk{}'.format(device_index)

            dpdk_add_bridge_port(br, portname,
                                 pci_address)
            device_index += 1

        if modern_ovs:
            bondmaps = neutron_ovs_context.resolve_dpdk_bonds()
            bridge_bond_map = DPDKBridgeBondMap()
            portmap = parse_data_port_mappings(config('data-port'))
            for pci_address, bond in bondmaps.items():
                if bond in portmap:
                    add_bridge(portmap[bond], datapath_type)
                    portname = 'dpdk-{}'.format(
                        hashlib.sha1(pci_address.encode('UTF-8'))
                        .hexdigest()[:7]
                    )
                    bridge_bond_map.add_port(portmap[bond], bond,
                                             portname, pci_address)

            bond_configs = DPDKBondsConfig()
            for br, bonds in bridge_bond_map.items():
                for bond, port_map in bonds.items():
                    dpdk_add_bridge_bond(br, bond, port_map)
                    dpdk_set_bond_config(
                        bond,
                        bond_configs.get_bond_config(bond)
                    )

    target = config('ipfix-target')
    bridges = [INT_BRIDGE, EXT_BRIDGE]
    if bridgemaps:
        bridges.extend(bridgemaps.values())

    if target:
        for bridge in bridges:
            disable_ipfix(bridge)
            enable_ipfix(bridge, target)
    else:
        # NOTE: removing ipfix setting from a bridge is idempotent and
        #       will pass regardless of the existence of the setting
        for bridge in bridges:
            disable_ipfix(bridge)

    # Ensure this runs so that mtu is applied to data-port interfaces if
    # provided.
    # NOTE(ajkavanagh) for pause/resume we don't gate this as it's not a
    # running service, but rather running a few commands.
    service_restart('os-charm-phy-nic-mtu')
def configure_ovs():
    status_set('maintenance', 'Configuring ovs')
    if not service_running('openvswitch-switch'):
        full_restart()
    datapath_type = determine_datapath_type()
    add_bridge(INT_BRIDGE, datapath_type)
    add_bridge(EXT_BRIDGE, datapath_type)
    ext_port_ctx = None
    if use_dvr():
        ext_port_ctx = ExternalPortContext()()
    if ext_port_ctx and ext_port_ctx['ext_port']:
        add_bridge_port(EXT_BRIDGE, ext_port_ctx['ext_port'])

    modern_ovs = ovs_has_late_dpdk_init()

    bridgemaps = None
    if not use_dpdk():
        # NOTE(jamespage):
        # Its possible to support both hardware offloaded 'direct' ports
        # and default 'openvswitch' ports on the same hypervisor, so
        # configure bridge mappings in addition to any hardware offload
        # enablement.
        portmaps = DataPortContext()()
        bridgemaps = parse_bridge_mappings(config('bridge-mappings'))
        for br in bridgemaps.values():
            add_bridge(br, datapath_type)
            if not portmaps:
                continue

            for port, _br in portmaps.items():
                if _br == br:
                    if not is_linuxbridge_interface(port):
                        add_bridge_port(br, port, promisc=True)
                    else:
                        add_ovsbridge_linuxbridge(br, port)

    # NOTE(jamespage):
    # hw-offload and dpdk are mutually exclusive so log and error
    # and skip any subsequent DPDK configuration
    if use_dpdk() and use_hw_offload():
        log(
            'DPDK and Hardware offload are mutually exclusive, '
            'please disable enable-dpdk or enable-hardware-offload',
            level=ERROR)
    elif use_dpdk():
        log('Configuring bridges with DPDK', level=DEBUG)
        global_mtu = (
            neutron_ovs_context.NeutronAPIContext()()['global_physnet_mtu'])
        # NOTE: when in dpdk mode, add based on pci bus order
        #       with type 'dpdk'
        bridgemaps = neutron_ovs_context.resolve_dpdk_bridges()
        log('bridgemaps: {}'.format(bridgemaps), level=DEBUG)
        device_index = 0
        for pci_address, br in bridgemaps.items():
            log('Adding DPDK bridge: {}:{}'.format(br, datapath_type),
                level=DEBUG)
            add_bridge(br, datapath_type)
            if modern_ovs:
                portname = 'dpdk-{}'.format(
                    hashlib.sha1(pci_address.encode('UTF-8')).hexdigest()[:7])
            else:
                portname = 'dpdk{}'.format(device_index)

            log('Adding DPDK port: {}:{}:{}'.format(br, portname, pci_address),
                level=DEBUG)
            dpdk_add_bridge_port(br, portname, pci_address)
            # TODO(sahid): We should also take into account the
            # "physical-network-mtus" in case different MTUs are
            # configured based on physical networks.
            dpdk_set_mtu_request(portname, global_mtu)
            device_index += 1

        if modern_ovs:
            log('Configuring bridges with modern_ovs/DPDK', level=DEBUG)
            bondmaps = neutron_ovs_context.resolve_dpdk_bonds()
            log('bondmaps: {}'.format(bondmaps), level=DEBUG)
            bridge_bond_map = DPDKBridgeBondMap()
            portmap = parse_data_port_mappings(config('data-port'))
            log('portmap: {}'.format(portmap), level=DEBUG)
            for pci_address, bond in bondmaps.items():
                if bond in portmap:
                    log('Adding DPDK bridge: {}:{}'.format(
                        portmap[bond], datapath_type),
                        level=DEBUG)
                    add_bridge(portmap[bond], datapath_type)
                    portname = 'dpdk-{}'.format(
                        hashlib.sha1(
                            pci_address.encode('UTF-8')).hexdigest()[:7])
                    bridge_bond_map.add_port(portmap[bond], bond, portname,
                                             pci_address)

            log('bridge_bond_map: {}'.format(bridge_bond_map), level=DEBUG)
            bond_configs = DPDKBondsConfig()
            for br, bonds in bridge_bond_map.items():
                for bond, port_map in bonds.items():
                    log('Adding DPDK bond: {}:{}:{}'.format(
                        br, bond, port_map),
                        level=DEBUG)
                    dpdk_add_bridge_bond(br, bond, port_map)
                    dpdk_set_interfaces_mtu(global_mtu, port_map.keys())
                    log('Configuring DPDK bond: {}:{}'.format(
                        bond, bond_configs.get_bond_config(bond)),
                        level=DEBUG)
                    dpdk_set_bond_config(bond,
                                         bond_configs.get_bond_config(bond))

    target = config('ipfix-target')
    bridges = [INT_BRIDGE, EXT_BRIDGE]
    if bridgemaps:
        bridges.extend(bridgemaps.values())

    if target:
        for bridge in bridges:
            disable_ipfix(bridge)
            enable_ipfix(bridge, target)
    else:
        # NOTE: removing ipfix setting from a bridge is idempotent and
        #       will pass regardless of the existence of the setting
        for bridge in bridges:
            disable_ipfix(bridge)

    # Ensure this runs so that mtu is applied to data-port interfaces if
    # provided.
    # NOTE(ajkavanagh) for pause/resume we don't gate this as it's not a
    # running service, but rather running a few commands.
    if not init_is_systemd():
        service_restart('os-charm-phy-nic-mtu')
def configure_ovs():
    status_set('maintenance', 'Configuring ovs')
    if not service_running('openvswitch-switch'):
        full_restart()
    datapath_type = determine_datapath_type()
    add_bridge(INT_BRIDGE, datapath_type)
    add_bridge(EXT_BRIDGE, datapath_type)
    ext_port_ctx = None
    if use_dvr():
        ext_port_ctx = ExternalPortContext()()
    if ext_port_ctx and ext_port_ctx['ext_port']:
        add_bridge_port(EXT_BRIDGE, ext_port_ctx['ext_port'])

    bridgemaps = None
    if not use_dpdk():
        portmaps = DataPortContext()()
        bridgemaps = parse_bridge_mappings(config('bridge-mappings'))
        for br in bridgemaps.values():
            add_bridge(br, datapath_type)
            if not portmaps:
                continue

            for port, _br in portmaps.items():
                if _br == br:
                    if not is_linuxbridge_interface(port):
                        add_bridge_port(br, port, promisc=True)
                    else:
                        add_ovsbridge_linuxbridge(br, port)
    else:
        # NOTE: when in dpdk mode, add based on pci bus order
        #       with type 'dpdk'
        bridgemaps = neutron_ovs_context.resolve_dpdk_bridges()
        bondmaps = neutron_ovs_context.resolve_dpdk_bonds()
        device_index = 0
        bridge_bond_map = DPDKBridgeBondMap()
        for pci_address, br in bridgemaps.items():
            add_bridge(br, datapath_type)
            portname = 'dpdk{}'.format(device_index)
            if pci_address in bondmaps:
                bond = bondmaps[pci_address]
                bridge_bond_map.add_port(br, bond, portname, pci_address)
            else:
                dpdk_add_bridge_port(br, portname, pci_address)
            device_index += 1

        bond_configs = DPDKBondsConfig()
        for br, bonds in bridge_bond_map.items():
            for bond, t in bonds.items():
                dpdk_add_bridge_bond(br, bond, *t)
                dpdk_set_bond_config(bond, bond_configs.get_bond_config(bond))

    target = config('ipfix-target')
    bridges = [INT_BRIDGE, EXT_BRIDGE]
    if bridgemaps:
        bridges.extend(bridgemaps.values())

    if target:
        for bridge in bridges:
            disable_ipfix(bridge)
            enable_ipfix(bridge, target)
    else:
        # NOTE: removing ipfix setting from a bridge is idempotent and
        #       will pass regardless of the existence of the setting
        for bridge in bridges:
            disable_ipfix(bridge)

    # Ensure this runs so that mtu is applied to data-port interfaces if
    # provided.
    # NOTE(ajkavanagh) for pause/resume we don't gate this as it's not a
    # running service, but rather running a few commands.
    service_restart('os-charm-phy-nic-mtu')