Example #1
0
def ensure_default_ovs_flows(ovn_bridge_mappings, cookie):
    cookie_id = ("cookie={}/-1").format(cookie)
    for bridge in ovn_bridge_mappings:
        ovs_port = ovs_cmd('ovs-vsctl', ['list-ports', bridge])[0].rstrip()
        if not ovs_port:
            continue
        ovs_ofport = ovs_cmd(
            'ovs-vsctl', ['get', 'Interface', ovs_port, 'ofport']
            )[0].rstrip()
        flow_filter = ('{},in_port={}').format(cookie_id, ovs_ofport)
        current_flows = ovs_cmd(
            'ovs-ofctl', ['dump-flows', bridge, flow_filter]
            )[0].split('\n')[1:-1]
        if len(current_flows) == 1:
            # assume the rule is the right one as it has the right cookie
            # and in_port
            continue

        with pyroute2.NDB() as ndb:
            flow = ("cookie={},priority=900,ip,in_port={},"
                    "actions=mod_dl_dst:{},NORMAL".format(
                        cookie, ovs_ofport,
                        ndb.interfaces[bridge]['address']))
            flow_v6 = ("cookie={},priority=900,ipv6,in_port={},"
                       "actions=mod_dl_dst:{},NORMAL".format(
                           cookie, ovs_ofport,
                           ndb.interfaces[bridge]['address']))
        ovs_cmd('ovs-ofctl', ['add-flow', bridge, flow])
        ovs_cmd('ovs-ofctl', ['add-flow', bridge, flow_v6])

        # Remove unneeded flows
        port = 'in_port={}'.format(ovs_ofport)
        current_flows = ovs_cmd(
                'ovs-ofctl', ['dump-flows', bridge, cookie_id]
                )[0].split('\n')[1:-1]
        for flow in current_flows:
            if not flow or port in flow:
                continue
            in_port = flow.split("in_port=")[1].split(" ")[0]
            del_flow = ('{},in_port={}').format(cookie_id, in_port)
            ovs_cmd('ovs-ofctl', ['del-flows', bridge, del_flow])
Example #2
0
    def sync(self):
        self.ovn_local_cr_lrps = {}
        self.ovn_local_lrps = set([])
        self.ovn_routing_tables_routes = collections.defaultdict()

        LOG.debug("Ensuring VRF configuration for advertising routes")
        # Create VRF
        linux_net.ensure_vrf(constants.OVN_BGP_VRF,
                             constants.OVN_BGP_VRF_TABLE)
        # Create OVN dummy device
        linux_net.ensure_ovn_device(constants.OVN_BGP_NIC,
                                    constants.OVN_BGP_VRF)

        LOG.debug("Configuring br-ex default rule and routing tables for "
                  "each provider network")
        flows_info = {}
        # 1) Get bridge mappings: xxxx:br-ex,yyyy:br-ex2
        bridge_mappings = self.ovs_idl.get_ovn_bridge_mappings()
        # 2) Get macs for bridge mappings
        extra_routes = {}
        with pyroute2.NDB() as ndb:
            for bridge_mapping in bridge_mappings:
                network = bridge_mapping.split(":")[0]
                bridge = bridge_mapping.split(":")[1]
                self.ovn_bridge_mappings[network] = bridge
                if not extra_routes.get(bridge):
                    extra_routes[bridge] = (
                        linux_net.ensure_routing_table_for_bridge(
                            self.ovn_routing_tables, bridge))
                vlan_tag = self.sb_idl.get_network_vlan_tag_by_network_name(
                    network)
                if vlan_tag:
                    vlan_tag = vlan_tag[0]
                    linux_net.ensure_vlan_device_for_network(bridge,
                                                             vlan_tag)

                if flows_info.get(bridge):
                    continue
                flows_info[bridge] = {
                    'mac': ndb.interfaces[bridge]['address'],
                    'in_port': set([])}
                # 3) Get in_port for bridge mappings (br-ex, br-ex2)
                ovs.get_ovs_flows_info(bridge, flows_info,
                                       constants.OVS_RULE_COOKIE)
        # 4) Add/Remove flows for each bridge mappings
        ovs.remove_extra_ovs_flows(flows_info, constants.OVS_RULE_COOKIE)

        LOG.debug("Syncing current routes.")
        exposed_ips = linux_net.get_exposed_ips(constants.OVN_BGP_NIC)
        # get the rules pointing to ovn bridges
        ovn_ip_rules = linux_net.get_ovn_ip_rules(
            self.ovn_routing_tables.values())

        # add missing routes/ips for fips/provider VMs
        ports = self.sb_idl.get_ports_on_chassis(self.chassis)
        for port in ports:
            self._ensure_port_exposed(port, exposed_ips, ovn_ip_rules)

        # add missing route/ips for tenant network VMs
        if self._expose_tenant_networks:
            for cr_lrp_info in self.ovn_local_cr_lrps.values():
                lrp_ports = self.sb_idl.get_lrp_ports_for_router(
                    cr_lrp_info['router_datapath'])
                for lrp in lrp_ports:
                    if lrp.chassis:
                        continue
                    self._ensure_network_exposed(
                        lrp, cr_lrp_info, exposed_ips, ovn_ip_rules)

        # remove extra routes/ips
        # remove all the leftovers on the list of current ips on dev OVN
        linux_net.delete_exposed_ips(exposed_ips, constants.OVN_BGP_NIC)
        # remove all the leftovers on the list of current ip rules for ovn
        # bridges
        linux_net.delete_ip_rules(ovn_ip_rules)

        # remove all the extra rules not needed
        linux_net.delete_bridge_ip_routes(self.ovn_routing_tables,
                                          self.ovn_routing_tables_routes,
                                          extra_routes)