예제 #1
0
    def _handle_hello(self, wtp, hello):
        """Handle an incoming HELLO message.
        Args:
            hello, a HELLO message
        Returns:
            None
        """

        LOG.info("Hello from %s WTP %s seq %u", self.addr[0], wtp.addr,
                 hello.seq)

        # New connection
        if not wtp.connection:

            # set pointer to pnfdev object
            self.wtp = wtp

            # set connection
            wtp.connection = self

        # Update WTP params
        wtp.period = hello.period
        wtp.last_seen = hello.seq
        wtp.last_seen_ts = time.time()

        # Upon connection to the controller, the WTP must be provided
        # with the list of shared VAP
        for tenant in RUNTIME.tenants.values():

            # tenant does not use shared VAPs
            if tenant.bssid_type == T_TYPE_UNIQUE:
                continue

            # wtp not in this tenant
            if wtp.addr not in tenant.wtps:
                continue

            tenant_id = tenant.tenant_id
            tokens = [tenant_id.hex[0:12][i:i + 2] for i in range(0, 12, 2)]
            base_bssid = EtherAddress(':'.join(tokens))

            for block in wtp.supports:

                net_bssid = generate_bssid(base_bssid, block.hwaddr)

                # vap has already been created
                if net_bssid in RUNTIME.tenants[tenant_id].vaps:
                    continue

                vap = VAP(net_bssid, block, wtp, tenant)

                self.send_add_vap(vap)
                RUNTIME.tenants[tenant_id].vaps[net_bssid] = vap
예제 #2
0
    def _handle_hello(self, wtp, hello):
        """Handle an incoming HELLO message.
        Args:
            hello, a HELLO message
        Returns:
            None
        """

        LOG.info("Hello from %s WTP %s seq %u", self.addr[0], wtp.addr,
                 hello.seq)

        # New connection
        if not wtp.connection:

            # set pointer to pnfdev object
            self.wtp = wtp

            # set connection
            wtp.connection = self

        # Update WTP params
        wtp.period = hello.period
        wtp.last_seen = hello.seq
        wtp.last_seen_ts = time.time()

        # Upon connection to the controller, the WTP must be provided
        # with the list of shared VAP
        for tenant in RUNTIME.tenants.values():

            # tenant does not use shared VAPs
            if tenant.bssid_type == T_TYPE_UNIQUE:
                continue

            # wtp not in this tenant
            if wtp.addr not in tenant.wtps:
                continue

            tenant_id = tenant.tenant_id
            tokens = [tenant_id.hex[0:12][i:i + 2] for i in range(0, 12, 2)]
            base_bssid = EtherAddress(':'.join(tokens))

            for block in wtp.supports:

                net_bssid = generate_bssid(base_bssid, block.hwaddr)

                # vap has already been created
                if net_bssid in RUNTIME.tenants[tenant_id].vaps:
                    continue

                vap = VAP(net_bssid, block, wtp, tenant)

                self.send_add_vap(vap)
                RUNTIME.tenants[tenant_id].vaps[net_bssid] = vap
예제 #3
0
    def __assign_downlink(self, dl_block):
        """Set the downlink block.

        Set the downlink block. Notice how this is always called before
        assigning the uplink and that if the specified dl_block is already
        defined as uplink then the agent will automatically promote the block
        to downlink."""

        # null operation
        if self.blocks and self.blocks[0] == dl_block:
            return

        # If LVAP is associated to a shared tenant, then reset LVAP
        if self._tenant and self._tenant.bssid_type == T_TYPE_SHARED:

            # check if tenant is available at target block
            base_bssid = self._tenant.get_prefix()
            net_bssid = generate_bssid(base_bssid, dl_block.hwaddr)

            # if not ignore request
            if net_bssid not in self._tenant.vaps:
                LOG.error("VAP %s not found on tenant %s", net_bssid,
                          self._tenant.tenant_name)
                return

            # otherwise reset lvap
            self._tenant = None
            self.association_state = False
            self.authentication_state = False
            self._assoc_id = 0
            self._lvap_bssid = net_bssid

        # save target block
        self.target_block = dl_block

        # clear downlink blocks
        for block in list(self._downlink.keys()):
            # this will add a new id to pending
            del self._downlink[block]

        # reset target block
        self.target_block = None

        # assign default port policy to downlink resource block, this will
        # trigger a send_add_lvap and a set_port (radio) message
        # this will add a new id to pending
        self._downlink[dl_block] = RadioPort(self, dl_block)
예제 #4
0
    def send_vaps(self):
        """Send VAPs configurations.

        Upon connection to the controller, the WTP must be provided
        with the list of shared VAPs

        Args:
            None
        Returns:
            None
        """

        for tenant in RUNTIME.tenants.values():

            # tenant does not use shared VAPs
            if tenant.bssid_type == T_TYPE_UNIQUE:
                continue

            # wtp not in this tenant
            if self.wtp.addr not in tenant.wtps:
                continue

            tenant_id = tenant.tenant_id
            tokens = [tenant_id.hex[0:12][i:i + 2] for i in range(0, 12, 2)]
            base_bssid = EtherAddress(':'.join(tokens))

            for block in self.wtp.supports:

                net_bssid = generate_bssid(base_bssid, block.hwaddr)

                # vap has already been created
                if net_bssid in RUNTIME.tenants[tenant_id].vaps:
                    continue

                vap = VAP(net_bssid, block, self.wtp, tenant)

                self.send_add_vap(vap)
                RUNTIME.tenants[tenant_id].vaps[net_bssid] = vap
예제 #5
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._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)
예제 #6
0
    def _handle_hello(self, hello):
        """Handle an incoming HELLO message.
        Args:
            hello, a HELLO message
        Returns:
            None
        """

        wtp_addr = EtherAddress(hello.wtp)

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

        LOG.info("Hello from %s seq %u", self.addr[0], hello.seq)

        # compute delta if not new connection
        if wtp.connection:

            delta = time.time() - wtp.last_seen_ts

            # uplink
            ul_bytes = hello.uplink_bytes - wtp.uplink_bytes
            wtp.uplink_bytes_per_second = int(ul_bytes / delta) * 8

            # downlink
            dl_bytes = hello.downlink_bytes - wtp.downlink_bytes
            wtp.downlink_bytes_per_second = int(dl_bytes / delta) * 8

        # If this is a new connection, then send caps request
        if not wtp.connection:
            # set wtp before connection because it is used when the
            # connection attribute of the PNFDev object is set
            self.wtp = wtp
            wtp.connection = self
            self.send_caps_request()

        # Update WTP params
        wtp.period = hello.period
        wtp.last_seen = hello.seq
        wtp.uplink_bytes = hello.uplink_bytes
        wtp.downlink_bytes = hello.downlink_bytes

        wtp.last_seen_ts = time.time()

        # Upon connection to the controller, the WTP must be provided
        # with the list of shared VAP

        for tenant in RUNTIME.tenants.values():

            # tenant does not use shared VAPs
            if tenant.bssid_type == T_TYPE_UNIQUE:
                continue

            # wtp not in this tenant
            if wtp_addr not in tenant.wtps:
                continue

            tenant_id = tenant.tenant_id
            tokens = [tenant_id.hex[0:12][i:i+2] for i in range(0, 12, 2)]
            base_bssid = EtherAddress(':'.join(tokens))

            for block in wtp.supports:

                net_bssid = generate_bssid(base_bssid, block.hwaddr)

                # vap has already been created
                if net_bssid in RUNTIME.tenants[tenant_id].vaps:
                    continue

                vap = VAP(net_bssid, block, wtp, tenant)

                self.send_add_vap(vap)
                RUNTIME.tenants[tenant_id].vaps[net_bssid] = vap
예제 #7
0
    def scheduled_on(self, downlink):
        """Assign default resource block to LVAP.

        Assign default resource block to LVAP. Accepts as input either a
        ResourcePool or a ResourceBlock. If the resource pool has more than
        one resource block then one random resource block is assigned as both
        downlink and default uplink. The remaining resource blocks are
        assigned as uplink only.

        Args:
            downlink: A ResourcePool or a ResourceBlock
        """

        # Null operation, just return
        if not downlink:
            return

        if isinstance(downlink, ResourcePool):

            pool = downlink

        elif isinstance(downlink, ResourceBlock):

            pool = ResourcePool()
            pool.add(downlink)

        else:

            raise TypeError("Expected ResourcePool, ResourceBlock, got %s",
                            type(downlink))

        current = ResourcePool(
            list(self.downlink.keys()) + list(self.uplink.keys()))

        # Null operation, just return, but before re-send configuration
        # commands (ports and of tables)
        if current == pool:
            self.set_ports()
            return

        # clear downlink blocks
        for block in list(self.downlink.keys()):
            del self.downlink[block]

        # clear uplink blocks
        for block in list(self.uplink.keys()):
            del self.uplink[block]

        # pick default resource block
        default_block = pool.pop()

        # If lvap is associated to a shared tenant. I need to reset the lvap
        # before moving it.
        if self._tenant and self._tenant.bssid_type == T_TYPE_SHARED:

            # check if tenant is available at target block
            base_bssid = self._tenant.get_prefix()
            net_bssid = generate_bssid(base_bssid, default_block.hwaddr)

            # if not ignore request
            if net_bssid not in self._tenant.vaps:
                LOG.error("VAP %s not found on tenant %s", net_bssid,
                          self._tenant.tenant_name)
                self.set_ports()
                return

            # check if vap is available at target block
            if net_bssid != self._tenant.vaps[net_bssid].net_bssid:
                LOG.error("VAP %s not available at target block %s", net_bssid,
                          default_block)
                self.set_ports()
                return

            # otherwise reset lvap
            self._tenant = None
            self.association_state = False
            self.authentication_state = False
            self._assoc_id = 0
            self._lvap_bssid = net_bssid

        else:

            self._lvap_bssid = self.net_bssid

        # assign default port policy to downlink resource block, this will
        # trigger a send_add_lvap and a set_port (radio) message
        self.downlink[default_block] = RadioPort(self, default_block)

        # assign remaining blocks (if any) to the uplink, this could
        # trigger one or more send_add_lvap and a set_port (radio) messages
        for block in pool:
            self.uplink[block] = RadioPort(self, block)

        # set ports
        self.set_ports()
예제 #8
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)
예제 #9
0
    def _handle_hello(self, hello):
        """Handle an incoming HELLO message.
        Args:
            hello, a HELLO message
        Returns:
            None
        """

        wtp_addr = EtherAddress(hello.wtp)

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

        LOG.info("Hello from %s seq %u", self.addr[0], hello.seq)

        # compute delta if not new connection
        if wtp.connection:

            delta = time.time() - wtp.last_seen_ts

            # uplink
            ul_bytes = hello.uplink_bytes - wtp.uplink_bytes
            wtp.uplink_bytes_per_second = int(ul_bytes / delta) * 8

            # downlink
            dl_bytes = hello.downlink_bytes - wtp.downlink_bytes
            wtp.downlink_bytes_per_second = int(dl_bytes / delta) * 8

        # If this is a new connection, then send caps request
        if not wtp.connection:
            # set wtp before connection because it is used when the
            # connection attribute of the PNFDev object is set
            self.wtp = wtp
            wtp.connection = self

        # Update WTP params
        wtp.period = hello.period
        wtp.last_seen = hello.seq
        wtp.uplink_bytes = hello.uplink_bytes
        wtp.downlink_bytes = hello.downlink_bytes

        wtp.last_seen_ts = time.time()

        # Upon connection to the controller, the WTP must be provided
        # with the list of shared VAP

        for tenant in RUNTIME.tenants.values():

            # tenant does not use shared VAPs
            if tenant.bssid_type == T_TYPE_UNIQUE:
                continue

            # wtp not in this tenant
            if wtp_addr not in tenant.wtps:
                continue

            tenant_id = tenant.tenant_id
            tokens = [tenant_id.hex[0:12][i:i + 2] for i in range(0, 12, 2)]
            base_bssid = EtherAddress(':'.join(tokens))

            for block in wtp.supports:

                net_bssid = generate_bssid(base_bssid, block.hwaddr)

                # vap has already been created
                if net_bssid in RUNTIME.tenants[tenant_id].vaps:
                    continue

                vap = VAP(net_bssid, block, wtp, tenant)

                self.send_add_vap(vap)
                RUNTIME.tenants[tenant_id].vaps[net_bssid] = vap
예제 #10
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)
예제 #11
0
    def downlink(self, blocks):
        """Set downlink block.

        Set the downlink block. Must receive as input a single resource block.
        """

        if isinstance(blocks, ResourcePool):
            pool = blocks
        elif isinstance(blocks, ResourceBlock):
            pool = ResourcePool()
            pool.add(blocks)
        else:
            raise TypeError("Invalid type: %s", type(blocks))

        if len(pool) > 1:
            raise ValueError("Downlink, too many blocks (%u)", len(blocks))

        current = ResourcePool(list(self._downlink.keys()))

        # Null operation, just return, but before re-send intent configuration
        if current == pool:
            self.set_ports()
            return

        # clear downlink blocks
        for block in list(self._downlink.keys()):
            del self._downlink[block]

        # downlink block
        default_block = pool.pop()

        # check if block is also in the uplink, if so remove it
        if default_block in self._uplink:
            del self._uplink[default_block]

        # If lvap is associated to a shared tenant. I need to reset the lvap
        # before moving it.
        if self._tenant and self._tenant.bssid_type == T_TYPE_SHARED:

            # check if tenant is available at target block
            base_bssid = self._tenant.get_prefix()
            net_bssid = generate_bssid(base_bssid, default_block.hwaddr)

            # if not ignore request
            if net_bssid not in self._tenant.vaps:
                LOG.error("VAP %s not found on tenant %s", net_bssid,
                          self._tenant.tenant_name)
                self.set_ports()
                return

            # check if vap is available at target block
            if net_bssid != self._tenant.vaps[net_bssid].net_bssid:
                LOG.error("VAP %s not available at target block %s", net_bssid,
                          default_block)
                self.set_ports()
                return

            # otherwise reset lvap
            self._tenant = None
            self.association_state = False
            self.authentication_state = False
            self._assoc_id = 0
            self._lvap_bssid = net_bssid

        # assign default port policy to downlink resource block, this will
        # trigger a send_add_lvap and a set_port (radio) message
        self._downlink[default_block] = RadioPort(self, default_block)

        # set ports
        self.set_ports()
예제 #12
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)
예제 #13
0
    def blocks(self, blocks):
        """Assign a list of block to the LVAP.

        Assign a list of blocks to the LVAP. Accepts as input either a list or
        a ResourceBlock. If the list has more than one ResourceBlocks, then the
        first one is assigned to the downlink and the remaining are assigned
        to the uplink.

        Args:
            blocks: A list of ResourceBlocks or a ResourceBlock
        """

        if self.pending:
            raise ValueError("Handover in progress")

        if not blocks:
            return

        if isinstance(blocks, list):
            pool = blocks
        elif isinstance(blocks, ResourceBlock):
            pool = []
            pool.append(blocks)
        else:
            raise TypeError("Invalid type: %s", type(blocks))

        for block in pool:
            if not isinstance(block, ResourceBlock):
                raise TypeError("Invalid type: %s", type(block))

        # If LVAP is associated to a shared tenant, then reset LVAP
        if self._tenant and self._tenant.bssid_type == T_TYPE_SHARED:

            # check if tenant is available at target block
            base_bssid = self._tenant.get_prefix()
            net_bssid = generate_bssid(base_bssid, pool[0].hwaddr)

            # if not ignore request
            if net_bssid not in self._tenant.vaps:
                return

            # otherwise reset lvap
            self._tenant = None
            self.association_state = False
            self.authentication_state = False
            self._assoc_id = 0
            self._lvap_bssid = net_bssid

        # clear all blocks
        self.clear_blocks(target_block=pool[0])

        # Set downlink block if different.
        self.__assign_downlink(pool[0])

        # set uplink blocks
        self.__assign_uplink(pool[1:])

        # delete all outgoing virtual link and then remove the entire port
        if self.ports:
            self.ports[0].clear()
            del self.ports[0]

        # Create a new port from scratch
        self.ports[0] = VirtualPort(virtual_port_id=0)
        for block in self.blocks:
            self.ports[0].poas.append(block.radio.port())

        # set/update intent
        intent = {
            'version': '1.0',
            'dpid': self.blocks[0].radio.port().dpid,
            'port': self.blocks[0].radio.port().port_id,
            'hwaddr': self.addr
        }

        intent_server = RUNTIME.components[IntentServer.__module__]

        if self.poa_uuid:
            intent_server.update_poa(intent, self.poa_uuid)
        else:
            self.poa_uuid = intent_server.add_poa(intent)
예제 #14
0
    def scheduled_on(self, downlink):
        """Assign default resource block to LVAP.

        Assign default resource block to LVAP. Accepts as input either a
        ResourcePool or a ResourceBlock. If the resource pool has more than
        one resource block then one random resource block is assigned as both
        downlink and default uplink. The remaining resource blocks are
        assigned as uplink only.

        Args:
            downlink: A ResourcePool or a ResourceBlock
        """

        # Null operation, just return
        if not downlink:
            return

        if isinstance(downlink, ResourcePool):

            pool = downlink

        elif isinstance(downlink, ResourceBlock):

            pool = ResourcePool()
            pool.add(downlink)

        else:

            raise TypeError("Expected ResourcePool, ResourceBlock, got %s",
                            type(downlink))

        current = ResourcePool(list(self.downlink.keys()) +
                               list(self.uplink.keys()))

        # Null operation, just return, but before re-send configuration
        # commands (ports and of tables)
        if current == pool:
            self.set_ports()
            return

        # clear downlink blocks
        for block in list(self.downlink.keys()):
            del self.downlink[block]

        # clear uplink blocks
        for block in list(self.uplink.keys()):
            del self.uplink[block]

        # pick default resource block
        default_block = pool.pop()

        # If lvap is associated to a shared tenant. I need to reset the lvap
        # before moving it.
        if self._tenant and self._tenant.bssid_type == T_TYPE_SHARED:

            # check if tenant is available at target block
            base_bssid = self._tenant.get_prefix()
            net_bssid = generate_bssid(base_bssid, default_block.hwaddr)

            # if not ignore request
            if net_bssid not in self._tenant.vaps:
                LOG.error("VAP %s not found on tenant %s", net_bssid,
                          self._tenant.tenant_name)
                self.set_ports()
                return

            # check if vap is available at target block
            if net_bssid != self._tenant.vaps[net_bssid].net_bssid:
                LOG.error("VAP %s not available at target block %s",
                          net_bssid, default_block)
                self.set_ports()
                return

            # otherwise reset lvap
            self._tenant = None
            self.association_state = False
            self.authentication_state = False
            self._assoc_id = 0
            self._lvap_bssid = net_bssid

        else:

            self._lvap_bssid = self.net_bssid

        # assign default port policy to downlink resource block, this will
        # trigger a send_add_lvap and a set_port (radio) message
        self.downlink[default_block] = RadioPort(self, default_block)

        # assign remaining blocks (if any) to the uplink, this could
        # trigger one or more send_add_lvap and a set_port (radio) messages
        for block in pool:
            self.uplink[block] = RadioPort(self, block)

        # set ports
        self.set_ports()