Example #1
0
def configure_ovs():
    status_set('maintenance', 'Configuring ovs')
    if not service_running('openvswitch-switch'):
        full_restart()
    add_bridge(INT_BRIDGE)
    add_bridge(EXT_BRIDGE)
    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'])

    portmaps = DataPortContext()()
    bridgemaps = parse_bridge_mappings(config('bridge-mappings'))
    for provider, br in bridgemaps.iteritems():
        add_bridge(br)
        if not portmaps:
            continue

        for port, _br in portmaps.iteritems():
            if _br == br:
                add_bridge_port(br, port, promisc=True)

    # Ensure this runs so that mtu is applied to data-port interfaces if
    # provided.
    service_restart('os-charm-phy-nic-mtu')
Example #2
0
def configure_ovs():
    status_set('maintenance', 'Configuring ovs')
    if not service_running('openvswitch-switch'):
        full_restart()
    add_bridge(INT_BRIDGE)
    add_bridge(EXT_BRIDGE)
    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'])

    portmaps = DataPortContext()()
    bridgemaps = parse_bridge_mappings(config('bridge-mappings'))
    for provider, br in bridgemaps.iteritems():
        add_bridge(br)
        if not portmaps:
            continue

        for port, _br in portmaps.iteritems():
            if _br == br:
                add_bridge_port(br, port, promisc=True)

    # Ensure this runs so that mtu is applied to data-port interfaces if
    # provided.
    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 = 'system'
    add_bridge(INT_BRIDGE, datapath_type)
    #add_bridge(EXT_BRIDGE, datapath_type)
    add_bridge_port(INT_BRIDGE, config('aci-uplink-interface'), promisc=True)
Example #4
0
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'])

    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'
        dpdk_bridgemaps = neutron_ovs_context.resolve_dpdk_ports()
        device_index = 0
        for br in dpdk_bridgemaps.values():
            add_bridge(br, datapath_type)
            dpdk_add_bridge_port(br,
                                 'dpdk{}'.format(device_index),
                                 port_type='dpdk')
            device_index += 1

    target = config('ipfix-target')
    bridges = [INT_BRIDGE, EXT_BRIDGE]
    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')
Example #5
0
 def test_add_bridge_port_promisc(self, check_call):
     ovs.add_bridge_port('test', 'eth1', promisc=True)
     check_call.assert_has_calls([
         call(["ovs-vsctl", "--", "--may-exist", "add-port",
               'test', 'eth1']),
         call(['ip', 'link', 'set', 'eth1', 'up']),
         call(['ip', 'link', 'set', 'eth1', 'promisc', 'on'])
     ])
     self.assertTrue(self.log.call_count == 1)
def configure_ovs():
    if config('plugin') == OVS:
        if not service_running('openvswitch-switch'):
            full_restart()
        add_bridge(INT_BRIDGE)
        add_bridge(EXT_BRIDGE)
        ext_port = config('ext-port')
        if ext_port:
            add_bridge_port(EXT_BRIDGE, ext_port)
Example #7
0
def configure_ovs():
    if config('plugin') in [OVS, OVS_ODL]:
        if not service_running('openvswitch-switch'):
            full_restart()
        add_bridge(INT_BRIDGE)
        add_bridge(EXT_BRIDGE)
        ext_port_ctx = ExternalPortContext()()
        if ext_port_ctx and ext_port_ctx['ext_port']:
            add_bridge_port(EXT_BRIDGE, ext_port_ctx['ext_port'])

        portmaps = DataPortContext()()
        bridgemaps = parse_bridge_mappings(config('bridge-mappings'))
        for br in bridgemaps.values():
            add_bridge(br)
            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)

        target = config('ipfix-target')
        bridges = [INT_BRIDGE, EXT_BRIDGE]
        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.
        service_restart('os-charm-phy-nic-mtu')
Example #8
0
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'])

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

            for port, _br in portmaps.iteritems():
                if _br == br:
                    add_bridge_port(br, port, promisc=True)
    else:
        # NOTE: when in dpdk mode, add based on pci bus order
        #       with type 'dpdk'
        dpdk_bridgemaps = neutron_ovs_context.resolve_dpdk_ports()
        device_index = 0
        for br in dpdk_bridgemaps.itervalues():
            add_bridge(br, datapath_type)
            dpdk_add_bridge_port(br,
                                 'dpdk{}'.format(device_index),
                                 port_type='dpdk')
            device_index += 1

    # 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():
    if config('plugin') in [OVS, OVS_ODL]:
        if not service_running('openvswitch-switch'):
            full_restart()
        add_bridge(INT_BRIDGE)
        add_bridge(EXT_BRIDGE)
        ext_port_ctx = ExternalPortContext()()
        if ext_port_ctx and ext_port_ctx['ext_port']:
            add_bridge_port(EXT_BRIDGE, ext_port_ctx['ext_port'])

        portmaps = DataPortContext()()
        # TODO: fudge in external network?
        bridgemaps = parse_bridge_mappings(config('bridge-mappings'))
        for provider, br in bridgemaps.iteritems():
            add_bridge(br)
            if not portmaps:
                continue

            for port, _br in portmaps.iteritems():
                if _br == br:
                    add_bridge_port(br, port, promisc=True)
def configure_ovs():
    if config('plugin') in [OVS, OVS_ODL]:
        if not service_running('openvswitch-switch'):
            full_restart()
        add_bridge(INT_BRIDGE)
        add_bridge(EXT_BRIDGE)
        ext_port_ctx = ExternalPortContext()()
        if ext_port_ctx and ext_port_ctx['ext_port']:
            add_bridge_port(EXT_BRIDGE, ext_port_ctx['ext_port'])

        portmaps = DataPortContext()()
        # TODO: fudge in external network?
        bridgemaps = parse_bridge_mappings(config('bridge-mappings'))
        for provider, br in bridgemaps.iteritems():
            add_bridge(br)
            if not portmaps:
                continue

            for port, _br in portmaps.iteritems():
                if _br == br:
                    add_bridge_port(br, port, promisc=True)
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'])

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

            for port, _br in portmaps.iteritems():
                if _br == br:
                    add_bridge_port(br, port, promisc=True)
    else:
        # NOTE: when in dpdk mode, add based on pci bus order
        #       with type 'dpdk'
        dpdk_bridgemaps = neutron_ovs_context.resolve_dpdk_ports()
        device_index = 0
        for br in dpdk_bridgemaps.itervalues():
            add_bridge(br, datapath_type)
            dpdk_add_bridge_port(br, 'dpdk{}'.format(device_index),
                                 port_type='dpdk')
            device_index += 1

    # 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')
Example #12
0
def configure_ovs():
    if config("plugin") in [OVS, OVS_ODL]:
        if not service_running("openvswitch-switch"):
            full_restart()
        add_bridge(INT_BRIDGE)
        add_bridge(EXT_BRIDGE)
        ext_port_ctx = ExternalPortContext()()
        if ext_port_ctx and ext_port_ctx["ext_port"]:
            add_bridge_port(EXT_BRIDGE, ext_port_ctx["ext_port"])

        portmaps = DataPortContext()()
        bridgemaps = parse_bridge_mappings(config("bridge-mappings"))
        for provider, br in bridgemaps.iteritems():
            add_bridge(br)
            if not portmaps:
                continue

            for port, _br in portmaps.iteritems():
                if _br == br:
                    add_bridge_port(br, port, promisc=True)

        # Ensure this runs so that mtu is applied to data-port interfaces if
        # provided.
        service_restart("os-charm-phy-nic-mtu")
Example #13
0
    def test_add_bridge_port(self):
        self.patch_object(ovs.subprocess, 'check_call')
        self.patch_object(ovs, 'log')
        ovs.add_bridge_port('test', 'eth1')
        self.check_call.assert_has_calls([
            mock.call(
                ['ovs-vsctl', '--', '--may-exist', 'add-port', 'test',
                 'eth1']),
            mock.call(['ip', 'link', 'set', 'eth1', 'up']),
            mock.call(['ip', 'link', 'set', 'eth1', 'promisc', 'off'])
        ])
        self.assertTrue(self.log.call_count == 1)

        self.check_call.reset_mock()
        self.log.reset_mock()
        ovs.add_bridge_port('test', 'eth1', promisc=True)
        self.check_call.assert_has_calls([
            mock.call(
                ['ovs-vsctl', '--', '--may-exist', 'add-port', 'test',
                 'eth1']),
            mock.call(['ip', 'link', 'set', 'eth1', 'up']),
            mock.call(['ip', 'link', 'set', 'eth1', 'promisc', 'on'])
        ])
        self.assertTrue(self.log.call_count == 1)

        self.check_call.reset_mock()
        ovs.add_bridge_port('test', 'eth1', exclusive=True, linkup=False)
        self.check_call.assert_has_calls([
            mock.call(['ovs-vsctl', '--', 'add-port', 'test', 'eth1']),
            mock.call(['ip', 'link', 'set', 'eth1', 'promisc', 'off'])
        ])

        self.check_call.reset_mock()
        self.patch_object(ovs, '_dict_to_vsctl_set')
        self._dict_to_vsctl_set.return_value = [['--', 'fakeextradata']]
        ovs.add_bridge_port('test', 'eth1', ifdata={'fakeinput': None})
        self._dict_to_vsctl_set.assert_called_once_with({'fakeinput': None},
                                                        'Interface', 'eth1')
        self.check_call.assert_has_calls([
            mock.call([
                'ovs-vsctl', '--', '--may-exist', 'add-port', 'test', 'eth1',
                '--', 'fakeextradata'
            ]),
            mock.call(['ip', 'link', 'set', 'eth1', 'up']),
            mock.call(['ip', 'link', 'set', 'eth1', 'promisc', 'off'])
        ])
Example #14
0
    def configure_bridges(self):
        """Configure Open vSwitch bridges ports and interfaces."""
        if self.check_if_paused() != (None, None):
            ch_core.hookenv.log(
                'Unit is paused, defer Open vSwitch bridge '
                'port interface configuration tasks.',
                level=ch_core.hookenv.INFO)
            return
        bpi = os_context.BridgePortInterfaceMap(bridges_key=self.bridges_key)
        bond_config = os_context.BondConfig()
        ch_core.hookenv.log('BridgePortInterfaceMap: "{}"'.format(bpi.items()),
                            level=ch_core.hookenv.DEBUG)

        # build map of bridges to ovn networks with existing if-mapping on host
        # and at the same time build ovn-bridge-mappings string
        ovn_br_map_str = ''
        ovnbridges = collections.defaultdict(list)
        config_obm = self.config['ovn-bridge-mappings'] or ''
        for pair in sorted(config_obm.split()):
            network, bridge = pair.split(':', 1)
            if bridge in bpi:
                ovnbridges[bridge].append(network)
                if ovn_br_map_str:
                    ovn_br_map_str += ','
                ovn_br_map_str += '{}:{}'.format(network, bridge)

        bridges = ch_ovsdb.SimpleOVSDB('ovs-vsctl').bridge
        ports = ch_ovsdb.SimpleOVSDB('ovs-vsctl').port
        for bridge in bridges.find('external_ids:charm-ovn-chassis=managed'):
            # remove bridges and ports that are managed by us and no longer in
            # config
            if bridge['name'] not in bpi and bridge['name'] != 'br-int':
                ch_core.hookenv.log(
                    'removing bridge "{}" as it is no longer'
                    'present in configuration for this unit.'.format(
                        bridge['name']),
                    level=ch_core.hookenv.DEBUG)
                ch_ovs.del_bridge(bridge['name'])
            else:
                for port in ports.find(
                        'external_ids:charm-ovn-chassis={}'.format(
                            bridge['name'])):
                    if port['name'] not in bpi[bridge['name']]:
                        ch_core.hookenv.log(
                            'removing port "{}" from bridge '
                            '"{}" as it is no longer present '
                            'in configuration for this unit.'.format(
                                port['name'], bridge['name']),
                            level=ch_core.hookenv.DEBUG)
                        ch_ovs.del_bridge_port(bridge['name'], port['name'])
        brdata = {
            'external-ids': {
                'charm-ovn-chassis': 'managed'
            },
            'protocols': 'OpenFlow13,OpenFlow15',
        }
        if self.options.enable_dpdk:
            brdata.update({'datapath-type': 'netdev'})
        else:
            brdata.update({'datapath-type': 'system'})
        # we always update the integration bridge to make sure it has settings
        # apropriate for the current charm configuration
        ch_ovs.add_bridge(
            'br-int',
            brdata={
                **brdata,
                **{
                    # for the integration bridge we want the datapath to await
                    # controller action before adding any flows. This is to avoid
                    # switching packets between isolated logical networks before
                    # `ovn-controller` starts up.
                    'fail-mode': 'secure',
                    # Suppress in-band control flows for the integration bridge,
                    # refer to ovn-architecture(7) for more details.
                    'other-config': {
                        'disable-in-band': 'true'
                    },
                },
            })
        for br in bpi:
            if br not in ovnbridges:
                continue
            ch_ovs.add_bridge(
                br,
                brdata={
                    **brdata,
                    # for bridges used for external connectivity we want the
                    # datapath to act like an ordinary MAC-learning switch.
                    **{
                        'fail-mode': 'standalone'
                    },
                })
            for port in bpi[br]:
                ifdatamap = bpi.get_ifdatamap(br, port)
                ifdatamap = {
                    port: {
                        **ifdata,
                        **{
                            'external-ids': {
                                'charm-ovn-chassis': br
                            }
                        },
                    }
                    for port, ifdata in ifdatamap.items()
                }

                if len(ifdatamap) > 1:
                    ch_ovs.add_bridge_bond(br, port, list(ifdatamap.keys()),
                                           bond_config.get_ovs_portdata(port),
                                           ifdatamap)
                else:
                    ch_ovs.add_bridge_port(
                        br,
                        port,
                        ifdata=ifdatamap.get(port, {}),
                        linkup=not self.options.enable_dpdk,
                        promisc=None,
                        portdata={'external-ids': {
                            'charm-ovn-chassis': br
                        }})

        opvs = ch_ovsdb.SimpleOVSDB('ovs-vsctl').open_vswitch
        if ovn_br_map_str:
            opvs.set('.', 'external_ids:ovn-bridge-mappings', ovn_br_map_str)
            # NOTE(fnordahl): Workaround for LP: #1848757
            opvs.set('.', 'external_ids:ovn-cms-options',
                     'enable-chassis-as-gw')
        else:
            opvs.remove('.', 'external_ids', 'ovn-bridge-mappings')
            # NOTE(fnordahl): Workaround for LP: #1848757
            opvs.remove('.', 'external_ids', 'ovn-cms-options')
Example #15
0
def configure_ovs():
    """Configure the OVS plugin.

    This function uses the config.yaml parameters ext-port, data-port and
    bridge-mappings to configure the bridges and ports on the ovs on the
    unit.

    Note that the ext-port is deprecated and data-port/bridge-mappings are
    preferred.

    Thus, if data-port is set, then ext-port is ignored (and if set, then
    it is removed from the set of bridges unless it is defined in
    bridge-mappings/data-port).  A warning is issued, if both data-port and
    ext-port are set.
    """
    status_set('maintenance', 'Configuring ovs')
    if not service_running('openvswitch-switch'):
        full_restart()

    # all bridges use the same datapath_type
    brdata = {
        'datapath-type': determine_datapath_type(),
    }
    brdata.update(generate_external_ids())

    add_bridge(INT_BRIDGE, brdata=brdata)
    add_bridge(EXT_BRIDGE, brdata=brdata)

    # If data-port is defined in the config, we can ignore ext-port value
    # and log an error to the unit's log
    if config('data-port') and config('ext-port'):
        log(
            "Both ext-port and data-port are set. ext-port is deprecated"
            " and is not used when data-port is set.",
            level=ERROR)

    ext_port_ctx = None
    if use_dvr():
        ext_port_ctx = ExternalPortContext()()
    # Set ext-port only if data-port isn't defined.
    if not config('data-port') and ext_port_ctx and ext_port_ctx['ext_port']:
        add_bridge_port(EXT_BRIDGE,
                        ext_port_ctx['ext_port'],
                        ifdata=generate_external_ids(EXT_BRIDGE),
                        portdata=generate_external_ids(EXT_BRIDGE))

    modern_ovs = ovs_has_late_dpdk_init()

    bridgemaps = None
    portmaps = 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, brdata=brdata)
            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,
                                        ifdata=generate_external_ids(br),
                                        portdata=generate_external_ids(br))
                    else:
                        log('{} is a Linux bridge: using Linux bridges in the '
                            'data-port config is deprecated for removal after '
                            '21.10 release of OpenStack charms.'.format(port),
                            level=WARNING)
                        add_ovsbridge_linuxbridge(
                            br,
                            port,
                            ifdata=generate_external_ids(br),
                            portdata=generate_external_ids(br))

    # 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)

        # TODO(sahid): We should also take into account the
        # "physical-network-mtus" in case different MTUs are
        # configured based on physical networks.
        global_mtu = (
            neutron_ovs_context.NeutronAPIContext()()['global_physnet_mtu'])

        dpdk_context = OVSDPDKDeviceContext()
        devices = dpdk_context.devices()

        portmaps = parse_data_port_mappings(config('data-port'))
        bridgemaps = parse_bridge_mappings(config('bridge-mappings'))

        bridge_port_interface_map = BridgePortInterfaceMap()
        bond_config = BondConfig()

        for br, port_iface_map in bridge_port_interface_map.items():
            log('Adding DPDK bridge: {}:{}'.format(br, brdata), level=DEBUG)
            add_bridge(br, brdata=brdata)
            if modern_ovs:
                for port in port_iface_map.keys():
                    ifdatamap = bridge_port_interface_map.get_ifdatamap(
                        br, port)
                    # set external-ids for all interfaces
                    for iface in ifdatamap:
                        ifdatamap[iface].update(generate_external_ids(br))
                    # NOTE: DPDK bonds are referenced by name and can be found
                    #       in the data-port config, regular DPDK ports are
                    #       referenced by MAC addresses and their names should
                    #       never be found in data-port
                    if port in portmaps.keys():
                        portdata = bond_config.get_ovs_portdata(port)
                        portdata.update(generate_external_ids(br))
                        log('Adding DPDK bond: {}({}) to bridge: {}'.format(
                            port, list(ifdatamap.keys()), br),
                            level=DEBUG)
                        add_bridge_bond(br,
                                        port,
                                        list(ifdatamap.keys()),
                                        portdata=portdata,
                                        ifdatamap=ifdatamap)
                    else:
                        log('Adding DPDK port: {} to bridge: {}'.format(
                            port, br),
                            level=DEBUG)
                        ifdata = ifdatamap[port]
                        add_bridge_port(br,
                                        port,
                                        ifdata=ifdata,
                                        portdata=generate_external_ids(br),
                                        linkup=False,
                                        promisc=None)
        if not modern_ovs:
            # port enumeration in legacy OVS-DPDK must follow alphabetic order
            # of the PCI addresses
            dev_idx = 0
            for pci, mac in sorted(devices.items()):
                # if mac.entity is a bridge, then the port can be added
                # directly, otherwise it is a bond (supported only in
                # modern_ovs) or misconfiguration
                if mac.entity in bridgemaps.values():
                    ifdata = {'type': 'dpdk', 'mtu-request': global_mtu}
                    ifdata.update(generate_external_ids(mac.entity))
                    ifname = 'dpdk{}'.format(dev_idx)
                    log('Adding DPDK port {}:{} to bridge {}'.format(
                        ifname, ifdata, mac.entity),
                        level=DEBUG)
                    add_bridge_port(mac.entity,
                                    ifname,
                                    ifdata=ifdata,
                                    portdata=generate_external_ids(mac.entity),
                                    linkup=False,
                                    promisc=None)
                else:
                    log('DPDK device {} skipped, {} is not a bridge'.format(
                        pci, mac.entity),
                        level=WARNING)
                dev_idx += 1

    target = config('ipfix-target')
    bridges = [INT_BRIDGE, EXT_BRIDGE]
    if bridgemaps:
        bridges.extend(bridgemaps.values())
    elif portmaps:
        bridges.extend([bridge_mac.entity for bridge_mac in portmaps.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():
    """Configure the OVS plugin.

    This function uses the config.yaml parameters ext-port, data-port and
    bridge-mappings to configure the bridges and ports on the ovs on the
    unit.

    Note that the ext-port is deprecated and data-port/bridge-mappings are
    preferred.

    Thus, if data-port is set, then ext-port is ignored (and if set, then
    it is removed from the set of bridges unless it is defined in
    bridge-mappings/data-port).  A warning is issued, if both data-port and
    ext-port are set.
    """
    if config('plugin') in [OVS, OVS_ODL]:
        if not service_running('openvswitch-switch'):
            full_restart()
        # Get existing set of bridges and ports
        current_bridges_and_ports = get_bridges_and_ports_map()
        log("configure OVS: Current bridges and ports map: {}".format(
            ", ".join("{}: {}".format(b, ",".join(v))
                      for b, v in current_bridges_and_ports.items())))

        add_bridge(INT_BRIDGE, brdata=_ovs_additional_data())
        add_bridge(EXT_BRIDGE, brdata=_ovs_additional_data())

        ext_port_ctx = ExternalPortContext()()
        portmaps = DataPortContext()()
        bridgemaps = parse_bridge_mappings(config('bridge-mappings'))

        # if we have portmaps, then we ignore its value and log an
        # error/warning to the unit's log.
        if config('data-port') and config('ext-port'):
            log(
                "Both ext-port and data-port are set.  ext-port is deprecated"
                " and is not used when data-port is set",
                level=ERROR)

        # only use ext-port if data-port is not set
        if not portmaps and ext_port_ctx and ext_port_ctx['ext_port']:
            _port = ext_port_ctx['ext_port']
            add_bridge_port(EXT_BRIDGE,
                            _port,
                            ifdata=_ovs_additional_data(EXT_BRIDGE),
                            portdata=_ovs_additional_data(EXT_BRIDGE))
            log("DEPRECATION: using ext-port to set the port {} on the "
                "EXT_BRIDGE ({}) is deprecated.  Please use data-port instead."
                .format(_port, EXT_BRIDGE),
                level=WARNING)

        for br in bridgemaps.values():
            add_bridge(br, brdata=_ovs_additional_data())
            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,
                                        ifdata=_ovs_additional_data(br),
                                        portdata=_ovs_additional_data(br))
                    else:
                        # NOTE(lourot): this will raise on focal+ and/or if the
                        # system has no `ifup`. See lp:1877594
                        add_ovsbridge_linuxbridge(
                            br,
                            port,
                            ifdata=_ovs_additional_data(br),
                            portdata=_ovs_additional_data(br))

        target = config('ipfix-target')
        bridges = [INT_BRIDGE, EXT_BRIDGE]
        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)

        new_bridges_and_ports = get_bridges_and_ports_map()
        log("configure OVS: Final bridges and ports map: {}".format(", ".join(
            "{}: {}".format(b, ",".join(v))
            for b, v in new_bridges_and_ports.items())),
            level=DEBUG)

        # Ensure this runs so that mtu is applied to data-port interfaces if
        # provided.
        service_restart('os-charm-phy-nic-mtu')
Example #17
0
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():
        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')