示例#1
0
    def setup(self):
        """Replace the 'init' method for the KytosApp subclass.

        The setup method is automatically called by the run method.
        Users shouldn't call this method directly.
        """
        log.debug("flow-manager starting")
        self._flow_mods_sent = OrderedDict()
        self._flow_mods_sent_max_size = FLOWS_DICT_MAX_SIZE
        self.cookie_ignored_range = []
        self.tab_id_ignored_range = []
        if _valid_consistency_ignored(CONSISTENCY_COOKIE_IGNORED_RANGE):
            self.cookie_ignored_range = CONSISTENCY_COOKIE_IGNORED_RANGE
        if _valid_consistency_ignored(CONSISTENCY_TABLE_ID_IGNORED_RANGE):
            self.tab_id_ignored_range = CONSISTENCY_TABLE_ID_IGNORED_RANGE

        # Storehouse client to save and restore flow data:
        self.storehouse = StoreHouse(self.controller)

        self._storehouse_lock = Lock()

        # Format of stored flow data:
        # {'flow_persistence': {'dpid_str': {'flow_list': [
        #                                     {'command': '<add|delete>',
        #                                      'flow': {flow_dict}}]}}}
        self.stored_flows = {}
        self.resent_flows = set()
示例#2
0
def send_packet_out(controller, switch, port, data):
    """ Just prepare the PacketOut to be used by the Tracer.

    Args:
        controller: Kytos controller
        switch: OpenFlow datapath
        port: in_port
        data: Ethernet frame
    Return:
        output_action = ActionOutput
    """
    output_action = ActionOutput()
    output_action.port = settings.OFPP_TABLE

    packet_out = PacketOut()
    packet_out.actions.append(output_action)
    packet_out.in_port = port
    packet_out.data = bytes(data)

    event_out = KytosEvent()
    event_out.name = 'kytos/of_lldp.messages.out.ofpt_packet_out'
    event_out.content = {
        'destination': switch.connection,
        'message': packet_out
    }

    log.debug('PacketOut %s sent' % event_out.content)
    controller.buffers.msg_out.put(event_out)
示例#3
0
文件: main.py 项目: macartur/of_core
    def update_port_status(self, port_status, source):
        """Dispatch 'port.*' events.

        Current events:

        created|deleted|up|down|link_up|link_down|modified

        Args:
            port_status: python openflow (pyof) PortStatus object.
            source: kytos.core.switch.Connection instance.

        Dispatch:
            `kytos/of_core.switch.port.[created|modified|deleted]`:
                {
                  switch : <switch.id>,
                  port: <port.port_no>
                  port_description: {<description of the port>}
                }

        """
        reason = port_status.reason.enum_ref(port_status.reason.value).name
        port = port_status.desc
        event_name = 'kytos/of_core.switch.interface.'

        if reason == 'OFPPR_ADD':
            status = 'created'
            interface = Interface(name=port.name.value,
                                  address=port.hw_addr.value,
                                  port_number=port.port_no.value,
                                  switch=source.switch,
                                  state=port.state.value,
                                  features=port.curr)
            source.switch.update_interface(interface)

        elif reason == 'OFPPR_MODIFY':
            status = 'modified'
            interface = Interface(name=port.name.value,
                                  address=port.hw_addr.value,
                                  port_number=port.port_no.value,
                                  switch=source.switch,
                                  state=port.state.value,
                                  features=port.curr)
            source.switch.update_interface(interface)

            self._send_specific_port_mod(port, interface)

        elif reason == 'OFPPR_DELETE':
            status = 'deleted'
            interface = source.switch.get_interface_by_port_no(
                port.port_no.value)
            source.switch.remove_interface(interface)

        event_name += status
        content = {'interface': interface}

        event = KytosEvent(name=event_name, content=content)
        self.controller.buffers.app.put(event)

        msg = 'The port %s from switch %s was %s.'
        log.debug(msg, port_status.desc.port_no, source.switch.id, status)
示例#4
0
    def update_port_status(self, event):
        """Dispatch 'port.[created|modified|deleted]' event.

        Listen:
            `kytos/of_core.v0x0[14].messages.in.ofpt_port_status`

        Dispatch:
            `kytos/of_topology.switch.port.[created|modified|deleted]`:
                { switch : <switch.id>,
                  port: <port.port_no>
                  port_description: {<description of the port>}
                }

        """
        port_status = event.message
        reason = port_status.reason.value

        name = 'kytos/of_topology.switch.port.' + reason.lower()
        content = {
            'switch': event.source.id,
            'port': port_status.desc.port_no,
            'port_description': vars(port_status.desc)
        }

        event = KytosEvent(name=name, content=content)
        self.controller.buffers.app.put(event)

        msg = 'The port %s (%s) from switch %s was %s.'
        log.debug(msg, port_status.desc.port_no, event.source.id, reason)
示例#5
0
def packet_in(event, packet_in_msg):
    """ Process OpenFlow 1.0 PacketIn messages

    Args:
        event: PacketIN event
        packet_in_msg: PacketIn msg
    Return:
        ethernet: PacketIn data
        in_port: in_port
        switch: OpenFlow datapath
        0, 0, 0 if it is not a trace probe
    """

    ethernet = Ethernet()
    ethernet.unpack(packet_in_msg.data.value)

    if settings.COLOR_VALUE in ethernet.source.value:
        log.debug("OpenFlow 1.0 PacketIn Trace Msg Received")

        in_port = packet_in_msg.in_port.value
        switch = event.source.switch
        return ethernet, in_port, switch

    log.debug("PacketIn is not a Data Trace Probe")
    return 0, 0, 0
示例#6
0
    def update_links(self, event):
        """Dispatch 'reacheable.mac' event.

        Listen:
            `kytos/of_core.v0x0[14].messages.in.ofpt_packet_in`

        Dispatch:
            `reachable.mac`:
                { switch : <switch.id>,
                  port: <port.port_no>
                  reachable_mac: <mac_address>
                }

        """
        ethernet = Ethernet()
        ethernet.unpack(event.message.data.value)

        name = 'kytos/of_topology.reachable.mac'
        content = {
            'switch': event.source.switch.id,
            'port': event.message.in_port,
            'reachable_mac': ethernet.source
        }
        event = KytosEvent(name, content)
        self.controller.buffers.app.put(event)

        msg = 'The MAC %s is reachable from switch/port %s/%s.'
        log.debug(msg, ethernet.source, event.source.switch.id,
                  event.message.in_port)
示例#7
0
    def install_table_miss_flow(self, event):
        """Install the TableMiss Flow in OF1.3 switches.

        This is needed because those drop packets by default.
        """
        dpid = event.content['dpid']
        switch = self.controller.get_switch_by_dpid(dpid)

        try:
            version = switch.connection.protocol.version
        except AttributeError:
            version = None
            log.debug(f'The OpenFlow version was not found for switch {dpid}.')

        if version != 0x04:
            return

        flow = {}
        flow['priority'] = 0
        flow['table_id'] = settings.TABLE_ID
        flow['actions'] = [{
            'action_type': 'output',
            'port': Port13.OFPP_CONTROLLER
        }]

        destination = switch.id
        endpoint = f'{settings.FLOW_MANAGER_URL}/flows/{destination}'
        data = {'flows': [flow]}

        requests.post(endpoint, json=data)
示例#8
0
def send_packet_out(controller, switch, port, data):
    """ Just prepare the PacketOut to be used by the Tracer.

    Args:
        controller: Kytos controller
        switch: OpenFlow datapath
        port: in_port
        data: Ethernet frame
    Return:
        output_action = ActionOutput
    """
    output_action = ActionOutput()
    output_action.port = settings.OFPP_TABLE

    packet_out = PacketOut()
    packet_out.actions.append(output_action)
    packet_out.in_port = port
    packet_out.data = bytes(data)

    event_out = KytosEvent()
    event_out.name = 'kytos/of_lldp.messages.out.ofpt_packet_out'
    event_out.content = {'destination': switch.connection,
                         'message': packet_out}

    log.debug('PacketOut %s sent' % event_out.content)
    controller.buffers.msg_out.put(event_out)
示例#9
0
    def _create_box_callback(self, _event, data, error):
        """Execute the callback to handle create_box."""
        if error:
            log.error(f"Can't create box with namespace {self.namespace}")

        self.box = data
        log.debug(f"Box {self.box.box_id} was created in {self.namespace}.")
示例#10
0
    def _get_box_callback(self, _event, data, error):
        """Handle get_box method saving the box or logging with the error."""
        if error:
            log.error(f'Box {data.box_id} not found in {self.namespace}.')

        self.box = data
        log.debug(f'Box {self.box.box_id} was load from storehouse.')
示例#11
0
 def handle_link_down(self, event):
     """Change circuit when link is down or under_mantenance."""
     log.debug("Event handle_link_down %s", event)
     for evc in self.circuits.values():
         if evc.is_affected_by_link(event.content['link']):
             log.info('handling evc %s' % evc)
             evc.handle_link_down()
示例#12
0
    def load_evcs(self, event):
        """Try to load the unloaded EVCs from storehouse."""
        with self._lock:
            log.debug("Event load_evcs %s", event)
            circuits = self.storehouse.get_data()
            if not self._circuits_by_interface:
                self.load_circuits_by_interface(circuits)

            interface_id = '{}:{}'.format(event.content['switch'],
                                          event.content['port'])

            for circuit_id in self._circuits_by_interface.get(
                    interface_id, []):
                if circuit_id in circuits and circuit_id not in self.circuits:
                    try:
                        evc = self._evc_from_dict(circuits[circuit_id])
                    except ValueError as exception:
                        log.error(f'Could not load EVC {circuit_id} '
                                  f'because {exception}')
                        continue

                    evc.deactivate()
                    evc.current_path = Path([])
                    evc.sync()
                    self.circuits.setdefault(circuit_id, evc)
                    self.sched.add(evc)
示例#13
0
    def setup(self):
        """Replace the 'init' method for the KytosApp subclass.

        The setup method is automatically called by the run method.
        Users shouldn't call this method directly.
        """
        log.debug("flow-manager starting")
示例#14
0
    def list_schedules(self):
        """Endpoint to return all schedules stored for all circuits.

        Return a JSON with the following template:
        [{"schedule_id": <schedule_id>,
         "circuit_id": <circuit_id>,
         "schedule": <schedule object>}]
        """
        log.debug('list_schedules /v2/evc/schedule')
        circuits = self.storehouse.get_data().values()
        if not circuits:
            result = {}
            status = 200
            return jsonify(result), status

        result = []
        status = 200
        for circuit in circuits:
            circuit_scheduler = circuit.get("circuit_scheduler")
            if circuit_scheduler:
                for scheduler in circuit_scheduler:
                    value = {
                        "schedule_id": scheduler.get("id"),
                        "circuit_id": circuit.get("id"),
                        "schedule": scheduler
                    }
                    result.append(value)

        log.debug('list_schedules result %s %s', result, status)
        return jsonify(result), status
示例#15
0
    def handle_packet_in(self, event):
        """Handle PacketIn Event.

        Install flows allowing communication between switch ports.

        Args:
            event (KytosPacketIn): Received Event
        """
        log.debug("PacketIn Received")

        packet_in = event.content['message']

        ethernet = Ethernet()
        ethernet.unpack(packet_in.data.value)

        # Ignore LLDP packets or packets not generated by table-miss flows
        if (ethernet.destination in settings.lldp_macs
                or packet_in.reason != PacketInReason.OFPR_NO_MATCH):
            return

        # Learn the port where the sender is connected
        in_port = packet_in.in_port.value
        switch = event.source.switch
        switch.update_mac_table(ethernet.source, in_port)

        ports = switch.where_is_mac(ethernet.destination)

        # Add a flow to the switch if the destination is known
        if ports:
            flow_mod = FlowMod()
            flow_mod.command = FlowModCommand.OFPFC_ADD
            flow_mod.match = Match()
            flow_mod.match.dl_src = ethernet.source.value
            flow_mod.match.dl_dst = ethernet.destination.value
            flow_mod.match.dl_type = ethernet.ether_type
            flow_mod.actions.append(ActionOutput(port=ports[0]))
            event_out = KytosEvent(name=('kytos/of_l2ls.messages.out.'
                                         'ofpt_flow_mod'),
                                   content={
                                       'destination': event.source,
                                       'message': flow_mod
                                   })
            self.controller.buffers.msg_out.put(event_out)

        # Send the packet to correct destination or flood it
        packet_out = PacketOut()
        packet_out.buffer_id = packet_in.buffer_id
        packet_out.in_port = packet_in.in_port
        packet_out.data = packet_in.data

        port = ports[0] if ports else Port.OFPP_FLOOD
        packet_out.actions.append(ActionOutput(port=port))
        event_out = KytosEvent(name=('kytos/of_l2ls.messages.out.'
                                     'ofpt_packet_out'),
                               content={
                                   'destination': event.source,
                                   'message': packet_out
                               })

        self.controller.buffers.msg_out.put(event_out)
示例#16
0
    def handle_link_down(self):
        """Handle circuit when link down.

        Returns:
            bool: True if the re-deploy was successly otherwise False.

        """
        success = False
        if self.is_using_primary_path():
            success = self.deploy_to_backup_path()
        elif self.is_using_backup_path():
            success = self.deploy_to_primary_path()

        if not success and self.dynamic_backup_path:
            success = self.deploy_to_path()

        if success:
            log.debug(f"{self} deployed after link down.")
        else:
            self.deactivate()
            self.current_path = Path([])
            self.sync()
            log.debug(f'Failed to re-deploy {self} after link down.')

        return success
示例#17
0
文件: stats.py 项目: diraol/of_stats
 def request(self, conn):
     """Ask for switch description. It is done only once per switch."""
     dpid = conn.switch.dpid
     if dpid not in self._desc:
         req = StatsRequest(body_type=StatsTypes.OFPST_DESC)
         self._send_event(req, conn)
         log.debug('Desc request for switch %s sent.', dpid)
示例#18
0
 def request(self, conn):
     """Ask for flow stats."""
     body = AggregateStatsRequest()  # Port.OFPP_NONE and All Tables
     req = StatsRequest(body_type=StatsType.OFPST_AGGREGATE, body=body)
     self._send_event(req, conn)
     log.debug('Aggregate Stats request for switch %s sent.',
               conn.switch.dpid)
示例#19
0
def packet_in(event, packet_in_msg):
    """ Process OpenFlow 1.0 PacketIn messages

    Args:
        event: PacketIN event
        packet_in_msg: PacketIn msg
    Return:
        ethernet: PacketIn data
        in_port: in_port
        switch: OpenFlow datapath
        0, 0, 0 if it is not a trace probe
    """

    ethernet = Ethernet()
    ethernet.unpack(packet_in_msg.data.value)

    if settings.COLOR_VALUE in ethernet.source.value:
        log.debug("OpenFlow 1.0 PacketIn Trace Msg Received")

        in_port = packet_in_msg.in_port.value
        switch = event.source.switch
        return ethernet, in_port, switch

    log.debug("PacketIn is not a Data Trace Probe")
    return 0, 0, 0
示例#20
0
    def _negotiate(self, connection, message):
        """Handle hello messages.

        This method will handle the incoming hello message by client
        and deal with negotiation.

        Parameters:
            event (KytosMessageInHello): KytosMessageInHelloEvent
        """

        if message.versions:
            version = self._get_version_from_bitmask(message.versions)
        else:
            version = self._get_version_from_header(message.header.version)

        log.debug('connection %s: negotiated version - %s',
                  connection.id, str(version))

        if version is None:
            self.fail_negotiation(connection, message)
            raise NegotiationException()

        version_utils = self.of_core_version_utils[version]
        version_utils.say_hello(self.controller, connection)

        connection.protocol.name = 'openflow'
        connection.protocol.version = version
        connection.protocol.unpack = unpack
        connection.protocol.state = 'sending_features'
        self.send_features_request(connection)
        log.debug('Connection %s: Hello complete', connection.id)
示例#21
0
 def handle_link_up(self, event):
     """Change circuit when link is up or end_maintenance."""
     log.debug("Event handle_link_up %s", event)
     for evc in self.circuits.values():
         if evc.is_enabled() and not evc.archived:
             with evc.lock:
                 evc.handle_link_up(event.content["link"])
示例#22
0
文件: main.py 项目: macartur/topology
 def update_instance(self, event, data, error):
     """Display in Kytos console if the data was updated."""
     entities = event.content.get('namespace', '').split('.')[-2]
     if error:
         log.error(f'Error trying to update storehouse {entities}.')
     else:
         log.debug(f'Storehouse update to entities: {entities}.')
示例#23
0
    def load_evcs(self, event):
        """Try to load the unloaded EVCs from storehouse."""
        log.debug("Event load_evcs %s", event)
        circuits = self.storehouse.get_data()
        if not self._circuits_by_interface:
            self.load_circuits_by_interface(circuits)

        interface_id = '{}:{}'.format(event.content['switch'],
                                      event.content['port'])

        for circuit_id in self._circuits_by_interface.get(interface_id, []):
            if circuit_id in circuits and circuit_id not in self.circuits:
                try:
                    evc = self._evc_from_dict(circuits[circuit_id])
                except ValueError as exception:
                    log.info(
                        f'Could not load EVC {circuit_id} because {exception}')
                    continue
                log.info(f'Loading EVC {circuit_id}')
                if evc.archived:
                    continue
                new_evc = self.circuits.setdefault(circuit_id, evc)
                if new_evc == evc:
                    if evc.is_enabled():
                        log.info(f'Trying to deploy EVC {circuit_id}')
                        evc.deploy()
                    self.sched.add(evc)
示例#24
0
 def execute(self):
     """Execute once when the napp is running."""
     if self._lock.locked():
         return
     log.debug("Starting consistency routine")
     with self._lock:
         self.execute_consistency()
     log.debug("Finished consistency routine")
示例#25
0
文件: main.py 项目: kytos/mef_eline
 def handle_link_down(self, event):
     """Change circuit when link is down or under_mantenance."""
     log.debug("Event handle_link_down %s", event)
     for evc in self.circuits.values():
         with evc.lock:
             if evc.is_affected_by_link(event.content['link']):
                 log.debug(f'Handling evc {evc.id} on link down')
                 evc.handle_link_down()
示例#26
0
    def _save_evc_callback(self, _event, data, error):
        """Display the save EVC result in the log."""
        self._lock.release()
        log.debug(f'Lock {self._lock} released.')
        if error:
            log.error(f'Can\'t update the {self.box.box_id}')

        log.info(f'Box {data.box_id} was updated.')
示例#27
0
文件: main.py 项目: macartur/topology
 def load_from_store(self, event, box, error):
     """Save the data retrived from storehouse."""
     entities = event.content.get('namespace', '').split('.')[-2]
     if error:
         log.error('Error while get a box from storehouse.')
     else:
         self.store_items[entities] = box
         log.debug('Data updated')
示例#28
0
 def listener(self, event):
     """Store switch descriptions."""
     msg = event.content['message']
     if msg.body_type.value in self._stats:
         stats = self._stats[msg.body_type.value]
         stats.listen(event.source.switch.dpid, msg.body)
     else:
         log.debug('No listener for %s in %s.', msg.body_type.value,
                   list(self._stats.keys()))
示例#29
0
    def setup(self):
        """Replace the 'init' method for the KytosApp subclass.

        The setup method is automatically called by the run method.
        Users shouldn't call this method directly.
        """
        log.debug("flow-manager starting")
        self._flow_mods_sent = OrderedDict()
        self._flow_mods_sent_max_size = FLOWS_DICT_MAX_SIZE
示例#30
0
    def list_stored_boxes(self):
        """List all boxes using the current namespace."""
        name = 'kytos.storehouse.list'
        content = {'namespace': self.namespace,
                   'callback': self._get_or_create_a_box_from_list_of_boxes}

        event = KytosEvent(name=name, content=content)
        self.controller.buffers.app.put(event)
        log.debug(f'Bootstraping storehouse box for {self.namespace}.')
示例#31
0
文件: stats.py 项目: diraol/of_stats
 def listen(self, dpid, desc):
     """Store switch description."""
     self._desc[dpid] = desc
     switch = self.controller.get_switch_by_dpid(dpid)
     switch.update_description(desc)
     log.debug(
         'Adding switch %s: mfr_desc = %s, hw_desc = %s,'
         ' sw_desc = %s, serial_num = %s', dpid, desc.mfr_desc,
         desc.hw_desc, desc.sw_desc, desc.serial_num)
示例#32
0
    def handle_packet_in(self, event):
        """Handle PacketIn Event.

        Install flows allowing communication between switch ports.

        Args:
            event (KytosPacketIn): Received Event
        """
        log.debug("PacketIn Received")

        packet_in = event.content['message']

        ethernet = Ethernet()
        ethernet.unpack(packet_in.data.value)

        # Ignore LLDP packets or packets not generated by table-miss flows
        if (ethernet.destination in settings.LLDP_MACS
                or packet_in.reason != PacketInReason.OFPR_NO_MATCH):
            return

        switch = event.source.switch
        version = switch.ofp_version

        # Learn the port where the sender is connected
        if version == '0x01':
            in_port = packet_in.in_port.value
        else:
            in_port = packet_in.in_port

        switch.update_mac_table(ethernet.source, in_port)

        ports = switch.where_is_mac(ethernet.destination)

        # Add a flow to the switch if the destination is known
        if ports:
            flow_mod = self._create_flow_mod(version, ethernet, ports[0])

            event_out = KytosEvent(name=('kytos/of_l2ls.messages.out.'
                                         'ofpt_flow_mod'),
                                   content={
                                       'destination': event.source,
                                       'message': flow_mod
                                   })
            self.controller.buffers.msg_out.put(event_out)

        # Send the packet to correct destination or flood it
        packet_out = self._create_packet_out(version, packet_in, ports)

        event_out = KytosEvent(name=('kytos/of_l2ls.messages.out.'
                                     'ofpt_packet_out'),
                               content={
                                   'destination': event.source,
                                   'message': packet_out
                               })

        self.controller.buffers.msg_out.put(event_out)