def delete(self, *args, **kwargs):
        """Delete slice.

        Args:
            tenant_id: network name of a tenant
            dscp: the slice DSCP

        Example URLs:
            DELETE /api/v1/tenants/52313ecb-9d00-4b7d-b873-b55d3d9ada26/slice/
              0x42
        """

        try:

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

            tenant_id = UUID(args[0])
            tenant = RUNTIME.tenants[tenant_id]

            dscp = DSCP(args[1])

            if dscp == DSCP("0x00"):
                raise ValueError("Invalid Slice")

            tenant.del_slice(dscp)

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

        self.set_status(204, None)
 def change_slices_configuration(self):
     # For each slice configuration
     for slice_descriptor_dscp in self.slices_descriptor:
         crr_dscp = DSCP(slice_descriptor_dscp)
         if crr_dscp in self.tenant.slices:
             # Check if values are the same
             if not self.same_slice_values(
                     self.slices_descriptor[slice_descriptor_dscp], self.
                     tenant.slices[crr_dscp].wifi['static-properties']):
                 # Setting a new slice to replace the values from the existing one
                 new_slice = format_slice_add_request(
                     slice_descriptor_dscp,
                     self.slices_descriptor[slice_descriptor_dscp]
                     ['quantum'],
                     self.slices_descriptor[slice_descriptor_dscp]
                     ['amsdu_aggregation'],
                     self.slices_descriptor[slice_descriptor_dscp]
                     ['scheduler'])
                 self.tenant.set_slice(DSCP(slice_descriptor_dscp),
                                       new_slice)
         else:
             # Add new ones
             new_slice = format_slice_add_request(
                 slice_descriptor_dscp,
                 self.slices_descriptor[slice_descriptor_dscp]['quantum'],
                 self.slices_descriptor[slice_descriptor_dscp]
                 ['amsdu_aggregation'],
                 self.slices_descriptor[slice_descriptor_dscp]['scheduler'])
             self.tenant.add_slice(DSCP(slice_descriptor_dscp), new_slice)
Example #3
0
    def __init__(self, dscp, tenant, descriptor):

        self.log = empower.logger.get_logger()

        self.dscp = DSCP(dscp)
        self.tenant = tenant

        self.wifi = {
            'static-properties': {
                'amsdu_aggregation': False,
                'quantum': 12000
            },
            'wtps': {}
        }

        if 'wifi' in descriptor:
            self.__parse_wifi_descriptor(descriptor)

        self.lte = {
            'static-properties': {
                'sched_id': ROUND_ROBIN_UE_SCHED,
                'rbgs': 6
            },
            'vbses': {}
        }

        if 'lte' in descriptor:
            self.__parse_lte_descriptor(descriptor)
Example #4
0
 def reset_all(self, crr_wtp_addr):
     for dscp in self.__slice_stats_handler['wtps'][crr_wtp_addr]['slices']:
         current_quantum = self.tenant.slices[DSCP(
             dscp)].wifi['static-properties']['quantum']
         if self.__maximum_quantum != current_quantum:
             self.send_slice_config_to_wtp(
                 dscp=dscp, new_quantum=self.__maximum_quantum)
Example #5
0
    def send_del_ran_mac_slice_request(self, cell, plmn_id, dscp):
        """Send an DEL_SLICE message. """

        tenant = RUNTIME.load_tenant_by_plmn_id(plmn_id)

        # check if tenant is valid
        if not tenant:
            self.log.info("Unknown tenant %s", plmn_id)
            return

        # check if slice is valid
        if dscp in tenant.slices:
            # UEs already present in the slice must be moved to the default slice
            # before deleting the current slice
            for ue in list(RUNTIME.ues.values()):

                if self.vbs == ue.vbs and dscp == ue.slice:
                    ue.slice = DSCP("0x00")
        else:
            self.log.warning("DSCP %s not found. Removing slice.", dscp)

        # Then proceed to remove the current slice
        msg = Container(plmn_id=plmn_id.to_raw(),
                        dscp=dscp.to_raw(),
                        padding=b'\x00\x00\x00',
                        length=REM_RAN_MAC_SLICE_REQUEST.sizeof())

        self.send_message(msg,
                          E_TYPE_SINGLE,
                          EP_ACT_RAN_MAC_SLICE,
                          REM_RAN_MAC_SLICE_REQUEST,
                          opcode=EP_OPERATION_REM,
                          cellid=cell.pci)
    def post(self, *args, **kwargs):
        """Add traffic rule.

        Args:
            tenant_id: network name of a tenant

        Example URLs:

            POST /api/v1/tenants/52313ecb-9d00-4b7d-b873-b55d3d9ada26/slices
            {
                "version" : 1.0,
                "dscp" : 0x40,
                "label" : "video traffic (high priority)",
                "match" : "dl_vlan=100,tp_dst=80",
            }

        """

        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")

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

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

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

            tenant_id = UUID(args[0])
            tenant = RUNTIME.tenants[tenant_id]

            dscp = DSCP(request["dscp"])
            match = Match(request["match"])

            if "priority" in request:
                tenant.add_traffic_rule(match, dscp, request["label"],
                                        request["priority"])
            else:
                tenant.add_traffic_rule(match, dscp, request["label"])

            url = "/api/v1/tenants/%s/trs/%s" % (tenant_id, match)
            self.set_header("Location", url)

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

        self.set_status(201, None)
    def get(self, *args, **kwargs):
        """List slices.

        Args:
            tenant_id: network name of a tenant
            dscp: the slice DSCP

        Example URLs:

            GET /api/v1/tenants/52313ecb-9d00-4b7d-b873-b55d3d9ada26/slices
            GET /api/v1/tenants/52313ecb-9d00-4b7d-b873-b55d3d9ada26/slices/ \
              0x40
        """

        try:

            if len(args) < 1 or len(args) > 2:
                raise ValueError("Invalid url")

            tenant_id = UUID(args[0])
            tenant = RUNTIME.tenants[tenant_id]

            if len(args) == 1:
                self.write_as_json(tenant.slices.values())
            else:
                dscp = DSCP(args[1])
                self.write_as_json(tenant.slices[dscp])

        except ValueError as ex:
            self.send_error(400, message=ex)
        except KeyError as ex:
            self.send_error(404, message=ex)
Example #8
0
    def __init__(self, ue_id, rnti, imsi, tmsi, cell, tenant):

        # read only parameters
        self.ue_id = ue_id
        self.tenant = tenant
        self.imsi = imsi
        self.tmsi = tmsi

        # set on different situations, e.g. after an handover
        self.rnti = rnti

        # the current cell
        self._cell = cell

        # current slice to which the UE is subscribed
        self._slice = DSCP("0x00")

        # the ue state
        self._state = PROCESS_RUNNING

        # target cell to be used for handover
        self.target_cell = None

        # migration sats
        self._timer = None

        # the ue measurements, this is set by a ue_measurement module
        self.ue_measurements = {}

        # logger :)
        self.log = empower.logger.get_logger()
Example #9
0
    def slice(self, slice_id):
        """Assign a slice to the UE. Accepts as input an Slice ID

        Args:
            slice_id: An Slice ID
        """

        slice_id = DSCP(slice_id)

        if slice_id not in self.tenant.slices:
            raise ValueError("Slice %u not found" % slice_id)

        self._slice = slice_id

        for slc in self.tenant.slices.values():

            rntis = list()

            for ue in self.tenant.ues.values():

                if self.vbs != ue.vbs:
                    break

                if slc.dscp == ue.slice:
                    rntis.append(ue.rnti)

            for cell in self.vbs.cells.values():
                self.vbs.connection.\
                    send_add_set_ran_mac_slice_request(cell,
                                                       slc,
                                                       EP_OPERATION_SET,
                                                       rntis)
Example #10
0
 def dscp(self, value):
     """Set DSCP"""
     try:
         self.__dscp = DSCP(value)
     except:
         raise ValueError("Invalid value for dscp!")
         self.__dscp = None
Example #11
0
    def __init__(self, dscp, tenant, descriptor):

        self.log = empower.logger.get_logger()

        self.dscp = DSCP(dscp)
        self.tenant = tenant

        self.wifi = {
            'static-properties': {
                'amsdu_aggregation': False,
                'quantum': 12000,
                'scheduler': WIFI_SLICE_SCHED['ROUND_ROBIN']
            },
            'wtps': {}
        }

        if 'wifi' in descriptor:
            self.__parse_wifi_descriptor(descriptor)

        self.lte = {
            'static-properties': {
                'sched_id': LTE_SLICE_SCHED['ROUND_ROBIN_UE_SCHED'],
                'rbgs': 6,
                'window': 1,
                'period': 1
            },
            'vbses': {}
        }

        if 'lte' in descriptor:
            self.__parse_lte_descriptor(descriptor)
    def _handle_status_slice(self, wtp, status):
        """Handle an incoming STATUS_SLICE message.
        Args:
            status, a STATUS_SLICE message
        Returns:
            None
        """

        dscp = DSCP(status.dscp)
        ssid = SSID(status.ssid)

        tenant = RUNTIME.load_tenant(ssid)

        if not tenant:
            self.log.info("Slice status from unknown tenant %s", ssid)
            return

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

        if not valid:
            self.log.warning("No valid intersection found.")
            return

        # check if slice is valid
        if dscp not in tenant.slices:
            self.log.warning("DSCP %s not found. Removing slice.", dscp)
            self.send_del_slice(valid[0], ssid, dscp)
            return

        slc = tenant.slices[dscp]

        if slc.wifi['static-properties']['quantum'] != status.quantum:

            if wtp.addr not in slc.wifi['wtps']:
                slc.wifi['wtps'][wtp.addr] = {'static-properties': {}}

                slc.wifi['wtps'][wtp.addr]['static-properties']['quantum'] = \
                status.quantum

        if slc.wifi['static-properties']['amsdu_aggregation'] != \
            bool(status.flags.amsdu_aggregation):

            if wtp.addr not in slc.wifi['wtps']:
                slc.wifi['wtps'][wtp.addr] = {'static-properties': {}}

            slc.wifi['wtps'][wtp.addr]['static-properties'] \
                ['amsdu_aggregation'] = bool(status.flags.amsdu_aggregation)

        if slc.wifi['static-properties']['scheduler'] != status.scheduler:

            if wtp.addr not in slc.wifi['wtps']:
                slc.wifi['wtps'][wtp.addr] = {'static-properties': {}}

                slc.wifi['wtps'][wtp.addr]['static-properties']['scheduler'] = \
                status.scheduler

        self.log.info("Slice %s updated", slc)
    def _handle_ran_mac_slice_response(self, vbs, hdr, event, msg):
        """Handle an incoming RAN_MAC_SLICE message.
        Args:
            status, a RAN_MAC_SLICE messagge
        Returns:
            None
        """

        dscp = DSCP(msg.dscp)
        plmn_id = PLMNID(msg.plmn_id)

        tenant = RUNTIME.load_tenant_by_plmn_id(plmn_id)

        # check if tenant is valid
        if not tenant:
            self.log.info("Unknown tenant %s", plmn_id)
            return

        # check if slice is valid
        if dscp not in tenant.slices:
            self.log.warning("DSCP %s not found. Removing slice.", dscp)
            # self.send_del_slice(valid[0], ssid, dscp)
            return

        slc = tenant.slices[dscp]

        if vbs.addr not in slc.lte['vbses']:
            slc.lte['vbses'][vbs.addr] = \
                {'static-properties': {}, 'runtime-properties': {}, 'cells': {}}

        if hdr.cellid not in slc.lte['vbses'][vbs.addr]['cells']:
            slc.lte['vbses'][vbs.addr]['cells'][hdr.cellid] = {}

        for raw_cap in msg.options:

            if raw_cap.type not in RAN_MAC_SLICE_TYPES:
                self.log.warning("Unknown options %u", raw_cap.type)
                continue

            prop = RAN_MAC_SLICE_TYPES[raw_cap.type].name
            option = RAN_MAC_SLICE_TYPES[raw_cap.type].parse(raw_cap.data)

            self.log.warning("Processing options %s", prop)

            if raw_cap.type == EP_RAN_MAC_SLICE_SCHED_ID:
                slc.lte['vbses'][vbs.addr] \
                    ['static-properties']['sched_id'] = option.sched_id

            if raw_cap.type == EP_RAN_MAC_SLICE_RBGS:
                slc.lte['vbses'][vbs.addr]['static-properties']['rbgs'] = \
                    option.rbgs

            if raw_cap.type == EP_RAN_MAC_SLICE_RNTI_LIST:
                slc.lte['vbses'][vbs.addr]['runtime-properties']['rntis'] = \
                    option.rntis

        self.log.info("Slice %s updated", slc)
    def __init__(self):

        super().__init__()

        # parameters
        self._block = None
        self._dscp = DSCP()

        # data structures
        self.slice_stats = {}
Example #15
0
 def send_slice_config_to_wtp(self):
     if self.__dscp is not None:
         if self.__quantum is None:
             # get current quantum
             self.__quantum = self.tenant.slices[DSCP(
                 self.__dscp)].wifi['static-properties']['quantum']
         if self.__amsdu is None:
             self.__amsdu = self.tenant.slices[DSCP(
                 self.__dscp
             )].wifi['static-properties']['amsdu_aggregation']
         if self.__wtp_addr is None:
             new_slice = format_slice_config_request(
                 tenant_id=self.tenant_id,
                 dscp=self.__dscp,
                 default_quantum=self.__quantum,
                 default_amsdu=self.__amsdu,
                 default_scheduler=self.__scheduler,
                 wtps=None)
         else:
             wtp = [{
                 'addr': self.__wtp_addr,
                 'quantum': self.__quantum,
                 'amsdu_aggregation': self.__amsdu,
                 'scheduler': self.__scheduler,
             }]
             new_slice = format_slice_config_request(
                 tenant_id=self.tenant_id,
                 dscp=self.__dscp,
                 default_quantum=self.tenant.slices[DSCP(
                     self.__dscp)].wifi['static-properties']['quantum'],
                 default_amsdu=self.tenant.slices[DSCP(
                     self.__dscp)].wifi['static-properties']
                 ['amsdu_aggregation'],
                 default_scheduler=self.tenant.slices[DSCP(
                     self.__dscp)].wifi['static-properties']['scheduler'],
                 wtps=wtp)
         self.log.debug("Sending new slice configurations to APs")
         self.tenant.set_slice(self.__dscp, new_slice)
         self.reset_slice_parameters()
     else:
         self.log.debug(
             "DSCP or quantum is not set, aborting configuration!")
Example #16
0
    def add_tenant(self,
                   owner,
                   desc,
                   tenant_name,
                   bssid_type,
                   tenant_id=None,
                   plmn_id=None):
        """Create new Tenant."""

        if tenant_id in self.tenants:
            raise ValueError("Tenant %s exists" % tenant_id)

        plmn_ids = [tenant.plmn_id for tenant in self.tenants.values()]

        if plmn_id and plmn_id in plmn_ids:
            raise ValueError("PLMN ID %s exists" % plmn_id)

        if bssid_type not in T_TYPES:
            raise ValueError("Invalid bssid_type %s" % bssid_type)

        session = Session()

        if tenant_id:
            request = TblTenant(tenant_id=tenant_id,
                                tenant_name=tenant_name,
                                owner=owner,
                                desc=desc,
                                bssid_type=bssid_type,
                                plmn_id=plmn_id)
        else:
            request = TblTenant(owner=owner,
                                tenant_name=tenant_name,
                                desc=desc,
                                bssid_type=bssid_type,
                                plmn_id=plmn_id)

        session.add(request)
        session.commit()

        self.tenants[request.tenant_id] = \
            Tenant(request.tenant_id,
                   request.tenant_name,
                   self.accounts[owner].username,
                   desc,
                   request.bssid_type,
                   request.plmn_id)

        # create default queue
        dscp = DSCP()
        descriptor = {}

        self.tenants[request.tenant_id].add_slice(dscp, descriptor)

        return request.tenant_id
    def post(self, *args, **kwargs):
        """Add a new slice.

        Check Slice object documentation for descriptors examples.

        Args:
            tenant_id: network name of a tenant
            dscp: the slice DSCP (optional)

        Example URLs:
            POST /api/v1/tenants/52313ecb-9d00-4b7d-b873-b55d3d9ada26/slices
        """

        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")

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

            tenant_id = UUID(args[0])
            tenant = RUNTIME.tenants[tenant_id]

            dscp = DSCP(request["dscp"])

            if dscp in tenant.slices:
                raise ValueError("slice already registered in this tenant")

            tenant.add_slice(dscp, request)

            url = "/api/v1/tenants/%s/slices/%s" % (tenant_id, dscp)
            self.set_header("Location", url)

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

        self.set_status(201, None)
Example #18
0
 def reconfigure(self, factor, crr_wtp_addr):
     for be_dscp in self.__active_flows_handler['be_slices']:
         if be_dscp in self.__slice_stats_handler['wtps'][crr_wtp_addr][
                 'slices']:
             slice = self.__slice_stats_handler['wtps'][crr_wtp_addr][
                 'slices'][be_dscp]
             # only if the slice active...
             if slice['tx_bytes'] > 0:
                 current_quantum = self.tenant.slices[DSCP(
                     be_dscp)].wifi['static-properties']['quantum']
                 adapted_quantum = int(current_quantum * factor)
                 if adapted_quantum > self.__maximum_quantum:
                     adapted_quantum = self.__maximum_quantum
                 if adapted_quantum < self.__minimum_quantum:
                     adapted_quantum = self.__minimum_quantum
                 if adapted_quantum != current_quantum:
                     self.send_slice_config_to_wtp(
                         dscp=be_dscp, new_quantum=adapted_quantum)
Example #19
0
    def send_ran_mac_slice_request(self,
                                   cell_id,
                                   plmn_id=PLMNID(),
                                   dscp=DSCP()):
        """Send a STATUS_SLICE_REQUEST message.
        Args:
            None
        Returns:
            None
        """

        msg = Container(length=RAN_MAC_SLICE_REQUEST.sizeof(),
                        plmn_id=plmn_id.to_raw(),
                        dscp=dscp.to_raw(),
                        padding=b'\x00\x00\x00')

        self.send_message(msg,
                          E_TYPE_SINGLE,
                          EP_ACT_RAN_MAC_SLICE,
                          RAN_MAC_SLICE_REQUEST,
                          cellid=cell_id)
    def put(self, *args, **kwargs):
        """Modify slice.

        Check Slice object documentation for descriptors examples.

        Args:
            tenant_id: network name of a tenant
            dscp: the slice DSCP (optional)

        Example URLs:
            PUT /api/v1/tenants/52313ecb-9d00-4b7d-b873-b55d3d9ada26/slices/
                0x42
        """

        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(args[0])
            tenant = RUNTIME.tenants[tenant_id]

            dscp = DSCP(args[1])

            tenant.set_slice(dscp, request)

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

        self.set_status(204, None)
Example #21
0
    def _handle_ran_mac_slice_response(self, vbs, hdr, event, msg):
        """Handle an incoming RAN_MAC_SLICE message.
        Args:
            status, a RAN_MAC_SLICE messagge
        Returns:
            None
        """

        dscp = DSCP(msg.dscp)
        plmn_id = PLMNID(msg.plmn_id)

        tenant = RUNTIME.load_tenant_by_plmn_id(plmn_id)

        # check if tenant is valid
        if not tenant:
            self.log.info("Unknown tenant %s", plmn_id)
            return

        # check if slice is valid
        if dscp not in tenant.slices:
            self.log.warning("DSCP %s not found. Removing slice.", dscp)

            cell = vbs.cells[hdr.cellid]
            self.send_del_ran_mac_slice_request(cell, plmn_id, dscp)

            return

        slc = tenant.slices[dscp]

        for raw_cap in msg.options:

            if raw_cap.type not in RAN_MAC_SLICE_TYPES:
                self.log.warning("Unknown options %u", raw_cap.type)
                continue

            prop = RAN_MAC_SLICE_TYPES[raw_cap.type].name
            option = RAN_MAC_SLICE_TYPES[raw_cap.type].parse(raw_cap.data)

            self.log.warning("Processing options %s", prop)

            if raw_cap.type == EP_RAN_MAC_SLICE_SCHED_ID:

                if option.sched_id != slc.lte['static-properties']['sched_id']:

                    if vbs.addr not in slc.lte['vbses']:
                        slc.lte['vbses'][vbs.addr] = {
                            'static-properties': {}
                        }

                    slc.lte['vbses'][vbs.addr] \
                        ['static-properties']['sched_id'] = option.sched_id

            if raw_cap.type == EP_RAN_MAC_SLICE_RBGS:

                if option.rbgs != slc.lte['static-properties']['rbgs']:

                    if vbs.addr not in slc.lte['vbses']:
                        slc.lte['vbses'][vbs.addr] = {
                            'static-properties': {}
                        }

                    slc.lte['vbses'][vbs.addr] \
                        ['static-properties']['rbgs'] = option.rbgs

            if raw_cap.type == EP_RAN_MAC_SLICE_RNTI_LIST:

                rntis = option.rntis

                for ue in list(tenant.ues.values()):

                    if ue.vbs != vbs:
                        continue

                    # if the UE was attached to this slice, but it is not
                    # in the information given by the eNB, it should be
                    # deleted.
                    if slc.dscp in ue.slices and ue.rnti not in rntis:
                        ue.remove_slice(slc.dscp)

                    # if the UE was not attached to this slice, but its RNTI
                    # is provided by the eNB for this slice, it should added.
                    if slc.dscp not in ue.slices and ue.rnti in rntis:
                        ue.add_slice(slc.dscp)

        self.log.info("Slice %s updated", slc)
Example #22
0
 def send_slice_config_to_wtp(self, dscp, new_quantum):
     new_slice = sliceconfigrequest.format_slice_config_request(
         tenant_id=self.tenant_id, dscp=dscp, default_quantum=new_quantum)
     self.log.debug("Sending new slice configurations to APs")
     self.tenant.set_slice(DSCP(dscp), new_slice)
Example #23
0
    def slices(self, slices):
        """Assign a list slices to the UE. Accepts as input either an Slice ID
            or a list of Slice IDs.

        Args:
            slices: A list of Slice IDs or a Slice ID
        """

        if not slices:
            return

        if isinstance(slices, list):
            slice_pool = [DSCP(x) for x in slices]
        else:
            slice_pool = [DSCP(slices)]

        for slc in slice_pool:
            if not isinstance(slc, DSCP):
                raise TypeError("Invalid type: %s" % type(slc))

        for slc_id in slice_pool:

            current_rntis = []
            slc = self.tenant.slices[slc_id]

            # If an slice has been added to a UE, the VBS must be updated.
            if slc_id in self.slices:
                continue

            current_rntis = [self.rnti]

            for ue in list(self.tenant.ues.values()):
                if self.vbs == ue.vbs and slc_id in ue.slices:
                    current_rntis.append(ue.rnti)

            for cell in self.vbs.cells.values():

                self.vbs.connection.\
                    send_add_set_ran_mac_slice_request(cell,
                                                       slc,
                                                       EP_OPERATION_SET,
                                                       current_rntis)

        # If it has been removed, the RNTI must not notified to the VBS.
        for slc_id in self.slices:

            if slc_id in slice_pool:
                continue

            current_rntis = []
            slc = self.tenant.slices[slc_id]

            for ue in list(RUNTIME.ues.values()):

                if ue == self:
                    continue

                if self.vbs == ue.vbs and slc_id in ue.slices:
                    current_rntis.append(ue.rnti)

            for cell in self.vbs.cells.values():

                self.vbs.connection.\
                    send_add_set_ran_mac_slice_request(cell,
                                                       slc,
                                                       EP_OPERATION_SET,
                                                       current_rntis)

        self._slices = slice_pool
 def dscp(self, value):
     self._dscp = DSCP(value)
Example #25
0
    def slice_stats_callback(self, slice_stats):
        """ New stats available. """
        crr_wtp_addr = str(slice_stats.block.addr)
        crr_dscp = str(slice_stats.dscp)

        if crr_wtp_addr not in self.__slice_stats_handler['wtps']:
            self.__slice_stats_handler['wtps'][crr_wtp_addr] = {
                'slices': {},
                'overall': {
                    'queue_delay_ms': {
                        "values": [],
                        "mean": None,
                        "median": None,
                        "stdev": None
                    },
                    'throughput_mbps': {
                        "values": [],
                        "mean": None,
                        "median": None,
                        "stdev": None
                    }
                }
            }

        if crr_dscp not in self.__slice_stats_handler['wtps'][crr_wtp_addr][
                'slices']:
            self.__slice_stats_handler['wtps'][crr_wtp_addr]['slices'][
                crr_dscp] = {
                    'tx_bytes': 0,
                    'tx_packets': 0,
                    'throughput_mbps': {
                        "values": [],
                        "mean": None,
                        "median": None,
                        "stdev": None
                    },
                    'deficit_used': None,
                    'deficit_avg': None,
                    'deficit': None,
                    'queue_delay_ms': {
                        "values": [],
                        "mean": None,
                        "median": None,
                        "stdev": None
                    },
                    'max_queue_length': None,
                    'crr_queue_length': None,
                    'tx_bytes_moving': [],
                    'tx_packets_moving': []
                }

        # Computing TX metrics...
        for metric in self.__tx_metrics:
            self.__slice_stats_handler['wtps'][crr_wtp_addr]['slices'][
                crr_dscp][metric + '_moving'].append(
                    slice_stats.to_dict()['slice_stats'][metric])

            if len(self.__slice_stats_handler['wtps'][crr_wtp_addr]['slices']
                   [crr_dscp][metric + '_moving']) >= 2:
                # Calculate diff
                self.__slice_stats_handler['wtps'][crr_wtp_addr]['slices'][crr_dscp][metric] = \
                    self.__slice_stats_handler['wtps'][crr_wtp_addr]['slices'][crr_dscp][
                        metric + '_moving'][1] - \
                    self.__slice_stats_handler['wtps'][crr_wtp_addr]['slices'][crr_dscp][
                        metric + '_moving'][0]

                self.__slice_stats_handler['wtps'][crr_wtp_addr]['slices'][
                    crr_dscp][metric + '_moving'].pop(0)

        # Computing TX megabits
        crr_tx_megabits = self.__slice_stats_handler['wtps'][crr_wtp_addr][
            'slices'][crr_dscp]['tx_bytes'] / 125000  # from bytes to megabits

        # Computing throughput metric...
        crr_throughput_mbps = 0
        if self.__slice_stats_handler['wtps'][crr_wtp_addr]['slices'][
                crr_dscp]['tx_bytes'] > 0:
            crr_throughput_mbps = self.__slice_stats_handler['wtps'][
                crr_wtp_addr]['slices'][crr_dscp][
                    'tx_bytes'] / 1000 / 1000 * 8  # from bytes to Mbps
        self.__slice_stats_handler['wtps'][crr_wtp_addr]['slices'][crr_dscp][
            'throughput_mbps']['values'].append(crr_throughput_mbps)

        crr_queue_delay_ms = 0
        if self.__slice_stats_handler['wtps'][crr_wtp_addr]['slices'][
                crr_dscp]['tx_bytes'] > 0:
            crr_queue_delay_sec = slice_stats.to_dict()['slice_stats'][
                'queue_delay_sec']  # getting seconds...
            crr_queue_delay_ms = slice_stats.to_dict(
            )['slice_stats']['queue_delay_usec'] / 1000  # from usec to ms
            crr_queue_delay_ms += crr_queue_delay_sec * 1000  # from sec to ms
        self.__slice_stats_handler['wtps'][crr_wtp_addr]['slices'][crr_dscp][
            'queue_delay_ms']['values'].append(crr_queue_delay_ms)

        for metric in self.__moving_window_metrics:
            if len(self.__slice_stats_handler['wtps'][crr_wtp_addr]['slices']
                   [crr_dscp][metric]['values']) > 10:
                self.__slice_stats_handler['wtps'][crr_wtp_addr]['slices'][
                    crr_dscp][metric]['values'].pop(0)

            if len(self.__slice_stats_handler['wtps'][crr_wtp_addr]['slices']
                   [crr_dscp][metric]['values']) >= 2:
                # Mean
                self.__slice_stats_handler['wtps'][crr_wtp_addr]['slices'][
                    crr_dscp][metric]['mean'] = statistics.mean(
                        self.__slice_stats_handler['wtps'][crr_wtp_addr]
                        ['slices'][crr_dscp][metric]['values'])

                # Median
                self.__slice_stats_handler['wtps'][crr_wtp_addr]['slices'][
                    crr_dscp][metric]['median'] = statistics.median(
                        self.__slice_stats_handler['wtps'][crr_wtp_addr]
                        ['slices'][crr_dscp][metric]['values'])

                # STDEV
                self.__slice_stats_handler['wtps'][crr_wtp_addr]['slices'][
                    crr_dscp][metric]['stdev'] = statistics.stdev(
                        self.__slice_stats_handler['wtps'][crr_wtp_addr]
                        ['slices'][crr_dscp][metric]['values'])

        # Computing queue delay metric...
        for metric in self.__raw_metrics:
            if self.slice_stats_handler['wtps'][crr_wtp_addr]['slices'][
                    crr_dscp]['tx_bytes'] == 0:
                self.slice_stats_handler['wtps'][crr_wtp_addr]['slices'][
                    crr_dscp][metric] = 0
            else:
                self.slice_stats_handler['wtps'][crr_wtp_addr]['slices'][crr_dscp][metric] = \
                slice_stats.to_dict()['slice_stats'][metric]

        # Update wtp counters
        self.update_wtp_overall_counters(crr_wtp_addr=crr_wtp_addr)

        # Saving slice stats into db
        if self.__db_monitor is not None:

            # If there is a specific slice configuration for this WTP
            if EtherAddress(crr_wtp_addr) in self.tenant.slices[DSCP(
                    crr_dscp)].wifi['wtps']:
                crr_quantum = self.tenant.slices[DSCP(crr_dscp)].wifi['wtps'][
                    EtherAddress(crr_wtp_addr)]['static-properties']['quantum']
            else:
                crr_quantum = self.tenant.slices[DSCP(
                    crr_dscp)].wifi['static-properties']['quantum']

            fields = [
                'WTP_ADDR', 'DSCP', 'WTP_DSCP', 'DEFICIT', 'DEFICIT_AVG',
                'DEFICIT_USED', 'MAX_QUEUE_LENGTH', 'CRR_QUEUE_LENGTH',
                'CURRENT_QUANTUM', 'QUEUE_DELAY_MSEC', 'TX_BYTES',
                'TX_PACKETS', 'TX_MBITS', 'THROUGHPUT_MBPS'
            ]
            values = [
                str(crr_wtp_addr),
                str(crr_dscp),
                'WTP: ' + str(crr_wtp_addr) + ' - Slice: ' + str(crr_dscp),
                self.__slice_stats_handler['wtps'][crr_wtp_addr]['slices']
                [crr_dscp]['deficit'], self.__slice_stats_handler['wtps']
                [crr_wtp_addr]['slices'][crr_dscp]['deficit_avg'],
                self.__slice_stats_handler['wtps'][crr_wtp_addr]['slices']
                [crr_dscp]['deficit_used'], self.__slice_stats_handler['wtps']
                [crr_wtp_addr]['slices'][crr_dscp]['max_queue_length'],
                self.__slice_stats_handler['wtps'][crr_wtp_addr]['slices']
                [crr_dscp]['crr_queue_length'], crr_quantum,
                crr_queue_delay_ms, self.__slice_stats_handler['wtps']
                [crr_wtp_addr]['slices'][crr_dscp]['tx_bytes'],
                self.__slice_stats_handler['wtps'][crr_wtp_addr]['slices']
                [crr_dscp]['tx_packets'], crr_tx_megabits, crr_throughput_mbps
            ]

            # Saving into db
            self.monitor.insert_into_db(table='slice_stats',
                                        fields=fields,
                                        values=values)