示例#1
0
    def remove_security_group_rule(self, secgroup, secgroup_rule):
        LOG.info(_LI("remove a rule %(rule)s to security group %(secgroup)s")
                 % {'rule': secgroup_rule, 'secgroup': secgroup.name})
        if self.get_datapath() is None:
            LOG.error(_LE("datapath is none"))
            return

        conj_id, priority = \
            self._get_secgroup_conj_id_and_priority(secgroup.name)
        if conj_id is None:
            # this security group wasn't associated with a local port
            LOG.info(_LI("this security group %s wasn't associated with"
                         " a local port"), secgroup.name)
            return

        # update the record of rules each of which specifies a same security
        # group as its parameter of remote group.
        remote_group_id = secgroup_rule.remote_group_id
        if remote_group_id is not None:
            associate_rules = self.remote_secgroup_ref.get(remote_group_id)
            if associate_rules is not None:
                del associate_rules[secgroup_rule.id]
                if len(associate_rules) == 0:
                    del self.remote_secgroup_ref[remote_group_id]

        self._uninstall_security_group_rule_flows(secgroup_rule)
示例#2
0
 def test_infrastructure(self):
     try:
         topology = app_testing_objects.Topology(self.neutron, self.nb_api)
         subnet1 = topology.create_subnet(cidr='192.168.10.0/24')
         subnet2 = topology.create_subnet(cidr='192.168.11.0/24')
         port1 = subnet1.create_port()
         port2 = subnet2.create_port()
         topology.create_router([subnet1.subnet_id, subnet2.subnet_id])
         LOG.info(_LI('Port1 name: {}').format(port1.tap.tap.name))
         LOG.info(_LI('Port2 name: {}').format(port2.tap.tap.name))
         test_utils.print_command(['ip', 'addr'])
         test_utils.print_command(['ovs-vsctl', 'show'], True)
         test_utils.print_command(
             ['ovs-ofctl', 'show', 'br-int'],
             True
         )
         test_utils.print_command(
             ['ovs-ofctl', 'dump-flows', 'br-int'],
             True
         )
         test_utils.print_command(
             ['ovsdb-client', 'dump', 'Open_vSwitch'],
             True
         )
     except Exception as e:
         traceback = sys.exc_info()[2]
         try:
             topology.close()
         except Exception:
             pass  # Ignore
         # Just calling raise may raise an exception from topology.close()
         raise e, None, traceback
     topology.close()
示例#3
0
    def _handle_dhcp_request(self, msg, pkt, lport):
        packet = ryu_packet.Packet(data=msg.data)
        in_port = msg.match.get("in_port")

        if isinstance(packet[3], str):
            dhcp_packet = dhcp.dhcp.parser(packet[3])[0]
        else:
            dhcp_packet = packet[3]

        dhcp_message_type = self._get_dhcp_message_type_opt(dhcp_packet)
        send_packet = None
        if dhcp_message_type == DHCP_DISCOVER:
            #DHCP DISCOVER
            send_packet = self._create_dhcp_offer(
                                pkt,
                                dhcp_packet,
                                lport)
            LOG.info(_LI("sending DHCP offer for port IP %(port_ip)s"
                " port id %(port_id)s")
                     % {'port_ip': lport.get_ip(), 'port_id': lport.get_id()})
        elif dhcp_message_type == DHCP_REQUEST:
            #DHCP REQUEST
            send_packet = self._create_dhcp_ack(
                                pkt,
                                dhcp_packet,
                                lport)
            LOG.info(_LI("sending DHCP ACK for port IP %(port_ip)s"
                        " port id %(tunnel_id)s")
                        % {'port_ip': lport.get_ip(),
                        'tunnel_id': lport.get_id()})
        else:
            LOG.error(_LE("DHCP message type %d not handled"),
                dhcp_message_type)
        if send_packet:
            self._send_packet(self.get_datapath(), in_port, send_packet)
def _acquire_lock(oid):
    # generate temporary session id for this API context
    sid = _generate_session_id()

    # NOTE(nick-ma-z): we disallow subtransactions because the
    # retry logic will bust any parent transactions
    wait_lock_retries = LOCK_MAX_RETRIES
    retry_interval = LOCK_INIT_RETRY_INTERVAL
    while(wait_lock_retries > 0):
        try:
            session = db_api.get_session()
            with session.begin():
                LOG.info(_LI("Try to get lock for object %(oid)s in "
                             "session %(sid)s."), {'oid': oid, 'sid': sid})
                row = _get_object_with_lock(session, oid, False)
                _update_lock(session, row, True, session_id=sid)
            LOG.info(_LI("Lock is acquired for object %(oid)s in "
                         "session %(sid)s."), {'oid': oid, 'sid': sid})
            return sid
        except orm_exc.NoResultFound:
            LOG.info(_LI("Lock has been obtained by other sessions. "
                         "Wait here and retry."))
            time.sleep(retry_interval)
            wait_lock_retries = wait_lock_retries - 1

            # dynamically increase the retry_interval until it reaches
            # the maximum of interval and then return to the initial value.
            if retry_interval >= LOCK_MAX_RETRY_INTERVAL:
                retry_interval = LOCK_INIT_RETRY_INTERVAL
            else:
                retry_interval = retry_interval + LOCK_INC_RETRY_INTERVAL

    # NOTE(nick-ma-z): The lock cannot be acquired.
    raise df_exceptions.DBLockFailed(oid=oid, sid=sid)
示例#5
0
    def _port_status_handler(self, ev):
        msg = ev.msg
        reason = msg.reason
        port_no = msg.desc.port_no
        port_name = msg.desc.name

        ofproto = msg.datapath.ofproto
        if reason == ofproto.OFPPR_ADD:
            LOG.info(_LI("port added %s"), port_no)
            lport = self.db_store.get_local_port_by_name(port_name)
            if lport:
                lport.set_external_value('ofport', port_no)
                lport.set_external_value('is_local', True)
                self.notify_add_local_port(lport)
        elif reason == ofproto.OFPPR_DELETE:
            LOG.info(_LI("port deleted %s"), port_no)
            lport = self.db_store.get_local_port_by_name(port_name)
            if lport:
                self.notify_remove_local_port(lport)
                # Leave the last correct OF port number of this port
        elif reason == ofproto.OFPPR_MODIFY:
            LOG.info(_LI("port modified %s"), port_no)
            # TODO(oanson) Add notification
        else:
            LOG.info(_LI("Illeagal port state %(port_no)s %(reason)s")
                     % {'port_no': port_no, 'reason': reason})
    def _logical_port_process(self, lport, original_lport=None):
        chassis = lport.get_chassis()
        if chassis in (None,
                       '',
                       constants.DRAGONFLOW_VIRTUAL_PORT):
            LOG.debug(("Port %s has not been bound or it is a vPort ") %
                      lport.get_id())
            return

        chassis_to_ofport, lport_to_ofport = (
            self.vswitch_api.get_local_ports_to_ofport_mapping())
        network = self.get_network_id(
            lport.get_lswitch_id(),
        )
        lport.set_external_value('local_network_id', network)

        if chassis == self.chassis_name:
            lport.set_external_value('is_local', True)
            ofport = lport_to_ofport.get(lport.get_id(), 0)
            if ofport != 0:
                lport.set_external_value('ofport', ofport)
                if original_lport is None:
                    LOG.info(_LI("Adding new local logical port = %s") %
                             str(lport))
                    self.open_flow_app.notify_add_local_port(lport)
                else:
                    LOG.info(_LI("Updating local logical port = %(port)s, "
                                 "original port = %(original_port)s") %
                             {'port': str(lport),
                              'original_port': str(original_lport)})
                    self.open_flow_app.notify_update_local_port(lport,
                                                                original_lport)
                self.db_store.set_port(lport.get_id(), lport, True)
            else:
                LOG.info(_LI("Local logical port %s was not created yet") %
                         str(lport))
        else:
            lport.set_external_value('is_local', False)
            ofport = chassis_to_ofport.get(chassis, 0)
            if ofport != 0:
                lport.set_external_value('ofport', ofport)
                if original_lport is None:
                    LOG.info(_LI("Adding new remote logical port = %s") %
                             str(lport))
                    self.open_flow_app.notify_add_remote_port(lport)
                else:
                    LOG.info(_LI("Updating remote logical port = %(port)s, "
                                 "original port = %(original_port)s") %
                             {'port': str(lport),
                              'original_port': str(original_lport)})
                    self.open_flow_app.notify_update_remote_port(
                        lport, original_lport)
                self.db_store.set_port(lport.get_id(), lport, False)
            else:
                # TODO(gampel) add handling for this use case
                # remote port but no tunnel to remote Host
                # if this should never happen raise an exception
                LOG.warning(_LW("No tunnel for remote logical port %s") %
                            str(lport))
示例#7
0
 def ovs_sync_started(self):
     LOG.info(_LI("start aging"))
     canary_flow = self.get_canary_flow()
     if canary_flow is None:
         self.do_aging = False
         cookie.set_aging_cookie(const.GLOBAL_INIT_AGING_COOKIE)
         LOG.info(_LI("no canary table, don't do aging"))
     else:
         self._renew_aging_cookie(canary_flow.cookie)
     self.add_canary_flow(cookie.get_aging_cookie())
示例#8
0
def _release_lock(oid, sid):
    # NOTE(nick-ma-z): we disallow subtransactions because the
    # retry logic will bust any parent transactions
    session = db_api.get_session()
    with session.begin():
        LOG.info(_LI("Try to get lock for object %(oid)s in "
                     "session %(sid)s."), {'oid': oid, 'sid': sid})
        _lock_free_update(session, oid, lock_state=True, session_id=sid)
        LOG.info(_LI("Lock is released for object %(oid)s in "
                     "session %(sid)s."), {'oid': oid, 'sid': sid})
示例#9
0
def _acquire_lock(oid):
    # generate temporary session id for this API context
    sid = _generate_session_id()

    # NOTE(nick-ma-z): we disallow subtransactions because the
    # retry logic will bust any parent transactions
    session = db_api.get_session()
    with session.begin():
        LOG.info(_LI("Try to get lock for object %(oid)s in "
                     "session %(sid)s."), {'oid': oid, 'sid': sid})
        _lock_free_update(session, oid, lock_state=False, session_id=sid)
        LOG.info(_LI("Lock is acquired for object %(oid)s in "
                     "session %(sid)s."), {'oid': oid, 'sid': sid})
        return sid
示例#10
0
 def logical_port_deleted(self, lport_id):
     lport = self.db_store.get_port(lport_id)
     if lport is None:
         return
     if lport.get_external_value('is_local'):
         LOG.info(_LI("Removing local Logical Port = %s") %
                  lport.__str__())
         self.open_flow_app.notify_remove_local_port(lport)
         self.db_store.delete_port(lport.get_id(), True)
     else:
         LOG.info(_LI("Removing remote Logical Port = %s") %
                  lport.__str__())
         self.open_flow_app.notify_remove_remote_port(lport)
         self.db_store.delete_port(lport.get_id(), False)
示例#11
0
 def chassis_created(self, chassis):
     # Check if tunnel already exists to this chassis
     t_ports = self.vswitch_api.get_tunnel_ports()
     remote_chassis_name = chassis.get_name()
     if self.chassis_name == remote_chassis_name:
         return
     for t_port in t_ports:
         if t_port.get_chassis_id() == remote_chassis_name:
             LOG.info(_LI("remote Chassis Tunnel already installed  = %s") %
                  chassis.__str__())
             return
     # Create tunnel port to this chassis
     LOG.info(_LI("Adding tunnel to remote chassis = %s") %
              chassis.__str__())
     self.vswitch_api.add_tunnel_port(chassis).execute()
示例#12
0
    def initialize(self):
        LOG.info(_LI("Starting DFMechDriver"))

        # When set to True, Nova plugs the VIF directly into the ovs bridge
        # instead of using the hybrid mode.
        self.vif_details = {portbindings.CAP_PORT_FILTER: True}
        self.vif_type = portbindings.VIF_TYPE_OVS
        self._set_base_port_binding()

        nb_driver_class = importutils.import_class(cfg.CONF.df.nb_db_class)
        self.nb_api = api_nb.NbApi(
                nb_driver_class(),
                use_pubsub=cfg.CONF.df.enable_df_pub_sub,
                is_neutron_server=True)
        self.nb_api.initialize(db_ip=cfg.CONF.df.remote_db_ip,
                               db_port=cfg.CONF.df.remote_db_port)

        registry.subscribe(self.create_security_group,
                           resources.SECURITY_GROUP,
                           events.AFTER_CREATE)
        registry.subscribe(self.delete_security_group,
                           resources.SECURITY_GROUP,
                           events.BEFORE_DELETE)
        registry.subscribe(self.create_security_group_rule,
                           resources.SECURITY_GROUP_RULE,
                           events.AFTER_CREATE)
        registry.subscribe(self.delete_security_group_rule,
                           resources.SECURITY_GROUP_RULE,
                           events.BEFORE_DELETE)
示例#13
0
 def _delete_router_port(self, router_port):
     LOG.info(_LI("Removing logical router interface = %s") %
              router_port.__str__())
     local_network_id = self.db_store.get_network_id(
             router_port.get_lswitch_id())
     self.open_flow_app.notify_remove_router_port(
             router_port, local_network_id)
示例#14
0
    def update_subnet_postcommit(self, context):
        new_subnet = context.current
        old_subnet = context.original
        plugin_context = context._plugin_context

        try:
            dhcp_port = self._handle_update_subnet_dhcp(plugin_context,
                                                        old_subnet,
                                                        new_subnet)
        except Exception as e:
            LOG.exception(e)
            return None

        dhcp_address = self._get_ip_from_port(dhcp_port)
        self.nb_api.update_subnet(
            new_subnet['id'],
            new_subnet['network_id'],
            new_subnet['tenant_id'],
            name=new_subnet.get('name', df_const.DF_SUBNET_DEFAULT_NAME),
            nw_version=new_subnet['db_version'],
            enable_dhcp=new_subnet['enable_dhcp'],
            cidr=new_subnet['cidr'],
            dhcp_ip=dhcp_address,
            gateway_ip=new_subnet['gateway_ip'],
            dns_nameservers=new_subnet.get('dns_nameservers', []),
            host_routes=new_subnet.get('host_routes', []))

        LOG.info(_LI("DFMechDriver: update subnet %s"), new_subnet['id'])
        return new_subnet
示例#15
0
    def create_port_postcommit(self, context):
        port = context.current
        ips = [ip['ip_address'] for ip in port.get('fixed_ips', [])]
        tunnel_key = self.nb_api.allocate_tunnel_key()

        # Router GW ports are not needed by dragonflow controller and
        # they currently cause error as they couldnt be mapped to
        # a valid ofport (or location)
        if port.get('device_owner') == n_const.DEVICE_OWNER_ROUTER_GW:
            chassis = None
        else:
            chassis = port.get('binding:host_id', None)

        self.nb_api.create_lport(
            id=port['id'],
            lswitch_id=port['network_id'],
            topic=port['tenant_id'],
            macs=[port['mac_address']], ips=ips,
            name=port.get('name', df_const.DF_PORT_DEFAULT_NAME),
            enabled=port.get('admin_state_up', None),
            chassis=chassis, tunnel_key=tunnel_key,
            version=port['db_version'],
            device_owner=port.get('device_owner', None),
            device_id=port.get('device_id', None),
            security_groups=port.get('security_groups', None),
            port_security_enabled=port.get(psec.PORTSECURITY, False),
            allowed_address_pairs=port.get(addr_pair.ADDRESS_PAIRS, None))

        LOG.info(_LI("DFMechDriver: create port %s"), port['id'])
        return port
示例#16
0
 def chassis_deleted(self, chassis_id):
     LOG.info(_LI("Deleting tunnel to remote chassis = %s") % chassis_id)
     tunnel_ports = self.vswitch_api.get_tunnel_ports()
     for port in tunnel_ports:
         if port.get_chassis_id() == chassis_id:
             self.vswitch_api.delete_port(port).execute()
             return
示例#17
0
    def add_local_port(self, lport):
        network_id = lport.get_external_value('local_network_id')
        if self.get_datapath() is None:
            return

        lport_id = lport.get_id()
        tunnel_key = lport.get_tunnel_key()
        self.local_tunnel_to_pid_map[tunnel_key] = lport_id

        if not self._is_dhcp_enabled_on_network(lport, network_id):
            return

        if not self._is_port_a_vm(lport):
            return

        LOG.info(_LI("Regiter VM as DHCP client::port <%s>") % lport.get_id())

        ofport = lport.get_external_value('ofport')
        parser = self.get_datapath().ofproto_parser
        ofproto = self.get_datapath().ofproto
        match = parser.OFPMatch()
        match.set_in_port(ofport)
        actions = []
        actions.append(parser.OFPActionSetField(metadata=tunnel_key))
        actions.append(parser.OFPActionOutput(ofproto.OFPP_CONTROLLER,
                                          ofproto.OFPCML_NO_BUFFER))
        inst = [self.get_datapath().ofproto_parser.OFPInstructionActions(
            ofproto.OFPIT_APPLY_ACTIONS, actions)]

        self.mod_flow(
            self.get_datapath(),
            inst=inst,
            table_id=const.DHCP_TABLE,
            priority=const.PRIORITY_MEDIUM,
            match=match)
示例#18
0
 def _add_new_router_port(self, router, router_port):
     LOG.info(_LI("Adding new logical router interface = %s") %
              router_port.__str__())
     local_network_id = self.db_store.get_network_id(
             router_port.get_lswitch_id())
     self.open_flow_app.notify_add_router_port(
             router, router_port, local_network_id)
示例#19
0
    def _install_flows_check_valid_ip_and_mac(self, datapath, ofport, ip, mac):
        if netaddr.IPNetwork(ip).version == 6:
            LOG.info(_LI("IPv6 addresses are not supported yet"))
            return

        parser = datapath.ofproto_parser

        # Valid ip mac pair pass
        match = parser.OFPMatch(in_port=ofport,
                                eth_src=mac,
                                eth_type=ether.ETH_TYPE_IP,
                                ipv4_src=ip)
        self.add_flow_go_to_table(datapath,
                                  const.EGRESS_PORT_SECURITY_TABLE,
                                  const.PRIORITY_HIGH,
                                  const.EGRESS_CONNTRACK_TABLE,
                                  match=match)

        # Valid arp request/reply pass
        match = parser.OFPMatch(in_port=ofport,
                                eth_src=mac,
                                eth_type=ether.ETH_TYPE_ARP,
                                arp_spa=ip,
                                arp_sha=mac)
        self.add_flow_go_to_table(datapath,
                                  const.EGRESS_PORT_SECURITY_TABLE,
                                  const.PRIORITY_HIGH,
                                  const.SERVICES_CLASSIFICATION_TABLE,
                                  match=match)
示例#20
0
    def _uninstall_flows_check_valid_ip_and_mac(self, datapath, ofport,
                                                ip, mac):
        if netaddr.IPNetwork(ip).version == 6:
            LOG.info(_LI("IPv6 addresses are not supported yet"))
            return

        parser = datapath.ofproto_parser

        # Remove valid ip mac pair pass
        match = parser.OFPMatch(in_port=ofport,
                                eth_src=mac,
                                eth_type=ether.ETH_TYPE_IP,
                                ipv4_src=ip)
        self._remove_one_port_security_flow(datapath,
                                            const.PRIORITY_HIGH,
                                            match)

        # Remove valid arp request/reply pass
        match = parser.OFPMatch(in_port=ofport,
                                eth_src=mac,
                                eth_type=ether.ETH_TYPE_ARP,
                                arp_spa=ip,
                                arp_sha=mac)
        self._remove_one_port_security_flow(datapath,
                                            const.PRIORITY_HIGH,
                                            match)
示例#21
0
 def register_notification_callback(self, controller):
     self.controller = controller
     LOG.info(_LI("DB configuration sync finished, waiting for changes"))
     if not self.use_pubsub:
         self.driver.register_notification_callback(
             self.db_change_callback)
     self._read_db_changes_from_queue()
示例#22
0
def _lock_free_update(session, id, lock_state=False, session_id=0):
    """Implement lock-free atomic update for the distributed lock

    :param session:    the db session
    :type session:     DB Session object
    :param id:         the lock uuid
    :type id:          string
    :param lock_state: the lock state to update
    :type lock_state:  boolean
    :param session_id: the API session ID to update
    :type session_id:  string
    :raises:           RetryRequest() when the lock failed to update
    """
    if not lock_state:
        # acquire lock
        search_params = {'object_uuid': id, 'lock': lock_state}
        update_params = {'lock': not lock_state, 'session_id': session_id,
                         'created_at': func.now()}
    else:
        # release or reset lock
        search_params = {'object_uuid': id, 'lock': lock_state,
                         'session_id': session_id}
        update_params = {'lock': not lock_state, 'session_id': 0}

    rows_update = session.query(models.DFLockedObjects).\
        filter_by(**search_params).\
        update(update_params, synchronize_session='fetch')

    if not rows_update:
        LOG.info(_LI('The lock for object %(id)s in session '
                     '%(sid)s cannot be updated.'), {'id': id,
                                                     'sid': session_id})
        raise db_exc.RetryRequest(df_exc.DBLockFailed(oid=id, sid=session_id))
示例#23
0
    def _vm_port_deleted(self, ovs_port):
        ovs_port_id = ovs_port.get_id()
        lport_id = ovs_port.get_iface_id()
        lport = self.db_store.get_port(lport_id)
        if lport is None:
            lport = self.ovs_to_lport_mapping.get(ovs_port_id)
            if lport is None:
                return
            topic = lport.get('topic')
            del self.ovs_to_lport_mapping[ovs_port_id]
            self._del_from_topic_subscribed(topic, lport_id)
            return

        topic = lport.get_topic()

        LOG.info(_LI("The logical port(%s) is offline") % str(lport))
        try:
            self.controller.logical_port_deleted(lport_id)
        except Exception:
            LOG.exception(_LE(
                'Failed to process logical port offline event %s') % lport_id)
        finally:
            # TODO(duankebo) publish vm port offline later
            # currently we will not publish vm port offline event.
            # lport = self.nb_api.get_logical_port(lport_id)
            # if lport.get_chassis() == self.chassis_name:
            #    self.nb_api.update_lport(lport.get_id(), chassis=None,
            #                             status='DOWN')
            del self.ovs_to_lport_mapping[ovs_port_id]
            self._del_from_topic_subscribed(topic, lport_id)
示例#24
0
    def ovs_port_deleted(self, ovs_port_id):
        """
        Changes in ovs port status will be monitored by ovsdb monitor thread
        and notified to topology. This method is the entrance port to process
        port offline event

        @param ovs_port_id:
        @return : None
        """
        ovs_port = self.ovs_ports.get(ovs_port_id)
        if ovs_port is None:
            return

        port_type = ovs_port.get_type()
        if port_type not in self.ovs_port_type:
            LOG.error(_LE("Unknown port offline: %s") % str(ovs_port))
            return

        handler_name = '_' + port_type + '_port_deleted'

        try:
            handler = getattr(self, handler_name, None)
            if handler is not None:
                handler(ovs_port)
            else:
                LOG(_LI("%s is None.") % handler_name)
        except Exception:
            LOG.exception(_LE("Exception occurred when handling "
                          "ovs port update event"))
        finally:
            del self.ovs_ports[ovs_port_id]
示例#25
0
 def floatingip_deleted(self, floatingip_id):
     floatingip = self.db_store.get_floatingip(floatingip_id)
     if not floatingip:
         return
     self.open_flow_app.notify_delete_floatingip(floatingip)
     LOG.info(_LI("Floatingip is deleted. Floatingip = %s") %
              str(floatingip))
示例#26
0
    def test_icmp_ping_pong(self):
        # the rules of the initial security group associated with port3
        # only let icmp echo requests from port1 pass.
        self.policy.start(self.topology)
        self.policy.wait(30)

        # switch the associated security group with port3 to a new security
        # group, and rules of this security group only let icmp echo requests
        # from port2 pass.
        self._switch_to_another_security_group()
        time.sleep(test_utils.DEFAULT_CMD_TIMEOUT)

        self.policy.start(self.topology)
        self.policy.wait(30)

        # switch the associated security group with port3 to the initial
        # security group
        self._switch_to_another_security_group()
        time.sleep(test_utils.DEFAULT_CMD_TIMEOUT)

        self.policy.start(self.topology)
        self.policy.wait(30)

        ovs = test_utils.OvsFlowsParser()
        LOG.info(_LI("flows are: %s"), ovs.get_ovs_flows())

        if len(self.policy.exceptions) > 0:
            raise self.policy.exceptions[0]
 def delete(self):
     self._disconnect_tap_device_to_vswitch('br-int', self.tap.name)
     LOG.info(_LI('Closing tap interface {} ({})').format(
         self.tap.name,
         self.tap.fileno(),
     ))
     self.tap.close()
示例#28
0
def _release_lock(oid, sid):
    # NOTE(nick-ma-z): we disallow subtransactions because the
    # retry logic will bust any parent transactions
    try:
        session = db_api.get_session()
        with session.begin():
            LOG.info(_LI("Try to get lock for object %(oid)s in "
                         "session %(sid)s."), {'oid': oid, 'sid': sid})
            row = _get_object_with_lock(session, oid, True,
                                        session_id=sid)
            _update_lock(session, row, False, session_id=0)
        LOG.info(_LI("Lock is released for object %(oid)s in "
                     "session %(sid)s."), {'oid': oid, 'sid': sid})
    except orm_exc.NoResultFound:
        LOG.exception(_LE("The lock for object %(oid)s is lost in the "
                          "session %(sid)s and obtained by other "
                          "sessions."), {'oid': oid, 'sid': sid})
    def logical_port_updated(self, lport):
        if self.db_store.get_port(lport.get_id()) is not None:
            # TODO(gsagie) support updating port
            return

        if lport.get_chassis() is None or (
                    lport.get_chassis() == constants.DRAGONFLOW_VIRTUAL_PORT):
            return

        chassis_to_ofport, lport_to_ofport = (
            self.vswitch_api.get_local_ports_to_ofport_mapping())
        network = self.get_network_id(
            lport.get_lswitch_id(),
            lport.get_topic(),
        )
        lport.set_external_value('local_network_id', network)

        if lport.get_chassis() == self.chassis_name:
            ofport = lport_to_ofport.get(lport.get_id(), 0)
            self.db_store.set_port(lport.get_id(), lport, True)
            if ofport != 0:
                lport.set_external_value('ofport', ofport)
                lport.set_external_value('is_local', True)
                LOG.info(_LI("Adding new local Logical Port = %s") %
                         lport.__str__())
                self.open_flow_app.notify_add_local_port(lport)
                self.db_store.set_port(lport.get_id(), lport, True)
            else:
                LOG.info(_LI("Logical Local Port %s was not created yet ") %
                         lport.__str__())
        else:
            ofport = chassis_to_ofport.get(lport.get_chassis(), 0)
            self.db_store.set_port(lport.get_id(), lport, False)
            if ofport != 0:
                lport.set_external_value('ofport', ofport)
                lport.set_external_value('is_local', False)
                LOG.info(_LI("Adding new remote Logical Port = %s") %
                         lport.__str__())
                self.open_flow_app.notify_add_remote_port(lport)
                self.db_store.set_port(lport.get_id(), lport, False)
            else:
                #TODO(gampel) add handling for this use case
                #remote port but no tunnel to remote Host
                #if this should never happen raise an exception
                LOG.warning(_LW("No tunnel for Logical Remote Port %s  ") %
                         lport.__str__())
示例#30
0
 def publisher_deleted(self, uuid):
     publisher = self.db_store.get_publisher(uuid)
     if publisher:
         LOG.info(_LI('Deleting publisher: %s'), str(publisher))
         self.nb_api.subscriber.unregister_listen_address(
             publisher.get_uri()
         )
         self.db_store.delete_publisher(uuid)
示例#31
0
    def _update_security_group_rule_flows_by_addresses(self, secgroup,
                                                       secgroup_rule,
                                                       added_cidr,
                                                       removed_cidr):
        conj_id, priority = self._get_secgroup_conj_id_and_priority(secgroup)
        if conj_id is None:
            LOG.error(_LE("the conj_id of the security group (%s) is none"),
                      secgroup)
            return

        parser = self.get_datapath().ofproto_parser
        ofproto = self.get_datapath().ofproto
        rule_id = self._get_security_rule_mapping(secgroup_rule.get_id())

        match_list = \
            self._get_rule_flows_match_except_net_addresses(secgroup_rule)

        if secgroup_rule.get_ethertype() == n_const.IPv4:
            if secgroup_rule.get_direction() == 'ingress':
                table_id = const.INGRESS_SECURITY_GROUP_TABLE
                ipv4_match_item = "ipv4_src"
            else:
                table_id = const.EGRESS_SECURITY_GROUP_TABLE
                ipv4_match_item = "ipv4_dst"
        elif secgroup_rule.get_ethertype() == n_const.IPv6:
            # not support yet
            LOG.info(_LI("IPv6 rules are not supported yet"))
            return
        else:
            LOG.error(_LE("wrong ethernet type"))
            return

        actions = [
            parser.NXActionConjunction(clause=1, n_clauses=2, id_=conj_id)
        ]
        action_inst = self.get_datapath(). \
            ofproto_parser.OFPInstructionActions(
            ofproto.OFPIT_APPLY_ACTIONS, actions)
        inst = [action_inst]

        for added_cidr_item in added_cidr:
            for match_item in match_list:
                parameters_merge = match_item.copy()
                parameters_merge[ipv4_match_item] = \
                    SGApp._get_network_and_mask(added_cidr_item)
                match = parser.OFPMatch(**parameters_merge)
                self.mod_flow(self.get_datapath(),
                              cookie=SGApp._get_rule_cookie(rule_id),
                              cookie_mask=COOKIE_FULLMASK,
                              inst=inst,
                              table_id=table_id,
                              priority=priority,
                              match=match)

        for removed_cidr_item in removed_cidr:
            for match_item in match_list:
                parameters_merge = match_item.copy()
                parameters_merge[ipv4_match_item] = \
                    SGApp._get_network_and_mask(removed_cidr_item)
                match = parser.OFPMatch(**parameters_merge)
                self.mod_flow(datapath=self.get_datapath(),
                              table_id=table_id,
                              priority=priority,
                              match=match,
                              command=ofproto.OFPFC_DELETE_STRICT,
                              out_port=ofproto.OFPP_ANY,
                              out_group=ofproto.OFPG_ANY)
示例#32
0
    def _install_security_group_rule_flows(self, secgroup, secgroup_rule):
        conj_id, priority = self._get_secgroup_conj_id_and_priority(secgroup)
        if conj_id is None:
            LOG.error(_LE("the conj_id of the security group %s is none"),
                      secgroup)
            return

        parser = self.get_datapath().ofproto_parser
        ofproto = self.get_datapath().ofproto
        rule_id = self._get_security_rule_mapping(secgroup_rule.get_id())
        remote_group_id = secgroup_rule.get_remote_group_id()
        remote_ip_prefix = secgroup_rule.get_remote_ip_prefix()
        ethertype = secgroup_rule.get_ethertype()

        if secgroup_rule.get_direction() == 'ingress':
            table_id = const.INGRESS_SECURITY_GROUP_TABLE
            ipv4_match_item = "ipv4_src"
        else:
            table_id = const.EGRESS_SECURITY_GROUP_TABLE
            ipv4_match_item = "ipv4_dst"

        match_list = \
            self._get_rule_flows_match_except_net_addresses(secgroup_rule)

        actions = [
            parser.NXActionConjunction(clause=1, n_clauses=2, id_=conj_id)
        ]
        action_inst = self.get_datapath(). \
            ofproto_parser.OFPInstructionActions(
            ofproto.OFPIT_APPLY_ACTIONS, actions)
        inst = [action_inst]

        if ethertype == n_const.IPv4:
            addresses_list = [{}]
            if remote_group_id is not None:
                aggregate_addresses_range = \
                    self.secgroup_aggregate_addresses.get(remote_group_id)
                addresses_list = []
                if aggregate_addresses_range is not None:
                    cidr_list = aggregate_addresses_range.iter_cidrs()
                    for aggregate_address in cidr_list:
                        addresses_list.append({
                            ipv4_match_item:
                            SGApp._get_network_and_mask(aggregate_address)
                        })
            elif remote_ip_prefix is not None:
                addresses_list = [{
                    ipv4_match_item:
                    SGApp._get_network_and_mask(remote_ip_prefix)
                }]

            for address_item in addresses_list:
                for match_item in match_list:
                    parameters_merge = match_item.copy()
                    parameters_merge.update(address_item)
                    match = parser.OFPMatch(**parameters_merge)
                    self.mod_flow(self.get_datapath(),
                                  cookie=SGApp._get_rule_cookie(rule_id),
                                  cookie_mask=COOKIE_FULLMASK,
                                  inst=inst,
                                  table_id=table_id,
                                  priority=priority,
                                  match=match)
        elif ethertype == n_const.IPv6:
            # not support yet
            LOG.info(_LI("IPv6 rules are not supported yet"))
        else:
            LOG.error(_LE("wrong ethernet type"))
示例#33
0
 def register_topic(self, topic):
     LOG.info(_LI('Register topic %s'), topic)
     if topic not in self.topic_list:
         self.topic_list.append(topic)
         return True
     return False
示例#34
0
 def unregister_topic(self, topic):
     LOG.info(_LI('Unregister topic %s'), topic)
     self.topic_list.remove(topic)
示例#35
0
    def test_default_flows(self):
        found_ingress_skip_flow = False
        found_egress_skip_flow = False
        found_ingress_default_drop_flow = False
        found_egress_default_drop_flow = False
        found_ingress_conntrack_established_pass_flow = False
        found_egress_conntrack_established_pass_flow = False
        found_ingress_conntrack_relative_not_new_pass_flow = False
        found_egress_conntrack_relative_not_new_pass_flow = False
        found_ingress_conntrack_relative_new_pass_flow = False
        found_egress_conntrack_relative_new_pass_flow = False
        found_ingress_conntrack_invalied_drop_flow = False
        found_egress_conntrack_invalied_drop_flow = False

        ovs = utils.OvsFlowsParser()
        flows = ovs.dump(self.integration_bridge)
        for flow in flows:
            if self._is_skip_flow(flow=flow, direction='ingress'):
                found_ingress_skip_flow = True
            elif self._is_skip_flow(flow=flow, direction='egress'):
                found_egress_skip_flow = True
            elif self._is_default_drop_flow(flow=flow, direction='ingress'):
                found_ingress_default_drop_flow = True
            elif self._is_default_drop_flow(flow=flow, direction='egress'):
                found_egress_default_drop_flow = True
            elif self._is_conntrack_established_pass_flow(flow=flow,
                                                          direction='ingress'):
                found_ingress_conntrack_established_pass_flow = True
            elif self._is_conntrack_established_pass_flow(flow=flow,
                                                          direction='egress'):
                found_egress_conntrack_established_pass_flow = True
            elif self._is_conntrack_relative_not_new_pass_flow(
                    flow=flow, direction='ingress'):
                found_ingress_conntrack_relative_not_new_pass_flow = True
            elif self._is_conntrack_relative_not_new_pass_flow(
                    flow=flow, direction='egress'):
                found_egress_conntrack_relative_not_new_pass_flow = True
            elif self._is_conntrack_relative_new_pass_flow(
                    flow=flow, direction='ingress'):
                found_ingress_conntrack_relative_new_pass_flow = True
            elif self._is_conntrack_relative_new_pass_flow(flow=flow,
                                                           direction='egress'):
                found_egress_conntrack_relative_new_pass_flow = True
            elif self._is_conntrack_invalid_drop_flow(flow=flow,
                                                      direction='ingress'):
                found_ingress_conntrack_invalied_drop_flow = True
            elif self._is_conntrack_invalid_drop_flow(flow=flow,
                                                      direction='egress'):
                found_egress_conntrack_invalied_drop_flow = True

        LOG.info(_LI("default flows are: %s"),
                 ovs.get_ovs_flows(self.integration_bridge))

        self.assertTrue(found_ingress_skip_flow)
        self.assertTrue(found_egress_skip_flow)
        self.assertTrue(found_ingress_default_drop_flow)
        self.assertTrue(found_egress_default_drop_flow)
        self.assertTrue(found_ingress_conntrack_established_pass_flow)
        self.assertTrue(found_egress_conntrack_established_pass_flow)
        self.assertTrue(found_ingress_conntrack_relative_not_new_pass_flow)
        self.assertTrue(found_egress_conntrack_relative_not_new_pass_flow)
        self.assertTrue(found_ingress_conntrack_relative_new_pass_flow)
        self.assertTrue(found_egress_conntrack_relative_new_pass_flow)
        self.assertTrue(found_ingress_conntrack_invalied_drop_flow)
        self.assertTrue(found_egress_conntrack_invalied_drop_flow)
示例#36
0
 def register_notification_callback(self, controller):
     self.controller = controller
     LOG.info(_LI("DB configuration sync finished, waiting for changes"))
     if not self.use_pubsub:
         self.driver.register_notification_callback(self.db_change_callback)
     self._read_db_changes_from_queue()
示例#37
0
    def apply_db_change(self, table, key, action, value):
        # determine if the action is allowed or not
        if action not in DB_ACTION_LIST:
            LOG.warning(
                _LW('Unknown action %(action)s for table '
                    '%(table)s'), {
                        'action': action,
                        'table': table
                    })
            return

        if action == 'sync':
            self.controller.run_sync()
            return
        elif action == 'dbrestart':
            self.db_recover_callback()
            return

        if 'secgroup' == table:
            if action == 'set' or action == 'create':
                secgroup = SecurityGroup(value)
                self.controller.security_group_updated(secgroup)
            elif action == 'delete':
                secgroup_id = key
                self.controller.security_group_deleted(secgroup_id)
        elif 'lport' == table:
            if action == 'create':
                lport = LogicalPort(value)
                self.controller.logical_port_created(lport)
            elif action == 'set':
                lport = LogicalPort(value)
                self.controller.logical_port_updated(lport)
            elif action == 'delete':
                lport_id = key
                self.controller.logical_port_deleted(lport_id)
        elif 'lrouter' == table:
            if action == 'set' or action == 'create':
                lrouter = LogicalRouter(value)
                self.controller.router_updated(lrouter)
            elif action == 'delete':
                lrouter_id = key
                self.controller.router_deleted(lrouter_id)
        elif 'chassis' == table:
            if action == 'set' or action == 'create':
                chassis = Chassis(value)
                self.controller.chassis_created(chassis)
            elif action == 'delete':
                chassis_id = key
                self.controller.chassis_deleted(chassis_id)
        elif 'lswitch' == table:
            if action == 'set' or action == 'create':
                lswitch = LogicalSwitch(value)
                self.controller.logical_switch_updated(lswitch)
            elif action == 'delete':
                lswitch_id = key
                self.controller.logical_switch_deleted(lswitch_id)
        elif 'floatingip' == table:
            if action == 'set' or action == 'create':
                floatingip = Floatingip(value)
                self.controller.floatingip_updated(floatingip)
            elif action == 'delete':
                floatingip_id = key
                self.controller.floatingip_deleted(floatingip_id)
        elif pub_sub_api.PUBLISHER_TABLE == table:
            if action == 'set' or action == 'create':
                publisher = Publisher(value)
                self.controller.publisher_updated(publisher)
            elif action == 'delete':
                self.controller.publisher_deleted(key)
        elif 'ovsinterface' == table:
            if action == 'set' or action == 'create':
                ovs_port = OvsPort(value)
                self.controller.ovs_port_updated(ovs_port)
            elif action == 'sync_finished':
                self.controller.ovs_sync_finished()
            elif action == 'sync_started':
                self.controller.ovs_sync_started()
            elif action == 'delete':
                ovs_port_id = key
                self.controller.ovs_port_deleted(ovs_port_id)
        elif 'log' == action:
            message = _LI('Log event (Info): '
                          'table: %(table)s '
                          'key: %(key)s '
                          'action: %(action)s '
                          'value: %(value)s')
            LOG.info(
                message, {
                    'table': str(table),
                    'key': str(key),
                    'action': str(action),
                    'value': str(value),
                })
        else:
            LOG.warning(_LW('Unknown table %s'), table)
示例#38
0
    def test_associating_flows(self):

        network = self.store(objects.NetworkTestObj(self.neutron, self.nb_api))
        network_id = network.create(network={'name': 'test_network1'})
        self.assertTrue(network.exists())

        subnet_info = {
            'network_id': network_id,
            'cidr': '192.168.123.0/24',
            'gateway_ip': '192.168.123.1',
            'ip_version': 4,
            'name': 'test_subnet1',
            'enable_dhcp': True
        }
        subnet = self.store(
            objects.SubnetTestObj(self.neutron,
                                  self.nb_api,
                                  network_id=network_id))
        subnet.create(subnet_info)
        self.assertTrue(subnet.exists())

        security_group = self.store(
            objects.SecGroupTestObj(self.neutron, self.nb_api))
        security_group_id = security_group.create()
        self.assertTrue(security_group.exists())

        vm = self.store(objects.VMTestObj(self, self.neutron))
        vm.create(network=network, security_groups=[security_group_id])

        addresses = vm.server.addresses['test_network1']
        self.assertIsNotNone(addresses)
        ip = addresses[0]['addr']
        self.assertIsNotNone(ip)
        mac = addresses[0]['OS-EXT-IPS-MAC:mac_addr']
        self.assertIsNotNone(mac)
        port = utils.wait_until_is_and_return(
            lambda: self._get_vm_port(ip, mac),
            exception=Exception('No port assigned to VM'))
        tunnel_key = port.get_tunnel_key()
        tunnel_key_hex = hex(tunnel_key)

        of_port = self._get_of_port(port.get_id())
        self.assertIsNotNone(of_port)

        ovs = utils.OvsFlowsParser()
        flows_after_change = ovs.dump(self.integration_bridge)

        # Check if the associating flows were installed.
        ingress_associating_flow, egress_associating_flow = \
            self._find_associating_flows(flows_after_change, of_port,
                                         tunnel_key_hex)

        LOG.info(
            _LI("flows after associating a port and a security group"
                " are: %s"), ovs.get_ovs_flows(self.integration_bridge))

        self.assertIsNotNone(ingress_associating_flow)
        self.assertIsNotNone(egress_associating_flow)

        vm.close()

        time.sleep(utils.DEFAULT_CMD_TIMEOUT)
        flows_after_update = ovs.dump(self.integration_bridge)

        # Check if the associating flows were removed.
        ingress_associating_flow, egress_associating_flow = \
            self._find_associating_flows(flows_after_update, of_port,
                                         tunnel_key_hex)

        self.assertIsNone(ingress_associating_flow)
        self.assertIsNone(egress_associating_flow)
示例#39
0
    def test_rule_flows(self):

        network = self.store(objects.NetworkTestObj(self.neutron, self.nb_api))
        network_id = network.create(network={'name': 'test_network2'})
        self.assertTrue(network.exists())

        subnet_info = {
            'network_id': network_id,
            'cidr': '192.168.124.0/24',
            'gateway_ip': '192.168.124.1',
            'ip_version': 4,
            'name': 'test_subnet4',
            'enable_dhcp': True
        }
        subnet = self.store(
            objects.SubnetTestObj(self.neutron,
                                  self.nb_api,
                                  network_id=network_id))
        subnet.create(subnet_info)

        security_group = self.store(
            objects.SecGroupTestObj(self.neutron, self.nb_api))
        security_group_id = security_group.create()
        self.assertTrue(security_group.exists())

        ingress_rule_info = {
            'ethertype': 'IPv4',
            'direction': 'ingress',
            'protocol': 'tcp',
            'port_range_min': '8000',
            'port_range_max': '8100',
            'remote_ip_prefix': '192.168.124.0/24'
        }
        ingress_rule_id = security_group.rule_create(secrule=ingress_rule_info)
        self.assertTrue(security_group.rule_exists(ingress_rule_id))

        egress_rule_info = {
            'ethertype': 'IPv4',
            'direction': 'egress',
            'protocol': '17',
            'port_range_min': '53',
            'port_range_max': '53',
            'remote_group_id': security_group_id
        }
        egress_rule_id = security_group.rule_create(secrule=egress_rule_info)
        self.assertTrue(security_group.rule_exists(egress_rule_id))

        vm = self.store(objects.VMTestObj(self, self.neutron))
        vm.create(network=network, security_groups=[security_group_id])

        time.sleep(utils.DEFAULT_CMD_TIMEOUT)

        ovs = utils.OvsFlowsParser()
        flows_after_change = ovs.dump(self.integration_bridge)

        LOG.info(_LI("flows after adding rules are: %s"),
                 ovs.get_ovs_flows(self.integration_bridge))

        # Check if the rule flows were installed.
        self._check_rule_flows(flows_after_change, True)

        vm.close()
示例#40
0
 def __call__(self, policy, rule, port_thread, buf):
     pkt = ryu.lib.packet.packet.Packet(buf)
     LOG.info(_LI('LogAction: Got packet: {}').format(str(pkt)))
示例#41
0
 def _disassociate_floatingip(self, floatingip):
     self.db_store.delete_floatingip(floatingip.get_id())
     self.open_flow_app.notify_disassociate_floatingip(floatingip)
     LOG.info(
         _LI("Floatingip is disassociated from port."
             " Floatingip = %s") % str(floatingip))
示例#42
0
    def _add_new_router_port(self, router, router_port):
        LOG.info(_LI("Adding new logical router interface = %s"),
                 router_port)
        local_network_id = self.db_store.get_network_id(
            router_port.get_lswitch_id()
        )
        datapath = self.get_datapath()
        if datapath is None:
            return

        parser = datapath.ofproto_parser
        ofproto = datapath.ofproto

        mac = router_port.get_mac()
        tunnel_key = router_port.get_tunnel_key()
        dst_ip = router_port.get_ip()

        # Add router ARP & ICMP responder for IPv4 Addresses
        is_ipv4 = netaddr.IPAddress(dst_ip).version == 4
        if is_ipv4:
            arp_responder.ArpResponder(
                self, local_network_id, dst_ip, mac).add()
            icmp_responder.ICMPResponder(self, dst_ip, mac).add()

        # If router interface IP, send to output table
        if is_ipv4:
            match = parser.OFPMatch(eth_type=ether.ETH_TYPE_IP,
                                    metadata=local_network_id,
                                    ipv4_dst=dst_ip)
        else:
            match = parser.OFPMatch(eth_type=ether.ETH_TYPE_IPV6,
                                    metadata=local_network_id,
                                    ipv6_dst=dst_ip)

        actions = []
        actions.append(parser.OFPActionSetField(reg7=tunnel_key))
        action_inst = self.get_datapath().ofproto_parser.OFPInstructionActions(
            ofproto.OFPIT_APPLY_ACTIONS, actions)
        goto_inst = parser.OFPInstructionGotoTable(const.EGRESS_TABLE)
        inst = [action_inst, goto_inst]
        self.mod_flow(
            datapath,
            inst=inst,
            table_id=const.L3_LOOKUP_TABLE,
            priority=const.PRIORITY_HIGH,
            match=match)

        #add dst_mac=gw_mac l2 goto l3 flow
        match = parser.OFPMatch()
        match.set_metadata(local_network_id)
        match.set_dl_dst(haddr_to_bin(mac))
        goto_inst = parser.OFPInstructionGotoTable(const.L3_LOOKUP_TABLE)
        inst = [goto_inst]
        self.mod_flow(
            self.get_datapath(),
            inst=inst,
            table_id=const.L2_LOOKUP_TABLE,
            priority=const.PRIORITY_HIGH,
            match=match)

        # Match all possible routeable traffic and send to controller
        for port in router.get_ports():
            if port.get_id() != router_port.get_id():
                # From this router interface to all other interfaces
                self._add_subnet_send_to_controller(local_network_id,
                                                    port.get_cidr_network(),
                                                    port.get_cidr_netmask(),
                                                    port.get_tunnel_key())

                # From all the other interfaces to this new interface
                router_port_net_id = self.db_store.get_network_id(
                    port.get_lswitch_id(),
                )
                self._add_subnet_send_to_controller(
                    router_port_net_id,
                    router_port.get_cidr_network(),
                    router_port.get_cidr_netmask(),
                    tunnel_key)
示例#43
0
 def publisher_updated(self, publisher):
     self.db_store.update_publisher(publisher.get_id(), publisher)
     LOG.info(_LI('Registering to new publisher: %s'), str(publisher))
     self.nb_api.subscriber.register_listen_address(publisher.get_uri())
示例#44
0
 def db_change_callback(self, table, key, action, value, topic=None):
     update = DbUpdate(table, key, action, value, topic=topic)
     LOG.info(_LI("Pushing Update to Queue: %s"), update)
     self._queue.put(update)
     eventlet.sleep(0)
示例#45
0
 def _add_new_security_group_rule(self, secgroup, secgroup_rule):
     LOG.info(_LI("Adding new secgroup rule = %s") % secgroup_rule)
     self.open_flow_app.notify_add_security_group_rule(
         secgroup, secgroup_rule)
示例#46
0
 def _delete_security_group_rule(self, secgroup, secgroup_rule):
     LOG.info(_LI("Removing secgroup rule = %s") % secgroup_rule)
     self.open_flow_app.notify_remove_security_group_rule(
         secgroup, secgroup_rule)
示例#47
0
    def _install_network_flows_for_vlan(self, segmentation_id,
                                        physical_network, local_network_id):
        LOG.info(_LI("Install network flows on first vlan up"))

        # L2_LOOKUP for Remote ports
        datapath = self.get_datapath()
        parser = datapath.ofproto_parser
        ofproto = datapath.ofproto
        match = parser.OFPMatch()

        addint = haddr_to_bin('00:00:00:00:00:00')
        add_mask_int = haddr_to_bin('01:00:00:00:00:00')
        match.set_dl_dst_masked(addint, add_mask_int)
        match.set_metadata(local_network_id)
        inst = [parser.OFPInstructionGotoTable(const.EGRESS_TABLE)]
        self.mod_flow(datapath=datapath,
                      inst=inst,
                      table_id=const.L2_LOOKUP_TABLE,
                      priority=const.PRIORITY_MEDIUM,
                      match=match)

        # EGRESS for Remote ports
        # Table=Egress
        # Match: metadata=network_id
        # Actions: mod_vlan, output:patch
        match = parser.OFPMatch(metadata=local_network_id)
        actions = [
            parser.OFPActionPushVlan(ether.ETH_TYPE_8021Q),
            parser.OFPActionSetField(vlan_vid=(segmentation_id & 0x1fff)
                                     | 0x1000)
        ]

        action_inst = parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                                   actions)
        goto_inst = parser.OFPInstructionGotoTable(const.EGRESS_EXTERNAL_TABLE)
        inst = [action_inst, goto_inst]
        self.mod_flow(datapath=datapath,
                      inst=inst,
                      table_id=const.EGRESS_TABLE,
                      priority=const.PRIORITY_LOW,
                      match=match)

        # Add EGRESS port according to physical_network
        self._install_output_to_physical_patch(physical_network,
                                               local_network_id)

        # Ingress
        # Match: dl_vlan=vlan_id,
        # Actions: metadata=network_id,
        # goto 'Destination Port Classification'
        match = parser.OFPMatch()
        match.set_vlan_vid(segmentation_id)
        actions = [
            parser.OFPActionSetField(metadata=local_network_id),
            parser.OFPActionPopVlan()
        ]

        action_inst = parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS,
                                                   actions)

        goto_inst = parser.OFPInstructionGotoTable(
            const.INGRESS_DESTINATION_PORT_LOOKUP_TABLE)

        inst = [action_inst, goto_inst]
        self.mod_flow(datapath=datapath,
                      inst=inst,
                      table_id=const.INGRESS_CLASSIFICATION_DISPATCH_TABLE,
                      priority=const.PRIORITY_LOW,
                      match=match)
示例#48
0
    def _logical_port_process(self, lport, original_lport=None):
        chassis = lport.get_chassis()
        local_network_id = self.get_network_id(lport.get_lswitch_id(), )
        lswitch = self.db_store.get_lswitch(lport.get_lswitch_id())
        if lswitch is not None:
            network_type = lswitch.get_network_type()
            segment_id = lswitch.get_segment_id()
            physical_network = lswitch.get_physical_network()

            lport.set_external_value('network_type', network_type)
            if segment_id is not None:
                lport.set_external_value('segmentation_id', int(segment_id))
            if physical_network:
                lport.set_external_value('physical_network', physical_network)

        lport.set_external_value('local_network_id', local_network_id)

        if chassis == self.chassis_name:
            lport.set_external_value('is_local', True)
            ofport = self.vswitch_api.get_port_ofport_by_id(lport.get_id())
            if ofport:
                lport.set_external_value('ofport', ofport)
                self.db_store.set_port(lport.get_id(), lport, True)
                if original_lport is None:
                    LOG.info(
                        _LI("Adding new local logical port = %s") % str(lport))
                    self.open_flow_app.notify_add_local_port(lport)
                else:
                    LOG.info(
                        _LI("Updating local logical port = %(port)s, "
                            "original port = %(original_port)s") % {
                                'port': str(lport),
                                'original_port': str(original_lport)
                            })
                    self.open_flow_app.notify_update_local_port(
                        lport, original_lport)
            else:
                LOG.info(
                    _LI("Local logical port %s was not created yet") %
                    str(lport))
        else:
            lport.set_external_value('is_local', False)
            ofport = self.vswitch_api.get_chassis_ofport(chassis)
            if ofport:
                lport.set_external_value('ofport', ofport)
                self.db_store.set_port(lport.get_id(), lport, False)
                if original_lport is None:
                    LOG.info(
                        _LI("Adding new remote logical port = %s") %
                        str(lport))
                    self.open_flow_app.notify_add_remote_port(lport)
                else:
                    LOG.info(
                        _LI("Updating remote logical port = %(port)s, "
                            "original port = %(original_port)s") % {
                                'port': str(lport),
                                'original_port': str(original_lport)
                            })
                    self.open_flow_app.notify_update_remote_port(
                        lport, original_lport)
            else:
                # TODO(gampel) add handling for this use case
                # remote port but no tunnel to remote Host
                # if this should never happen raise an exception
                LOG.warning(
                    _LW("No tunnel for remote logical port %s") % str(lport))
示例#49
0
 def register_topic(self, topic):
     LOG.info(_LI('Register topic %s'), topic)
     topic = topic.encode('ascii', 'ignore')
     if topic not in self.topic_list:
         self.topic_list.append(topic)
示例#50
0
 def _associate_floatingip(self, floatingip):
     self.db_store.update_floatingip(floatingip.get_id(), floatingip)
     self.open_flow_app.notify_associate_floatingip(floatingip)
     LOG.info(
         _LI("Floatingip is associated with port. Floatingip = %s") %
         str(floatingip))