Ejemplo n.º 1
0
    def _handle_status_vap(cls, wtp, status):
        """Handle an incoming STATUS_VAP message.
        Args:
            status, a STATUS_VAP message
        Returns:
            None
        """

        if not wtp.connection:
            LOG.info("VAP Status from disconnected WTP %s", wtp.addr)
            return

        net_bssid_addr = EtherAddress(status.net_bssid)
        ssid = SSID(status.ssid)
        tenant = RUNTIME.load_tenant(ssid)

        if not tenant:
            LOG.info("VAP %s from unknown tenant %s", net_bssid_addr, ssid)
            return

        incoming = ResourceBlock(wtp, EtherAddress(status.hwaddr),
                                 status.channel, status.band)

        LOG.info("VAP status update from %s", net_bssid_addr)

        # If the VAP does not exists, then create a new one
        if net_bssid_addr not in tenant.vaps:
            vap = VAP(net_bssid_addr, incoming, wtp, tenant)
            tenant.vaps[net_bssid_addr] = vap

        vap = tenant.vaps[net_bssid_addr]

        LOG.info("VAP status %s", vap)
Ejemplo n.º 2
0
    def _handle_caps(self, wtp, caps):
        """Handle an incoming CAPS message.
        Args:
            caps, a CAPS message
        Returns:
            None
        """

        LOG.info("Received caps from %s", wtp.addr)

        for block in caps.blocks:
            hwaddr = EtherAddress(block[0])
            r_block = ResourceBlock(wtp, hwaddr, block[1], block[2])
            wtp.supports.add(r_block)

        for port in caps.ports:

            iface = port[2].decode("utf-8").strip('\0')

            network_port = NetworkPort(dpid=wtp.addr,
                                       hwaddr=EtherAddress(port[0]),
                                       port_id=int(port[1]),
                                       iface=iface)

            wtp.ports[network_port.port_id] = network_port

        # WTP can be considered as available once the empower0 port has been
        # added to the OVS
        if wtp.port():
            self.send_register_message_to_self()
Ejemplo n.º 3
0
    def block(self, value):

        if isinstance(value, ResourceBlock):

            self._block = value

        elif isinstance(value, dict):

            wtp = RUNTIME.wtps[EtherAddress(value['wtp'])]

            if 'hwaddr' not in value:
                raise ValueError("Missing field: hwaddr")

            if 'channel' not in value:
                raise ValueError("Missing field: channel")

            if 'band' not in value:
                raise ValueError("Missing field: band")

            if 'wtp' not in value:
                raise ValueError("Missing field: wtp")

            # Check if block is valid
            incoming = ResourceBlock(wtp, EtherAddress(value['hwaddr']),
                                     int(value['channel']), int(value['band']))

            match = [block for block in wtp.supports if block == incoming]

            if not match:
                raise ValueError("No block specified")

            if len(match) > 1:
                raise ValueError("More than one block specified")

            self._block = match[0]
Ejemplo n.º 4
0
    def _handle_caps_response(self, caps):
        """Handle an incoming CAPS message."""

        for block in caps.blocks:

            self.device.blocks[block.block_id] = \
                ResourceBlock(self.device,
                              block.block_id,
                              EtherAddress(block.hwaddr),
                              block.channel,
                              block.band)

        # set state to online
        super()._handle_caps_response(caps)

        # fetch active lvaps
        self.send_lvap_status_request()

        # fetch active vaps
        self.send_vap_status_request()

        # fetch active traffic rules
        self.send_slice_status_request()

        # fetch active tramission policies
        self.send_tx_policy_status_request()

        # send vaps
        self.update_vaps()

        # send slices
        self.update_slices()
Ejemplo n.º 5
0
    def _handle_caps(cls, caps):
        """Handle an incoming CAPS message.
        Args:
            caps, a CAPS message
        Returns:
            None
        """

        wtp_addr = EtherAddress(caps.wtp)

        try:
            wtp = RUNTIME.wtps[wtp_addr]
        except KeyError:
            LOG.info("Caps response from unknown WTP (%s)", wtp_addr)
            return

        LOG.info("Received caps response from %s", wtp_addr)

        for block in caps.blocks:

            hwaddr = EtherAddress(block[0])

            r_block = ResourceBlock(wtp, hwaddr, block[1], block[2])
            wtp.supports.add(r_block)

        for port in caps.ports:

            iface = port[2].decode("utf-8").strip('\0')

            network_port = NetworkPort(dpid=wtp.addr,
                                       hwaddr=EtherAddress(port[0]),
                                       port_id=int(port[1]),
                                       iface=iface)

            wtp.ports[network_port.port_id] = network_port
Ejemplo n.º 6
0
    def handle_response(self, message):
        """ Handle an incoming BUSYNESS_TRIGGER message.
        Args:
            message, a BUSYNESS_TRIGGER message
        Returns:
            None
        """

        wtp_addr = EtherAddress(message.wtp)

        if wtp_addr not in RUNTIME.wtps:
            return

        wtp = RUNTIME.wtps[wtp_addr]

        if wtp_addr not in RUNTIME.tenants[self.tenant_id].wtps:
            return

        hwaddr = EtherAddress(message.hwaddr)
        channel = message.channel
        band = message.band
        incoming = ResourceBlock(wtp, hwaddr, channel, band)

        match = [block for block in wtp.supports if block == incoming]

        self.event = \
            {'block': matches[0],
             'timestamp': datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%fZ"),
             'current': message.current / 180.0}

        self.handle_callback(self)
Ejemplo n.º 7
0
    def handle_response(self, message):
        """ Handle an incoming RSSI_TRIGGER message.
        Args:
            message, a RSSI_TRIGGER message
        Returns:
            None
        """

        wtp_addr = EtherAddress(message.wtp)

        if wtp_addr not in RUNTIME.wtps:
            return

        wtp = RUNTIME.wtps[wtp_addr]

        if wtp_addr not in RUNTIME.tenants[self.tenant_id].wtps:
            return

        incoming = ResourcePool()
        hwaddr = EtherAddress(message.hwaddr)
        channel = message.channel
        band = message.band
        incoming.add(ResourceBlock(wtp, hwaddr, channel, band))

        matches = wtp.supports & incoming

        self.event = \
            {'block': matches.pop(),
             'timestamp': datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%fZ"),
             'current': message.current}

        self.handle_callback(self)
Ejemplo n.º 8
0
    def _handle_caps(self, wtp, caps):
        """Handle an incoming CAPS message.
        Args:
            caps, a CAPS message
        Returns:
            None
        """

        dpid = DPID(caps['dpid'])

        if dpid not in RUNTIME.datapaths:
            RUNTIME.datapaths[dpid] = Datapath(dpid)

        wtp.datapath = RUNTIME.datapaths[dpid]

        for block in caps.blocks:
            hwaddr = EtherAddress(block[0])
            r_block = ResourceBlock(wtp, hwaddr, block[1], block[2])
            wtp.supports.add(r_block)

        for port in caps.ports:

            hwaddr = EtherAddress(port[0])
            port_id = int(port[1])
            iface = port[2].decode("utf-8").strip('\0')

            if port_id not in wtp.datapath.network_ports:

                network_port = NetworkPort(dp=wtp.datapath,
                                           port_id=port_id,
                                           hwaddr=hwaddr,
                                           iface=iface)

                wtp.datapath.network_ports[port_id] = network_port

        # set state to online
        wtp.set_online()

        # fetch active lvaps
        self.send_lvap_status_request()

        # fetch active vaps
        self.send_vap_status_request()

        # fetch active traffic rules
        self.send_slice_status_request()

        # fetch active tramission policies
        self.send_transmission_policy_status_request()

        # send vaps
        self.update_vaps()

        # send slices
        self.update_slices()
Ejemplo n.º 9
0
    def handle_poller_response(self, message):
        """Handle an incoming poller response message.
        Args:
            message, a poller response message
        Returns:
            None
        """

        if message.poller_id not in self.modules:
            return

        wtp_addr = EtherAddress(message.wtp)

        if wtp_addr not in RUNTIME.wtps:
            return

        wtp = RUNTIME.wtps[wtp_addr]
        hwaddr = EtherAddress(message.hwaddr)
        incoming = ResourcePool()
        incoming.add(ResourceBlock(wtp, hwaddr, message.channel, message.band))

        matching = (wtp.supports & incoming).pop()

        LOG.info("Received %s response from %s (id=%u)",
                 self.MODULE_NAME,
                 matching,
                 message.poller_id)

        # find poller object
        poller = self.modules[message.poller_id]

        # handle the message
        map_type = self.MODULE_NAME
        setattr(poller.block, map_type, CQM())
        map_entry = getattr(poller.block, map_type)

        for entry in message.img_entries:

            addr = EtherAddress(entry[0])

            if not addr.match(poller.addrs):
                continue

            value = {'addr': addr,
                     'last_rssi_std': entry[1] / 1000.0,
                     'last_rssi_avg': entry[2] / 1000.0,
                     'last_packets': entry[3],
                     'hist_packets': entry[4],
                     'ewma_rssi': entry[5] / 1000.0,
                     'sma_rssi': entry[6] / 1000.0}

            map_entry[addr] = value

        # call callback
        handle_callback(poller, poller)
Ejemplo n.º 10
0
    def _handle_status_vap(cls, status):
        """Handle an incoming STATUS_VAP message.
        Args:
            status, a STATUS_VAP message
        Returns:
            None
        """

        wtp_addr = EtherAddress(status.wtp)

        try:
            wtp = RUNTIME.wtps[wtp_addr]
        except KeyError:
            LOG.info("VAP Status from unknown WTP %s", wtp_addr)
            return

        if not wtp.connection:
            LOG.info("VAP Status from disconnected WTP %s", wtp_addr)
            return

        net_bssid_addr = EtherAddress(status.net_bssid)
        ssid = SSID(status.ssid)
        tenant_id = None

        for tenant in RUNTIME.tenants.values():
            if tenant.tenant_name == ssid:
                tenant_id = tenant.tenant_id
                break

        if not tenant_id:
            LOG.info("VAP %s from unknown tenant %s", net_bssid_addr, ssid)
            return

        tenant = RUNTIME.tenants[tenant_id]

        vap = None
        hwaddr = EtherAddress(status.hwaddr)
        block = ResourceBlock(wtp, hwaddr, status.channel, status.band)
        ssid = status.ssid

        LOG.info("VAP %s status update block %s", net_bssid_addr, block)

        # If the VAP does not exists, then create a new one
        if net_bssid_addr not in tenant.vaps:
            tenant.vaps[net_bssid_addr] = \
                VAP(net_bssid_addr, block, wtp, tenant)

        vap = tenant.vaps[net_bssid_addr]
        LOG.info("VAP status %s", vap)
Ejemplo n.º 11
0
    def handle_response(self, response):
        """Handle an incoming poller response message.
        Args:
            message, a poller response message
        Returns:
            None
        """

        wtp_addr = EtherAddress(response.wtp)

        if wtp_addr not in RUNTIME.wtps:
            return

        wtp = RUNTIME.wtps[wtp_addr]

        hwaddr = EtherAddress(response.hwaddr)
        block = ResourceBlock(wtp, hwaddr, response.channel, response.band)
        incoming = ResourcePool()
        incoming.add(block)

        matching = (wtp.supports & incoming).pop()

        if not matching:
            return

        # handle the message
        setattr(self.block, self.MODULE_NAME, CQM())
        map_entry = getattr(self.block, self.MODULE_NAME)

        for entry in response.img_entries:

            addr = EtherAddress(entry[0])

            if not addr.match(self.addrs):
                continue

            value = {'addr': addr,
                     'last_rssi_std': entry[1] / 1000.0,
                     'last_rssi_avg': entry[2] / 1000.0,
                     'last_packets': entry[3],
                     'hist_packets': entry[4],
                     'ewma_rssi': entry[5] / 1000.0,
                     'sma_rssi': entry[6] / 1000.0}

            map_entry[addr] = value

        # call callback
        self.handle_callback(self)
Ejemplo n.º 12
0
    def _handle_status_port(cls, status):
        """Handle an incoming PORT message.
        Args:
            status, a STATUS_PORT message
        Returns:
            None
        """

        wtp_addr = EtherAddress(status.wtp)

        try:
            wtp = RUNTIME.wtps[wtp_addr]
        except KeyError:
            LOG.info("Status from unknown WTP %s", wtp_addr)
            return

        if not wtp.connection:
            LOG.info("Status from disconnected WTP %s", wtp_addr)
            return

        sta_addr = EtherAddress(status.sta)
        hwaddr = EtherAddress(status.hwaddr)
        block = ResourceBlock(wtp, hwaddr, status.channel, status.band)

        # incoming block
        pool = ResourcePool()
        pool.add(block)

        match = wtp.supports & pool

        if not match:
            LOG.error("Incoming block %s is invalid", block)
            return

        block = match.pop()

        LOG.info("Port status from %s, station %s", wtp_addr, sta_addr)

        tx_policy = block.tx_policies[sta_addr]

        tx_policy._mcs = set([float(x) / 2 for x in status.mcs])
        tx_policy._rts_cts = int(status.rts_cts)
        tx_policy._mcast = int(status.tx_mcast)
        tx_policy._ur_count = int(status.ur_mcast_count)
        tx_policy._no_ack = bool(status.flags.no_ack)

        LOG.info("Port status %s", tx_policy)
Ejemplo n.º 13
0
    def _handle_status_port(self, status):
        """Handle an incoming PORT message.
        Args:
            status, a STATUS_PORT message
        Returns:
            None
        """

        wtp_addr = EtherAddress(status.wtp)

        try:
            wtp = RUNTIME.wtps[wtp_addr]
        except KeyError:
            LOG.info("Status from unknown WTP %s", wtp_addr)
            return

        if not wtp.connection:
            LOG.info("Status from disconnected WTP %s", wtp_addr)
            return

        sta_addr = EtherAddress(status.sta)
        hwaddr = EtherAddress(status.hwaddr)
        block = ResourceBlock(wtp, hwaddr, status.channel, status.band)

        LOG.info("Port status from %s", sta_addr)

        try:
            lvap = RUNTIME.lvaps[sta_addr]
        except KeyError:
            LOG.error("Invalid LVAP %s, ignoring", sta_addr)
            return

        try:
            port = lvap.downlink[block]
        except KeyError:
            LOG.error("Invalid Block %s, ignoring", block)
            return

        port._no_ack = bool(status.flags.no_ack)
        port._rts_cts = int(status.rts_cts)
        port._mcs = set([float(x) / 2 for x in status.mcs])

        LOG.info("Port status %s", port)
Ejemplo n.º 14
0
    def _handle_caps(self, wtp, caps):
        """Handle an incoming CAPS message.
        Args:
            caps, a CAPS message
        Returns:
            None
        """

        LOG.info("Received caps from %s", wtp.addr)

        for block in caps.blocks:
            hwaddr = EtherAddress(block[0])
            r_block = ResourceBlock(wtp, hwaddr, block[1], block[2])
            wtp.supports.add(r_block)

        for port in caps.ports:

            iface = port[2].decode("utf-8").strip('\0')

            network_port = NetworkPort(dpid=wtp.addr,
                                       hwaddr=EtherAddress(port[0]),
                                       port_id=int(port[1]),
                                       iface=iface)

            wtp.ports[network_port.port_id] = network_port

        # set state to online
        wtp.set_online()

        # fetch active lvaps
        self.send_lvap_status_request()

        # fetch active vaps
        self.send_vap_status_request()

        # fetch active traffic rules
        self.send_traffic_rule_status_request()

        # fetch active transmission rules
        self.send_port_status_request()

        # send vaps
        self.send_vaps()
Ejemplo n.º 15
0
    def _handle_status_traffic_rule(self, wtp, status):
        """Handle an incoming STATUS_TRAFFIC_RULE message.
        Args:
            status, a STATUS_TRAFFIC_RULE message
        Returns:
            None
        """

        if not wtp.connection:
            LOG.info("Traffic rule status from disconnected WTP %s", wtp.addr)
            return

        quantum = status.quantum
        amsdu_aggregation = bool(status.flags.amsdu_aggregation)
        dscp = "{0:#0{1}x}".format(status.dscp, 4)
        ssid = SSID(status.ssid)

        tenant = RUNTIME.load_tenant(ssid)

        if not tenant:
            LOG.info("Traffic rule status from unknown tenant %s", ssid)
            return

        incoming = ResourceBlock(wtp, EtherAddress(status.hwaddr),
                                 status.channel, status.band)

        valid = [block for block in self.wtp.supports if block == incoming]

        if not valid:
            LOG.warning("No valid intersection found. Ignoring request.")
            return

        block = valid[0]

        trq = block.traffic_rule_queues[(ssid, dscp)]

        trq._quantum = quantum
        trq._amsdu_aggregation = amsdu_aggregation

        LOG.info("Transmission rule status %s", trq)
Ejemplo n.º 16
0
    def _handle_status_port(cls, wtp, status):
        """Handle an incoming PORT message.
        Args:
            status, a STATUS_PORT message
        Returns:
            None
        """

        if not wtp.connection:
            LOG.info("Status from disconnected WTP %s", wtp.addr)
            return

        sta_addr = EtherAddress(status.sta)

        # incoming block
        incoming = ResourceBlock(wtp, EtherAddress(status.hwaddr),
                                 status.channel, status.band)

        valid = [block for block in wtp.supports if block == incoming]

        if not valid:
            LOG.error("Incoming block %s is invalid", incoming)
            return

        block = valid[0]

        LOG.info("Port status from %s, station %s", wtp.addr, sta_addr)

        tx_policy = block.tx_policies[sta_addr]

        tx_policy._mcs = set([float(x) / 2 for x in status.mcs])
        tx_policy._ht_mcs = set([int(x) for x in status.ht_mcs])
        tx_policy._rts_cts = int(status.rts_cts)
        tx_policy._mcast = int(status.tx_mcast)
        tx_policy._ur_count = int(status.ur_mcast_count)
        tx_policy._no_ack = bool(status.flags.no_ack)

        LOG.info("Port status %s", tx_policy)
Ejemplo n.º 17
0
    def block(self, value):
        """Set block."""

        if isinstance(value, ResourceBlock):

            self._block = value

        elif isinstance(value, dict):

            wtp = RUNTIME.wtps[EtherAddress(value['wtp'])]

            if 'hwaddr' not in value:
                raise ValueError("Missing field: hwaddr")

            if 'channel' not in value:
                raise ValueError("Missing field: channel")

            if 'band' not in value:
                raise ValueError("Missing field: band")

            if 'wtp' not in value:
                raise ValueError("Missing field: wtp")

            incoming = ResourcePool()
            block = ResourceBlock(wtp, EtherAddress(value['hwaddr']),
                                  int(value['channel']), int(value['band']))
            incoming.add(block)

            match = wtp.supports & incoming

            if not match:
                raise ValueError("No block specified")

            if len(match) > 1:
                raise ValueError("More than one block specified")

            self._block = match.pop()
Ejemplo n.º 18
0
    def post(self, *args, **kwargs):
        """ Create a new module.

        Args:
            [0]: tenant_id

        Request:
            version: the protocol version (1.0)

        Example URLs:

            POST /api/v1/tenants/EmPOWER/<module>
        """

        try:

            if len(args) != 1:
                raise ValueError("Invalid URL")

            tenant_id = uuid.UUID(args[0])

            request = tornado.escape.json_decode(self.request.body)

            if "version" not in request:
                raise ValueError("missing version element")

            if "wtp" not in request:
                raise ValueError("missing wtp element")

            if "band" not in request:
                raise ValueError("missing band element")

            if "channel" not in request:
                raise ValueError("missing channel element")

            del request['version']
            request['tenant_id'] = tenant_id
            request['module_type'] = self.worker.MODULE_NAME
            request['worker'] = self.worker

            wtp_addr = EtherAddress(request['wtp'])
            wtp = RUNTIME.tenants[tenant_id].wtps[wtp_addr]

            channel = int(request['channel'])
            band = int(request['band'])

            del request['wtp']
            del request['channel']
            del request['band']

            request['block'] = ResourceBlock(wtp, channel, band)

            module = self.worker.add_module(**request)

            self.set_header("Location", "/api/v1/tenants/%s/%s/%s" %
                            (module.tenant_id,
                             self.worker.MODULE_NAME,
                             module.module_id))

            self.set_status(201, None)

        except KeyError as ex:
            self.send_error(404, message=ex)
        except ValueError as ex:
            self.send_error(400, message=ex)
Ejemplo n.º 19
0
    def get_block(self, hwaddr, channel, band):
        """Look for block."""

        incoming = ResourceBlock(self, EtherAddress(hwaddr), channel, band)
        return [block for block in self.supports if block == incoming]
Ejemplo n.º 20
0
    def _handle_status_lvap(self, wtp, status):
        """Handle an incoming STATUS_LVAP message.
        Args:
            status, a STATUS_LVAP message
        Returns:
            None
        """

        if not wtp.connection:
            LOG.info("Status from disconnected WTP %s", wtp.addr)
            return

        sta = EtherAddress(status.sta)
        set_mask = bool(status.flags.set_mask)

        lvap = None

        accum = []
        incoming_ssids = [SSID(x.ssid) for x in status.ssids]

        accum.append("addr ")
        accum.append(EtherAddress(status.sta).to_str())
        accum.append(" net_bssid ")
        accum.append(EtherAddress(status.net_bssid).to_str())
        accum.append(" lvap_bssid ")
        accum.append(EtherAddress(status.lvap_bssid).to_str())

        accum.append(" ssid ")

        if incoming_ssids[0]:
            accum.append(incoming_ssids[0].to_str())
        else:
            accum.append("None")

        accum.append(" ssids [")

        for ssid in incoming_ssids[1:]:
            accum.append(" ")
            accum.append(ssid.to_str())

        accum.append(" ]")

        accum.append(" assoc_id ")
        accum.append(str(status.assoc_id))

        if bool(status.flags.authenticated):
            accum.append(" AUTH")

        if bool(status.flags.associated):
            accum.append(" ASSOC")

        LOG.info("LVAP status %s", ''.join(accum))

        # If the LVAP does not exists, then create a new one
        if sta not in RUNTIME.lvaps:

            net_bssid_addr = EtherAddress(status.net_bssid)
            lvap_bssid_addr = EtherAddress(status.lvap_bssid)
            lvap = LVAP(sta, net_bssid_addr, lvap_bssid_addr)

            RUNTIME.lvaps[sta] = lvap

        lvap = RUNTIME.lvaps[sta]

        # Check if block is valid
        incoming = ResourceBlock(wtp, EtherAddress(status.hwaddr),
                                 status.channel, status.band)

        valid = [block for block in wtp.supports if block == incoming]

        if not valid:
            LOG.warning("No valid intersection found. Removing block.")
            wtp.connection.send_del_lvap(lvap)
            return

        # received downlink block but a different downlink block is already
        # present, delete before going any further
        if set_mask and lvap._downlink and lvap._downlink != valid[0]:
            lvap._downlink.radio.connection.send_del_lvap(lvap)

        if set_mask:
            lvap._downlink = valid[0]
        else:
            lvap._uplink.append(valid[0])

        # update ports
        if not lvap.ports:
            lvap.ports[0] = VirtualPort(virtual_port_id=0)

        lvap.ports[0].poas.append(wtp.port())

        # set supported band
        lvap._supported_band = status.supported_band

        # update LVAP params
        lvap.authentication_state = bool(status.flags.authenticated)
        lvap.association_state = bool(status.flags.associated)

        lvap._assoc_id = status.assoc_id
        lvap._encap = EtherAddress(status.encap)
        ssids = [SSID(x.ssid) for x in status.ssids]

        # update ssid
        if lvap.ssid:

            # Raise LVAP leave event
            self.server.send_lvap_leave_message_to_self(lvap)

            # removing LVAP from tenant, need first to look for right tenant
            if lvap.addr in lvap.tenant.lvaps:
                LOG.info("Removing %s from tenant %s", lvap.addr, lvap.ssid)
                del lvap.tenant.lvaps[lvap.addr]

            lvap._tenant = None

        # update remaining ssids
        lvap._ssids = ssids[1:]

        if ssids[0]:

            tenant = RUNTIME.load_tenant(ssids[0])

            if not tenant:
                LOG.info("LVAP %s from unknown tenant %s", lvap.addr, ssids[0])
                RUNTIME.remove_lvap(lvap.addr)
                return

            # setting tenant without seding out add lvap message
            lvap._tenant = tenant

            # adding LVAP to tenant
            LOG.info("Adding %s to tenant %s", lvap.addr, ssids[0])
            lvap.tenant.lvaps[lvap.addr] = lvap

            # Raise LVAP join event
            self.server.send_lvap_join_message_to_self(lvap)
    def put(self, *args, **kwargs):
        """ Set the WTP for a given LVAP, effectivelly hands-over the LVAP to
        another WTP

        Args:
            pool_id: the pool address
            lvap_id: the lvap address

        Request:
            version: the protocol version (1.0)

        Example URLs:
            PUT /api/v1/pools/52313ecb-9d00-4b7d-b873-b55d3d9ada26/lvaps/11:22:33:44:55:66
        """

        try:

            if len(args) != 2:
                raise ValueError("Invalid URL")

            request = tornado.escape.json_decode(self.request.body)

            if "version" not in request:
                raise ValueError("missing version element")

            tenant_id = uuid.UUID(args[0])
            lvap_addr = EtherAddress(args[1])

            tenant = RUNTIME.tenants[tenant_id]
            lvap = tenant.lvaps[lvap_addr]

            if "wtp" in request:

                wtp_addr = EtherAddress(request['wtp'])
                wtp = tenant.wtps[wtp_addr]
                lvap.wtp = wtp

            elif "blocks" in request:

                pool = []

                for block in request["blocks"]:

                    wtp_addr = EtherAddress(block['wtp'])
                    wtp = RUNTIME.wtps[wtp_addr]
                    hwaddr = EtherAddress(block['hwaddr'])
                    channel = int(block['channel'])
                    band = int(block['band'])

                    r_block = ResourceBlock(wtp, hwaddr, channel, band)
                    pool.append(r_block)

                lvap.blocks = pool

            if "encap" in request:

                encap = EtherAddress(request["encap"])
                lvap.encap = encap

        except KeyError as ex:
            self.send_error(404, message=ex)
        except ValueError as ex:
            self.send_error(400, message=ex)

        self.set_status(204, None)
Ejemplo n.º 22
0
    def put(self, *args, **kwargs):
        """ Set the WTP for a given LVAP, effectivelly hands-over the LVAP to
        another WTP

        Args:
            lvap_id: the lvap address

        Request:
            version: the protocol version (1.0)

        Example URLs:
            PUT /api/v1/lvaps/11:22:33:44:55:66
        """

        try:

            if len(args) != 1:
                raise ValueError("Invalid URL")

            request = tornado.escape.json_decode(self.request.body)

            if "version" not in request:
                raise ValueError("missing version element")

            lvap_addr = EtherAddress(args[0])

            lvap = RUNTIME.lvaps[lvap_addr]

            if "blocks" in request:

                pool = []

                for block in request["blocks"]:

                    wtp_addr = EtherAddress(block['wtp'])
                    wtp = RUNTIME.wtps[wtp_addr]
                    hwaddr = EtherAddress(block['hwaddr'])
                    channel = int(block['channel'])
                    band = block['band']

                    r_block = ResourceBlock(wtp, hwaddr, channel,
                                            REVERSE_BANDS[band])
                    pool.append(r_block)

                lvap.blocks = pool

            elif "wtp" in request:

                wtp_addr = EtherAddress(request['wtp'])
                wtp = RUNTIME.wtps[wtp_addr]
                lvap.wtp = wtp

            if "encap" in request:

                encap = EtherAddress(request["encap"])
                lvap.encap = encap

        except KeyError as ex:
            self.send_error(404, message=ex)
        except ValueError as ex:
            self.send_error(400, message=ex)

        self.set_status(204, None)
Ejemplo n.º 23
0
    def put(self, *args, **kwargs):
        """ Set the WTP for a given LVAP, effectivelly hands-over the LVAP to
        another WTP

        Args:
            pool_id: the pool address
            lvap_id: the lvap address

        Request:
            version: the protocol version (1.0)
            wtp: the new wtp address

        Example URLs:
            PUT /api/v1/pools/EmPOWER/lvaps/11:22:33:44:55:66
        """

        try:

            if len(args) != 2:
                raise ValueError("Invalid URL")

            request = tornado.escape.json_decode(self.request.body)

            if "version" not in request:
                raise ValueError("missing version element")

            if "wtp" not in request and "scheduled_on" not in request and \
               "encap" not in request:

                raise ValueError("missing wtp/scheduled_on element")

            tenant_id = uuid.UUID(args[0])
            lvap_addr = EtherAddress(args[1])

            tenant = RUNTIME.tenants[tenant_id]
            lvap = tenant.lvaps[lvap_addr]

            if "wtp" in request:

                wtp_addr = EtherAddress(request['wtp'])
                wtp = tenant.wtps[wtp_addr]
                lvap.wtp = wtp

            if "scheduled_on" in request:

                pool = ResourcePool()

                for block in request["scheduled_on"]:

                    wtp_addr = EtherAddress(block['wtp'])
                    wtp = RUNTIME.wtps[wtp_addr]
                    channel = int(block['channel'])
                    band = int(block['band'])

                    rb = ResourceBlock(wtp, channel, band)
                    pool.add(rb)

                lvap.scheduled_on = pool

            if "encap" in request:

                encap = EtherAddress(request["encap"])
                lvap.encap = encap

        except KeyError as ex:
            self.send_error(404, message=ex)
        except ValueError as ex:
            self.send_error(400, message=ex)

        self.set_status(204, None)
Ejemplo n.º 24
0
    def _handle_probe_request(self, wtp, request):
        """Handle an incoming PROBE_REQUEST message.
        Args:
            request, a PROBE_REQUEST message
        Returns:
            None
        """

        if not wtp.connection:
            LOG.info("Probe request from disconnected WTP %s", wtp.addr)
            self.stream.close()
            return

        if not wtp.port():
            LOG.info("WTP %s not ready", wtp.addr)
            return

        sta = EtherAddress(request.sta)

        if sta in RUNTIME.lvaps:
            return

        if not RUNTIME.is_allowed(sta):
            return

        if RUNTIME.is_denied(sta):
            return

        ssid = SSID(request.ssid)

        if request.ssid == b'':
            LOG.info("Probe request from %s ssid %s", sta, "Broadcast")
        else:
            LOG.info("Probe request from %s ssid %s", sta, ssid)

        # generate list of available SSIDs
        ssids = set()

        for tenant in RUNTIME.tenants.values():
            if tenant.bssid_type == T_TYPE_SHARED:
                continue
            for wtp_in_tenant in tenant.wtps.values():
                if wtp.addr == wtp_in_tenant.addr:
                    ssids.add(tenant.tenant_name)

        if not ssids:
            LOG.info("No SSIDs available at this WTP")
            return

        # spawn new LVAP
        LOG.info("Spawning new LVAP %s on %s", sta, wtp.addr)
        net_bssid = generate_bssid(BASE_MAC, sta)
        lvap = LVAP(sta, net_bssid, net_bssid)
        lvap.set_ssids(list(ssids))

        RUNTIME.lvaps[sta] = lvap

        # This will trigger an LVAP ADD message (and REMOVE if necessary)
        lvap.supported = ResourcePool()
        hwaddr = EtherAddress(request.hwaddr)
        channel = request.channel
        band = request.band
        lvap.supported.add(ResourceBlock(lvap, hwaddr, channel, band))

        lvap.scheduled_on = wtp.supports & lvap.supported

        LOG.info("Sending probe response to %s", lvap.addr)
        self.send_probe_response(lvap)
Ejemplo n.º 25
0
    def _handle_assoc_request(self, wtp, request):
        """Handle an incoming ASSOC_REQUEST message.
        Args:
            request, a ASSOC_REQUEST message
        Returns:
            None
        """

        if not wtp.connection:
            LOG.info("Assoc request from disconnected WTP %s", wtp.addr)
            return

        sta = EtherAddress(request.sta)

        if sta not in RUNTIME.lvaps:
            LOG.info("Assoc request from unknown LVAP %s", sta)
            return

        lvap = RUNTIME.lvaps[sta]

        if not RUNTIME.is_allowed(sta):
            LOG.info("Assoc request from %s ignored (white list)", sta)
            return

        if RUNTIME.is_denied(sta):
            LOG.info("Assoc request from %s ignored (black list)", sta)
            return

        ssid = SSID(request.ssid.decode('UTF-8'))
        bssid = EtherAddress(request.bssid)

        tenant_name = None

        # look for ssid in shared tenants
        for tenant_id in RUNTIME.tenants:

            tenant = RUNTIME.tenants[tenant_id]

            if tenant.bssid_type == T_TYPE_UNIQUE:
                continue

            if bssid in tenant.vaps and ssid == tenant.tenant_name:
                tenant_name = tenant.tenant_name

        # otherwise this must be the lvap unique bssid
        if lvap.net_bssid == bssid and ssid in lvap.ssids:
            tenant_name = ssid

        if not tenant_name:
            LOG.info("Assoc request sta %s for ssid %s bssid %s, ignoring",
                     lvap.addr, lvap.ssid, lvap.lvap_bssid)
            return

        # this will trigger an add lvap message to update the ssid
        lvap.tenant = RUNTIME.load_tenant(tenant_name)

        # update supported blocks field
        lvap.supported = ResourcePool()
        hwaddr = EtherAddress(request.hwaddr)
        channel = request.channel
        band = request.band
        lvap.supported.add(ResourceBlock(lvap, hwaddr, channel, band))

        # this will trigger an add lvap message to update the assoc id
        lvap.assoc_id = self.server.assoc_id

        LOG.info("Assoc request sta %s ssid %s bssid %s assoc id %u, replying",
                 lvap.addr, lvap.ssid, lvap.lvap_bssid, lvap.assoc_id)

        self.send_assoc_response(lvap)
Ejemplo n.º 26
0
    def _handle_status_lvap(self, status):
        """Handle an incoming STATUS_LVAP message.
        Args:
            status, a STATUS_LVAP message
        Returns:
            None
        """

        wtp_addr = EtherAddress(status.wtp)

        try:
            wtp = RUNTIME.wtps[wtp_addr]
        except KeyError:
            LOG.info("Status from unknown WTP %s", wtp_addr)
            return

        if not wtp.connection:
            LOG.info("Status from disconnected WTP %s", wtp_addr)
            return

        sta_addr = EtherAddress(status.sta)
        set_mask = bool(status.flags.set_mask)

        lvap = None
        hwaddr = EtherAddress(status.hwaddr)
        block = ResourceBlock(wtp, hwaddr, status.channel, status.band)

        LOG.info("LVAP status update from %s", sta_addr)

        # If the LVAP does not exists, then create a new one
        if sta_addr not in RUNTIME.lvaps:

            net_bssid_addr = EtherAddress(status.net_bssid)
            lvap_bssid_addr = EtherAddress(status.lvap_bssid)
            lvap = LVAP(sta_addr, net_bssid_addr, lvap_bssid_addr)

            # TODO: This should be built starting from the status message
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 1, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 2, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 3, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 4, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 5, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 6, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 7, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 8, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 9, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 10, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 11, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 36, BT_L20))
            lvap.supports.add(ResourceBlock(lvap, sta_addr, 48, BT_L20))

            RUNTIME.lvaps[sta_addr] = lvap

        lvap = RUNTIME.lvaps[sta_addr]

        # incoming block
        pool = ResourcePool()
        pool.add(block)

        match = wtp.supports & pool

        if not match:
            LOG.error("Incoming block %s is invalid", block)
            return

        block = match.pop()

        # this will try to updated the lvap object with the resource block
        # coming in this status update message.
        try:

            if set_mask:

                # set downlink+uplink block
                lvap._downlink.setitem(block, RadioPort(lvap, block))

            else:

                # set uplink only blocks
                lvap._uplink.setitem(block, RadioPort(lvap, block))

        except ValueError:
            LOG.error("Error while importing block %s, removing.", block)
            block.radio.connection.send_del_lvap(lvap)
            return

        lvap.authentication_state = bool(status.flags.authenticated)
        lvap.association_state = bool(status.flags.associated)

        lvap._assoc_id = status.assoc_id
        lvap._encap = EtherAddress(status.encap)
        ssids = [SSID(x.ssid) for x in status.ssids]

        if lvap.ssid:

            # Raise LVAP leave event
            LOG.info("LVAP LEAVE %s (%s)", lvap.addr, lvap.ssid)
            for handler in self.server.pt_types_handlers[PT_LVAP_LEAVE]:
                handler(lvap)

            # removing LVAP from tenant, need first to look for right tenant
            if lvap.addr in lvap.tenant.lvaps:
                LOG.info("Removing %s from tenant %s", lvap.addr, lvap.ssid)
                del lvap.tenant.lvaps[lvap.addr]

        lvap._tenant = None

        if ssids[0]:

            # setting tenant without seding out add lvap message
            lvap._tenant = RUNTIME.load_tenant(ssids[0])

            # adding LVAP to tenant
            LOG.info("Adding %s to tenant %s", lvap.addr, ssids[0])
            lvap.tenant.lvaps[lvap.addr] = lvap

            # Raise LVAP join event
            LOG.info("LVAP JOIN %s (%s)", lvap.addr, lvap.ssid)
            for handler in self.server.pt_types_handlers[PT_LVAP_JOIN]:
                handler(lvap)

        # update remaining ssids
        lvap._ssids = ssids[1:]

        # set ports
        lvap.set_ports()

        LOG.info("LVAP status %s", lvap)
Ejemplo n.º 27
0
    def _handle_probe_request(self, request):
        """Handle an incoming PROBE_REQUEST message.
        Args:
            request, a PROBE_REQUEST message
        Returns:
            None
        """

        wtp_addr = EtherAddress(request.wtp)

        try:
            wtp = RUNTIME.wtps[wtp_addr]
        except KeyError:
            LOG.info("Probe request from unknown WTP (%s)", wtp_addr)
            return

        if not wtp.connection:
            LOG.info("Probe request from disconnected WTP %s", wtp_addr)
            return

        sta = EtherAddress(request.sta)

        if sta in RUNTIME.lvaps:
            return

        if not RUNTIME.is_allowed(sta):
            return

        if RUNTIME.is_denied(sta):
            return

        ssid = SSID(request.ssid)

        if request.ssid == b'':
            LOG.info("Probe request from %s ssid %s", sta, "Broadcast")
        else:
            LOG.info("Probe request from %s ssid %s", sta, ssid)

        # generate list of available SSIDs
        ssids = set()

        for tenant in RUNTIME.tenants.values():
            if tenant.bssid_type == T_TYPE_SHARED:
                continue
            for wtp_in_tenant in tenant.wtps.values():
                if wtp_addr == wtp_in_tenant.addr:
                    ssids.add(tenant.tenant_name)

        if not ssids:
            LOG.info("No SSIDs available at this WTP")
            return

        # spawn new LVAP
        LOG.info("Spawning new LVAP %s on %s", sta, wtp.addr)
        net_bssid = generate_bssid(BASE_MAC, sta)
        lvap = LVAP(sta, net_bssid, net_bssid)
        lvap.set_ssids(ssids)

        RUNTIME.lvaps[sta] = lvap

        # TODO: This should be built starting from the probe request
        lvap.supports.add(ResourceBlock(lvap, sta, 1, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 2, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 3, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 4, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 5, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 6, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 7, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 8, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 9, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 10, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 11, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 36, BT_L20))
        lvap.supports.add(ResourceBlock(lvap, sta, 48, BT_L20))

        # This will trigger an LVAP ADD message (and REMOVE if necessary)
        requested = ResourcePool()
        hwaddr = EtherAddress(request.hwaddr)
        channel = request.channel
        band = request.band
        requested.add(ResourceBlock(wtp, hwaddr, channel, band))

        lvap.scheduled_on = wtp.supports & requested

        LOG.info("Sending probe response to %s", lvap.addr)
        self.send_probe_response(lvap)
Ejemplo n.º 28
0
    def _handle_status_lvap(self, wtp, status):
        """Handle an incoming STATUS_LVAP message.
        Args:
            status, a STATUS_LVAP message
        Returns:
            None
        """

        if not wtp.connection:
            LOG.info("Status from disconnected WTP %s", wtp.addr)
            return

        sta_addr = EtherAddress(status.sta)
        set_mask = bool(status.flags.set_mask)

        lvap = None

        LOG.info("LVAP status update from %s", sta_addr)

        # If the LVAP does not exists, then create a new one
        if sta_addr not in RUNTIME.lvaps:

            net_bssid_addr = EtherAddress(status.net_bssid)
            lvap_bssid_addr = EtherAddress(status.lvap_bssid)
            lvap = LVAP(sta_addr, net_bssid_addr, lvap_bssid_addr)

            RUNTIME.lvaps[sta_addr] = lvap

        lvap = RUNTIME.lvaps[sta_addr]

        # incoming block
        lvap.supported = ResourcePool()
        hwaddr = EtherAddress(status.hwaddr)
        channel = status.channel
        band = status.band
        lvap.supported.add(ResourceBlock(lvap, hwaddr, channel, band))

        match = wtp.supports & lvap.supported

        if not match:
            LOG.error("Incoming block %s is invalid", block)
            return

        block = match.pop()

        # this will try to updated the lvap object with the resource block
        # coming in this status update message.
        try:

            if set_mask:

                # set downlink+uplink block
                lvap._downlink.setitem(block, RadioPort(lvap, block))

            else:

                # set uplink only blocks
                lvap._uplink.setitem(block, RadioPort(lvap, block))

        except ValueError:
            LOG.error("Error while importing block %s, removing.", block)
            block.radio.connection.send_del_lvap(lvap)
            return

        lvap.authentication_state = bool(status.flags.authenticated)
        lvap.association_state = bool(status.flags.associated)

        lvap._assoc_id = status.assoc_id
        lvap._encap = EtherAddress(status.encap)
        ssids = [SSID(x.ssid) for x in status.ssids]

        if lvap.ssid:

            # Raise LVAP leave event
            self.server.send_lvap_leave_message_to_self(lvap)

            # removing LVAP from tenant, need first to look for right tenant
            if lvap.addr in lvap.tenant.lvaps:
                LOG.info("Removing %s from tenant %s", lvap.addr, lvap.ssid)
                del lvap.tenant.lvaps[lvap.addr]

        lvap._tenant = None

        if ssids[0]:

            tenant = RUNTIME.load_tenant(ssids[0])

            if not tenant:
                LOG.info("LVAP %s from unknown tenant %s", lvap.addr, ssids[0])
                RUNTIME.remove_lvap(lvap.addr)
                return

            # setting tenant without seding out add lvap message
            lvap._tenant = tenant

            # adding LVAP to tenant
            LOG.info("Adding %s to tenant %s", lvap.addr, ssids[0])
            lvap.tenant.lvaps[lvap.addr] = lvap

            # Raise LVAP join event
            self.server.send_lvap_join_message_to_self(lvap)

        # update remaining ssids
        lvap._ssids = ssids[1:]

        # set ports
        lvap.set_ports()

        LOG.info("LVAP status %s", lvap)
Ejemplo n.º 29
0
    def _handle_probe_request(self, wtp, request):
        """Handle an incoming PROBE_REQUEST message.
        Args:
            request, a PROBE_REQUEST message
        Returns:
            None
        """

        if not wtp.connection:
            LOG.info("Probe request from disconnected WTP %s", wtp.addr)
            self.stream.close()
            return

        if not wtp.port():
            LOG.info("WTP %s not ready", wtp.addr)
            return

        sta = EtherAddress(request.sta)

        if sta in RUNTIME.lvaps:
            return

        if not RUNTIME.is_allowed(sta):
            return

        if RUNTIME.is_denied(sta):
            return

        ssid = SSID(request.ssid)

        if request.ssid == b'':
            LOG.info("Probe request from %s ssid %s", sta, "Broadcast")
        else:
            LOG.info("Probe request from %s ssid %s", sta, ssid)

        # generate list of available SSIDs
        ssids = set()

        for tenant in RUNTIME.tenants.values():
            if tenant.bssid_type == T_TYPE_SHARED:
                continue
            for wtp_in_tenant in tenant.wtps.values():
                if wtp.addr == wtp_in_tenant.addr:
                    ssids.add(tenant.tenant_name)

        if not ssids:
            LOG.info("No SSIDs available at this WTP")
            return

        # spawn new LVAP
        LOG.info("Spawning new LVAP %s on %s", sta, wtp.addr)
        net_bssid = generate_bssid(BASE_MAC, sta)
        lvap = LVAP(sta, net_bssid, net_bssid)
        lvap.set_ssids(list(ssids))

        # set supported band
        lvap.supported_band = request.supported_band

        # Check if block is valid
        incoming = ResourceBlock(wtp, EtherAddress(request.hwaddr),
                                 request.channel, request.band)

        valid = [block for block in wtp.supports if block == incoming]

        if not valid:
            LOG.warning("No valid intersection found. Ignoring request.")
            return

        # This will trigger an LVAP ADD message (and REMOVE if necessary)
        lvap.blocks = valid[0]

        # save LVAP in the runtime
        RUNTIME.lvaps[sta] = lvap

        LOG.info("Sending probe response to %s", lvap.addr)
        self.send_probe_response(lvap, ssid)
Ejemplo n.º 30
0
    def _handle_status_lvap(self, wtp, status):
        """Handle an incoming STATUS_LVAP message.
        Args:
            status, a STATUS_LVAP message
        Returns:
            None
        """

        if not wtp.connection:
            LOG.info("Status from disconnected WTP %s", wtp.addr)
            return

        sta = EtherAddress(status.sta)
        set_mask = bool(status.flags.set_mask)

        lvap = None

        accum = []
        incoming_ssids = [SSID(x.ssid) for x in status.ssids]

        accum.append("addr ")
        accum.append(EtherAddress(status.sta).to_str())
        accum.append(" net_bssid ")
        accum.append(EtherAddress(status.net_bssid).to_str())
        accum.append(" lvap_bssid ")
        accum.append(EtherAddress(status.lvap_bssid).to_str())

        accum.append(" ssid ")

        if incoming_ssids[0]:
            accum.append(incoming_ssids[0].to_str())
        else:
            accum.append("None")

        accum.append(" ssids [")

        for ssid in incoming_ssids[1:]:
            accum.append(" ")
            accum.append(ssid.to_str())

        accum.append(" ]")

        accum.append(" assoc_id ")
        accum.append(str(status.assoc_id))

        if bool(status.flags.authenticated):
            accum.append(" AUTH")

        if bool(status.flags.associated):
            accum.append(" ASSOC")

        LOG.info("LVAP status %s", ''.join(accum))

        # If the LVAP does not exists, then create a new one
        if sta not in RUNTIME.lvaps:

            net_bssid_addr = EtherAddress(status.net_bssid)
            lvap_bssid_addr = EtherAddress(status.lvap_bssid)
            lvap = LVAP(sta, net_bssid_addr, lvap_bssid_addr)

            RUNTIME.lvaps[sta] = lvap

        lvap = RUNTIME.lvaps[sta]

        # Check if block is valid
        incoming = ResourceBlock(wtp, EtherAddress(status.hwaddr),
                                 status.channel, status.band)

        valid = [block for block in wtp.supports if block == incoming]

        if not valid:
            LOG.warning("No valid intersection found. Removing block.")
            wtp.connection.send_del_lvap(lvap)
            return

        # this will try to updated the lvap object with the resource block
        # coming in this status update message.
        try:
            if set_mask:
                # set downlink+uplink block
                lvap._downlink.setitem(valid[0], RadioPort(lvap, valid[0]))
            else:
                # set uplink only blocks
                lvap._uplink.setitem(valid[0], RadioPort(lvap, valid[0]))
        except Exception as e:
            LOG.exception(e)
            LOG.error("Error while importing block %s, removing.", valid[0])
            wtp.connection.send_del_lvap(lvap)
            return

        # update LVAP ports
        lvap.ports[0] = VirtualPortLvap(phy_port=wtp.port(),
                                        virtual_port_id=0,
                                        lvap=lvap)

        # set supported band
        lvap.supported_band = status.supported_band

        # update LVAP params
        lvap.authentication_state = bool(status.flags.authenticated)
        lvap.association_state = bool(status.flags.associated)

        lvap._assoc_id = status.assoc_id
        lvap._encap = EtherAddress(status.encap)
        ssids = [SSID(x.ssid) for x in status.ssids]

        # update ssid
        if lvap.ssid:

            # Raise LVAP leave event
            self.server.send_lvap_leave_message_to_self(lvap)

            # removing LVAP from tenant, need first to look for right tenant
            if lvap.addr in lvap.tenant.lvaps:
                LOG.info("Removing %s from tenant %s", lvap.addr, lvap.ssid)
                del lvap.tenant.lvaps[lvap.addr]

            lvap._tenant = None

        # update remaining ssids
        lvap._ssids = ssids[1:]

        if ssids[0]:

            tenant = RUNTIME.load_tenant(ssids[0])

            if not tenant:
                LOG.info("LVAP %s from unknown tenant %s", lvap.addr, ssids[0])
                RUNTIME.remove_lvap(lvap.addr)
                return

            # setting tenant without seding out add lvap message
            lvap._tenant = tenant

            # adding LVAP to tenant
            LOG.info("Adding %s to tenant %s", lvap.addr, ssids[0])
            lvap.tenant.lvaps[lvap.addr] = lvap

            # Raise LVAP join event
            self.server.send_lvap_join_message_to_self(lvap)