Пример #1
0
    def __init__(self, dpid, connection=None, features=None):
        """Contructor of switches have the below parameters.

        Args:
          dpid (|DPID|): datapath_id of the switch
          connection (:class:`~.Connection`): Connection used by switch.
          features (|features_reply|): FeaturesReply instance.

        """
        self.dpid = dpid
        self.connection = connection
        self.features = features
        self.firstseen = now()
        self.lastseen = now()
        self.sent_xid = None
        self.waiting_for_reply = False
        self.request_timestamp = 0
        #: Dict associating mac addresses to switch ports.
        #:      the key of this dict is a mac_address, and the value is a set
        #:      containing the ports of this switch in which that mac can be
        #:      found.
        self.mac2port = {}
        #: This flood_table will keep track of flood packets to avoid over
        #:     flooding on the network. Its key is a hash composed by
        #:     (eth_type, mac_src, mac_dst) and the value is the timestamp of
        #:     the last flood.
        self.flood_table = {}
        self.interfaces = {}
        self.flows = []
        self.description = {}

        if connection:
            connection.switch = self

        super().__init__()
Пример #2
0
    def update_flood_table(self, ethernet_frame):
        """Update a flood table using the given ethernet frame.

        Args:
            ethernet_frame (|ethernet|): Ethernet frame to be updated.
        """
        self.flood_table[ethernet_frame.get_hash()] = now()
Пример #3
0
    def start_controller(self):
        """Start the controller.

        Starts the KytosServer (TCP Server) coroutine.
        Starts a thread for each buffer handler.
        Load the installed apps.
        """
        self.log.info("Starting Kytos - Kytos Controller")
        self.server = KytosServer((self.options.listen,
                                   int(self.options.port)),
                                  KytosServerProtocol,
                                  self,
                                  self.options.protocol_name)

        self.log.info("Starting TCP server: %s", self.server)
        self.server.serve_forever()

        def _stop_loop(_):
            loop = asyncio.get_event_loop()
            # print(_.result())
            threads = threading.enumerate()
            self.log.debug("%s threads before loop.stop: %s",
                           len(threads), threads)
            loop.stop()

        async def _run_api_server_thread(executor):
            log = logging.getLogger('controller.api_server_thread')
            log.debug('starting')
            # log.debug('creating tasks')
            loop = asyncio.get_event_loop()
            blocking_tasks = [
                loop.run_in_executor(executor, self.api_server.run)
            ]
            # log.debug('waiting for tasks')
            completed, pending = await asyncio.wait(blocking_tasks)
            # results = [t.result() for t in completed]
            # log.debug('results: {!r}'.format(results))
            log.debug('completed: %d, pending: %d',
                      len(completed), len(pending))

        task = self._loop.create_task(self.raw_event_handler())
        task = self._loop.create_task(self.msg_in_event_handler())
        task = self._loop.create_task(self.msg_out_event_handler())
        task = self._loop.create_task(self.app_event_handler())
        task = self._loop.create_task(_run_api_server_thread(self._pool))
        task.add_done_callback(_stop_loop)

        self.log.info("ThreadPool started: %s", self._pool)

        # ASYNC TODO: ensure all threads started correctly
        # This is critical, if any of them failed starting we should exit.
        # sys.exit(error_msg.format(thread, exception))

        self.log.info("Loading Kytos NApps...")
        self.napp_dir_listener.start()
        self.pre_install_napps(self.options.napps_pre_installed)
        self.load_napps()

        self.started_at = now()
Пример #4
0
    def add_endpoint(self, endpoint):
        """Create a new endpoint to Interface instance.

        Args:
            endpoint(|hw_address|, :class:`.Interface`): A target endpoint.
        """
        exists = self.get_endpoint(endpoint)
        if not exists:
            self.endpoints.append((endpoint, now()))
Пример #5
0
    def start_controller(self):
        """Start the controller.

        Starts the KytosServer (TCP Server) coroutine.
        Starts a thread for each buffer handler.
        Load the installed apps.
        """
        self.log.info("Starting Kytos - Kytos Controller")
        self.server = KytosServer(
            (self.options.listen, int(self.options.port)), KytosServerProtocol,
            self, self.options.protocol_name)

        self.log.info("Starting TCP server: %s", self.server)
        self.server.serve_forever()

        def _stop_loop(_):
            loop = asyncio.get_event_loop()
            # print(_.result())
            threads = threading.enumerate()
            self.log.debug("%s threads before loop.stop: %s", len(threads),
                           threads)
            loop.stop()

        async def _run_api_server_thread(executor):
            log = logging.getLogger('kytos.core.controller.api_server_thread')
            log.debug('starting')
            # log.debug('creating tasks')
            loop = asyncio.get_event_loop()
            blocking_tasks = [
                loop.run_in_executor(executor, self.api_server.run)
            ]
            # log.debug('waiting for tasks')
            completed, pending = await asyncio.wait(blocking_tasks)
            # results = [t.result() for t in completed]
            # log.debug('results: {!r}'.format(results))
            log.debug('completed: %d, pending: %d', len(completed),
                      len(pending))

        task = self._loop.create_task(self.raw_event_handler())
        task = self._loop.create_task(self.msg_in_event_handler())
        task = self._loop.create_task(self.msg_out_event_handler())
        task = self._loop.create_task(self.app_event_handler())
        task = self._loop.create_task(_run_api_server_thread(self._pool))
        task.add_done_callback(_stop_loop)

        self.log.info("ThreadPool started: %s", self._pool)

        # ASYNC TODO: ensure all threads started correctly
        # This is critical, if any of them failed starting we should exit.
        # sys.exit(error_msg.format(thread, exception))

        self.log.info("Loading Kytos NApps...")
        self.napp_dir_listener.start()
        self.pre_install_napps(self.options.napps_pre_installed)
        self.load_napps()

        self.started_at = now()
Пример #6
0
    def add_endpoint(self, endpoint):
        """Create a new endpoint to Interface instance.

        Args:
            endpoint(|hw_address|, :class:`.Interface`): A target endpoint.
        """
        exists = self.get_endpoint(endpoint)
        if not exists:
            self.endpoints.append((endpoint, now()))
Пример #7
0
    def __init__(self, name=None, content=None):
        """Create an event to be published.

        Args:
            name (string): The name of the event. You should prepend it with
                           the name of the napp.
            content (dict): Dictionary with any extra data for the event.
        """
        self.name = name
        self.content = content if content is not None else {}
        self.timestamp = now()
Пример #8
0
    def __init__(self, name=None, content=None):
        """Constructor of KytosEvent receive the parameters below.

        Args:
            name (string): The name of the event. You should prepend with
                           the name of the napp.
            content (dict): Dictionary with all event informations.
        """
        self.name = name
        self.content = content if content is not None else {}
        self.timestamp = now()
Пример #9
0
    def uptime(self):
        """Return the uptime of kytos server.

        This method should return:
            - 0 if Kytos Server is stopped.
            - (kytos.start_at - datetime.now) if Kytos Server is running.

        Returns:
           datetime.timedelta: The uptime interval.
        """
        return now() - self.started_at if self.started_at else 0
Пример #10
0
    def circuit_deploy(self, circuit):
        """Add a new circuit deploy event."""
        seconds = (circuit.creation_time - now()).total_seconds()

        if not circuit.is_enabled():
            log.debug(f'{circuit} is not enabled')
        if not circuit.is_active():
            log.debug(f'{circuit} is not active')
        if circuit.is_enabled() and not circuit.is_active():
            self.scheduler.enter(seconds, circuit.priority, circuit.deploy)
            log.debug(f'{circuit} scheduled to be activated.')
Пример #11
0
    def should_flood(self, ethernet_frame):
        """Verify if the ethernet frame should flood.

        Args:
            ethernet_frame (|ethernet|): Ethernet instance to be verified.
        Returns:
            bool: True if the ethernet_frame should flood.
        """
        last_flood = self.last_flood(ethernet_frame)
        diff = (now() - last_flood).microseconds

        return last_flood is None or diff > FLOOD_TIMEOUT
Пример #12
0
    def uptime(self):
        """Return the uptime of kytos server.

        This method should return:
            - 0 if Kytos Server is stopped.
            - (kytos.start_at - datetime.now) if Kytos Server is running.

        Returns:
           datetime.timedelta: The uptime interval.

        """
        return now() - self.started_at if self.started_at else 0
Пример #13
0
    def __init__(self,
                 dpid,
                 connection=None,
                 ofp_version='0x01',
                 features=None):
        """Contructor of switches have the below parameters.

        Args:
          dpid (|DPID|): datapath_id of the switch
          connection (:class:`~.Connection`): Connection used by switch.
          ofp_version (string): Current talked OpenFlow version.
          features (|features_reply|): FeaturesReply instance.

        """
        self.dpid = dpid
        self.connection = connection
        self.ofp_version = ofp_version
        self.features = features
        self.firstseen = now()
        self.lastseen = now()
        self.sent_xid = None
        self.waiting_for_reply = False
        self.request_timestamp = 0
        #: Dict associating mac addresses to switch ports.
        #:      the key of this dict is a mac_address, and the value is a set
        #:      containing the ports of this switch in which that mac can be
        #:      found.
        self.mac2port = {}
        #: This flood_table will keep track of flood packets to avoid over
        #:     flooding on the network. Its key is a hash composed by
        #:     (eth_type, mac_src, mac_dst) and the value is the timestamp of
        #:     the last flood.
        self.flood_table = {}
        self.interfaces = {}
        self.flows = []
        self.description = {}

        if connection:
            connection.switch = self
Пример #14
0
    def should_flood(self, ethernet_frame):
        """Verify if the ethernet frame should flood.

        Args:
            ethernet_frame (|ethernet|): Ethernet instance to be verified.

        Returns:
            bool: True if the ethernet_frame should flood.

        """
        last_flood = self.last_flood(ethernet_frame)
        diff = (now() - last_flood).microseconds

        return last_flood is None or diff > FLOOD_TIMEOUT
Пример #15
0
    def start_controller(self):
        """Start the controller.

        Starts a thread with the KytosServer (TCP Server).
        Starts a thread for each buffer handler.
        Load the installed apps.
        """
        self.log.info("Starting Kytos - Kytos Controller")
        self.server = KytosServer(
            (self.options.listen, int(self.options.port)), KytosRequestHandler,
            self, self.options.protocol_name)

        raw_event_handler = self.raw_event_handler
        msg_in_event_handler = self.msg_in_event_handler
        msg_out_event_handler = self.msg_out_event_handler
        app_event_handler = self.app_event_handler

        thrds = {
            'tcp_server':
            Thread(name='TCP server', target=self.server.serve_forever),
            'api_server':
            Thread(name='API server', target=self.api_server.run),
            'raw_event_handler':
            Thread(name='RawEvent Handler', target=raw_event_handler),
            'msg_in_event_handler':
            Thread(name='MsgInEvent Handler', target=msg_in_event_handler),
            'msg_out_event_handler':
            Thread(name='MsgOutEvent Handler', target=msg_out_event_handler),
            'app_event_handler':
            Thread(name='AppEvent Handler', target=app_event_handler)
        }

        self._threads = thrds
        # This is critical, if any of them started we should exit.
        for thread in self._threads.values():
            try:
                thread.start()
            except OSError as exception:
                error_msg = "Error starting thread {}: {}."
                sys.exit(error_msg.format(thread, exception))

        self.log.info("Loading Kytos NApps...")
        self.napp_dir_listener.start()
        self.load_napps()
        self.started_at = now()
Пример #16
0
    def __init__(self, name=None, content=None, trace_parent=None, priority=0):
        """Create an event to be published.

        Args:
            name (string): The name of the event. You should prepend it with
                           the name of the napp.
            content (dict): Dictionary with any extra data for the event.
            trace_parent (object): APM TraceParent for distributed tracing,
                                   if you have APM enabled, @listen_to will
                                   set the root parent, and then you have to
                                   pass the trace_parent to subsequent
                                   correlated KytosEvent(s).
            priority (int): Priority of this event if a PriorityQueue is being
                            used, the lower the number the higher the priority.
        """
        self.name = name
        self.content = content if content is not None else {}
        self.timestamp = now()
        self.reinjections = 0
        self.priority = priority

        # pylint: disable=invalid-name
        self.id = uuid4()
        self.trace_parent = trace_parent
Пример #17
0
    def __init__(self, controller, **kwargs):
        """Create an EVC instance with the provided parameters.

        Args:
            id(str): EVC identifier. Whether it's None an ID will be genereted.
                     Only the first 14 bytes passed will be used.
            name: represents an EVC name.(Required)
            uni_a (UNI): Endpoint A for User Network Interface.(Required)
            uni_z (UNI): Endpoint Z for User Network Interface.(Required)
            start_date(datetime|str): Date when the EVC was registred.
                                      Default is now().
            end_date(datetime|str): Final date that the EVC will be fineshed.
                                    Default is None.
            bandwidth(int): Bandwidth used by EVC instance. Default is 0.
            primary_links(list): Primary links used by evc. Default is []
            backup_links(list): Backups links used by evc. Default is []
            current_path(list): Circuit being used at the moment if this is an
                                active circuit. Default is [].
            primary_path(list): primary circuit offered to user IF one or more
                                links were provided. Default is [].
            backup_path(list): backup circuit offered to the user IF one or
                               more links were provided. Default is [].
            dynamic_backup_path(bool): Enable computer backup path dynamically.
                                       Dafault is False.
            creation_time(datetime|str): datetime when the circuit should be
                                         activated. default is now().
            enabled(Boolean): attribute to indicate the administrative state;
                              default is False.
            active(Boolean): attribute to indicate the operational state;
                             default is False.
            archived(Boolean): indicate the EVC has been deleted and is
                               archived; default is False.
            owner(str): The EVC owner. Default is None.
            priority(int): Service level provided in the request. Default is 0.

        Raises:
            ValueError: raised when object attributes are invalid.

        """
        self._validate(**kwargs)
        super().__init__()

        # required attributes
        self._id = kwargs.get('id', uuid4().hex)[:14]
        self.uni_a = kwargs.get('uni_a')
        self.uni_z = kwargs.get('uni_z')
        self.name = kwargs.get('name')

        # optional attributes
        self.start_date = get_time(kwargs.get('start_date')) or now()
        self.end_date = get_time(kwargs.get('end_date')) or None
        self.queue_id = kwargs.get('queue_id', None)

        self.bandwidth = kwargs.get('bandwidth', 0)
        self.primary_links = Path(kwargs.get('primary_links', []))
        self.backup_links = Path(kwargs.get('backup_links', []))
        self.current_path = Path(kwargs.get('current_path', []))
        self.primary_path = Path(kwargs.get('primary_path', []))
        self.backup_path = Path(kwargs.get('backup_path', []))
        self.dynamic_backup_path = kwargs.get('dynamic_backup_path', False)
        self.creation_time = get_time(kwargs.get('creation_time')) or now()
        self.owner = kwargs.get('owner', None)
        self.priority = kwargs.get('priority', 0)
        self.circuit_scheduler = kwargs.get('circuit_scheduler', [])

        self.current_links_cache = set()
        self.primary_links_cache = set()
        self.backup_links_cache = set()

        self.lock = Lock()

        self.archived = kwargs.get('archived', False)

        self._storehouse = StoreHouse(controller)

        if kwargs.get('active', False):
            self.activate()
        else:
            self.deactivate()

        if kwargs.get('enabled', False):
            self.enable()
        else:
            self.disable()

        # datetime of user request for a EVC (or datetime when object was
        # created)
        self.request_time = kwargs.get('request_time', now())
        # dict with the user original request (input)
        self._requested = kwargs
Пример #18
0
 def is_connected(self):
     """Verify if the switch is connected to a socket."""
     return (self.connection is not None and self.connection.is_alive()
             and self.connection.is_established()
             and (now() - self.lastseen).seconds <= CONNECTION_TIMEOUT)
Пример #19
0
 def update_lastseen(self):
     """Update the lastseen attribute."""
     self.lastseen = now()
Пример #20
0
 def is_active(self):
     """Return true if the switch connection is alive."""
     return (now() - self.lastseen).seconds <= CONNECTION_TIMEOUT
Пример #21
0
 def update_lastseen(self):
     """Update the lastseen attribute."""
     self.lastseen = now()
Пример #22
0
 def is_active(self):
     """Return true if the switch connection is alive."""
     return (now() - self.lastseen).seconds <= CONNECTION_TIMEOUT