def post(self, *args, **kwargs):
        """Create a new tenant.

        Args:
            [0], the tenant id

        Request:
            version: protocol version (1.0)
            owner: the username of the requester
            tenant_name: the network name
            desc: a description for the new tenant
            bssid_type: shared or unique
            plmn_id: the PLMN id
        """

        bssid_type = kwargs["bssid_type"] \
            if "bssid_type" in kwargs else T_TYPE_UNIQUE

        plmn_id = PLMNID(kwargs["plmn_id"]) if "plmn_id" in kwargs else None

        tenant_id = UUID(args[0]) if args else None

        RUNTIME.add_tenant(kwargs['owner'], kwargs['desc'],
                           kwargs['tenant_name'], bssid_type, tenant_id,
                           plmn_id)

        self.set_header("Location", "/api/v1/tenants/%s" % tenant_id)
    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)
示例#3
0
    def _handle_ue_report_response(self, vbs, hdr, event, ue_report):
        """Handle an incoming UE_REPORT message.
        Args:
            hello, a UE_REPORT message
        Returns:
            None
        """

        incoming = []

        for ue in ue_report.ues:

            if RUNTIME.find_ue_by_rnti(ue.rnti, ue.pci, vbs):
                continue

            plmn_id = PLMNID(ue.plmn_id[1:].hex())
            tenant = RUNTIME.load_tenant_by_plmn_id(plmn_id)

            if not tenant:
                self.log.info("Unable to find PLMN id %s", plmn_id)
                continue

            if vbs.addr not in tenant.vbses:
                self.log.info("VBS %s not in PLMN id %s", vbs.addr, plmn_id)
                continue

            cell = vbs.get_cell_by_pci(ue.pci)

            if not cell:
                self.log.info("PCI %u not found", u.pci)
                continue

            if ue.imsi != 0:
                ue_id = uuid.uuid5(uuid.NAMESPACE_DNS, str(ue.imsi))
            else:
                ue_id = uuid.uuid4()

            ue = UE(ue_id, ue.imsi, ue.rnti, cell, plmn_id, tenant)
            ue.set_active()

            RUNTIME.ues[ue.ue_id] = ue
            tenant.ues[ue.ue_id] = ue

            incoming.append(ue.ue_id)

            self.server.send_ue_join_message_to_self(ue)

        # check for leaving UEs
        for ue_id in list(RUNTIME.ues.keys()):
            if RUNTIME.ues[ue_id].vbs != vbs:
                continue
            if not RUNTIME.ues[ue_id].is_active():
                self.log.info("Handover in progress for %u, ignoring", ue_id)
                continue
            if ue_id not in incoming:
                RUNTIME.remove_ue(ue_id)
示例#4
0
    def _handle_ue_report_response(self, vbs, hdr, event, msg):
        """Handle an incoming UE_REPORT message.
        Args:
            hello, a UE_REPORT message
        Returns:
            None
        """

        for raw_entry in msg.options:

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

            prop = UE_REPORT_TYPES[raw_entry.type].name
            option = UE_REPORT_TYPES[raw_entry.type].parse(raw_entry.data)

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

            if raw_entry.type == EP_UE_REPORT_IDENTITY:

                plmn_id = PLMNID(option.plmn_id)
                tenant = RUNTIME.load_tenant_by_plmn_id(plmn_id)

                if not tenant:
                    self.log.info("Unknown tenant %s", plmn_id)
                    continue

                # TODO: Implement fallback mechanism IMSI->TMSI->RNTI
                ue_id = uuid.UUID(int=option.imsi)

                # UE already known, update its parameters
                if ue_id in RUNTIME.ues:

                    ue = RUNTIME.ues[ue_id]
                    ue.rnti = option.rnti

                    # UE is disconnecting
                    if option.state == 1:
                        RUNTIME.remove_ue(ue_id)

                else:

                    cell = vbs.cells[hdr.cellid]

                    ue = UE(ue_id, option.rnti, option.imsi, option.timsi,
                            cell, tenant)

                    RUNTIME.ues[ue.ue_id] = ue
                    tenant.ues[ue.ue_id] = ue

                    # UE is connected
                    if option.state == 0:
                        self.server.send_ue_join_message_to_self(ue)
示例#5
0
    def _handle_ue_report_response(self, vbs, hdr, event, ue_report):
        """Handle an incoming UE_REPORT message.
        Args:
            hello, a UE_REPORT message
        Returns:
            None
        """

        ues = {u.imsi: u for u in ue_report.ues}

        # check for new UEs
        for u in ues.values():

            # UE already known
            if u.imsi in RUNTIME.ues:
                continue

            plmn_id = PLMNID(u.plmn_id[1:].hex())
            tenant = RUNTIME.load_tenant_by_plmn_id(plmn_id)

            if not tenant:
                self.log.info("Unable to find PLMN id %s", plmn_id)
                continue

            if vbs.addr not in tenant.vbses:
                self.log.info("VBS %s not in PLMN id %s", vbs.addr, plmn_id)
                continue

            cell = None

            for c in vbs.cells:
                if c.pci == u.pci:
                    cell = c
                    break

            if not cell:
                self.log.info("PCI %u not found", u.pci)
                continue

            ue = UE(u.imsi, u.rnti, cell, plmn_id, tenant)
            ue.set_active()

            RUNTIME.ues[u.imsi] = ue
            tenant.ues[u.imsi] = ue

            self.server.send_ue_join_message_to_self(ue)

        # check for leaving UEs
        for imsi in list(RUNTIME.ues.keys()):
            if RUNTIME.ues[imsi].vbs != vbs:
                continue
            if imsi not in ues:
                RUNTIME.remove_ue(imsi)
示例#6
0
    def _handle_ue_report_response(self, vbs, hdr, event, ue_report):
        """Handle an incoming UE_REPORT message.
        Args:
            hello, a UE_REPORT message
        Returns:
            None
        """

        LOG.info("UE report from %s VBS %s seq %u", self.addr[0], vbs.addr,
                 hdr.seq)

        ues = {u.imsi: u for u in ue_report.ues}

        for u in ues.values():

            plmn_id = PLMNID(u.plmn_id[1:].hex())
            tenant = RUNTIME.load_tenant_by_plmn_id(plmn_id)

            if not tenant:
                LOG.info("Unable to find PLMN id %s", plmn_id)
                continue

            if vbs.addr not in tenant.vbses:
                LOG.info("VBS %s not in PLMN id %s", vbs.addr, plmn_id)
                continue

            cell = None

            for c in vbs.cells:
                if c.pci == u.pci:
                    cell = c

            if not cell:
                LOG.info("PCI %u not found", u.pci)
                continue

            ue = UE(u.imsi, u.rnti, cell, plmn_id, tenant)

            new_ue = False

            if u.imsi not in RUNTIME.ues:
                new_ue = True

            RUNTIME.ues[u.imsi] = ue
            tenant.ues[u.imsi] = ue

            if new_ue:
                self.server.send_ue_join_message_to_self(ue)

        for ue in RUNTIME.ues.values():
            if ue.imsi not in ues:
                self.server.send_ue_leave_message_to_self(ue)
示例#7
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)
示例#8
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)
示例#9
0
    def _handle_ue_report_response(self, vbs, hdr, event, msg):
        """Handle an incoming UE_REPORT message.
        Args:
            hello, a UE_REPORT message
        Returns:
            None
        """

        for raw_entry in msg.options:

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

            prop = UE_REPORT_TYPES[raw_entry.type].name
            option = UE_REPORT_TYPES[raw_entry.type].parse(raw_entry.data)

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

            if raw_entry.type == EP_UE_REPORT_IDENTITY:

                # NOTE: These ID generation should fallback to a data-type like for PLMNID
                imsi_id = uuid.UUID(int=option.imsi)
                tmsi_id = uuid.UUID(int=option.tmsi)

                # VBS can have multiple carriers (cells), and each carrier can allocate
                # its own RNTI range independently. This means that on UUID generation
                # by RNTI you can get multiple different UEs with the same UUID if only
                # RNTI is considered. This gives to the ID a little of context.
                rnti_id = uuid.UUID(int=vbs.addr.to_int() << 32
                                    | hdr.cellid << 16 | option.rnti)

                plmn_id = PLMNID(option.plmn_id)
                tenant = RUNTIME.load_tenant_by_plmn_id(plmn_id)

                if not tenant:
                    self.log.info("Unknown tenant %s", plmn_id)
                    continue

                # Basic fallback mechanism for UE unique ID generation
                #
                # IMSI
                #   UE ID is generated using the Subscriber Identity, thus it
                #   will remain stable through multiple connection/disconnection
                if option.imsi != 0:
                    ue_id = imsi_id

                # TMSI
                #   UE ID is generated using Temporary ID assigned by the Core
                #   Network, and will be stable depending on the CN ID generation
                #   behavior
                elif option.tmsi != 0:
                    ue_id = tmsi_id

                # RNTI
                #   UE ID is generated using the Radio Network Temporary
                #   Identifier. This means that at any event where such identifier
                #   is changed update, the UE ID will potentially will change too
                else:
                    ue_id = rnti_id

                # UE already known, update its parameters
                if ue_id in RUNTIME.ues:

                    ue = RUNTIME.ues[ue_id]

                    # RNTI must always be set, but just in case handle the event
                    if option.rnti != 0:
                        ue.rnti = option.rnti
                    else:
                        self.log.info("UE is missing RNTI identifier!")
                        continue

                    # Update the TMSI if has been renew for some reason
                    if option.tmsi != 0:
                        ue.tmsi = option.tmsi

                    # Fill IMSI only if it was not previously set
                    if option.imsi != 0 and ue.imsi != 0:
                        ue.imsi = option.imsi

                    # UE is disconnecting
                    if option.state == 1:
                        RUNTIME.remove_ue(ue_id)

                # UE not known
                else:
                    # Reporting on and entry which switched to offline; ignore
                    if option.state == 1:
                        continue

                    cell = vbs.cells[hdr.cellid]

                    ue = UE(ue_id, option.rnti, option.imsi, option.tmsi, cell,
                            tenant)

                    RUNTIME.ues[ue.ue_id] = ue
                    tenant.ues[ue.ue_id] = ue

                    # UE is connected
                    if option.state == 0:
                        self.server.send_ue_join_message_to_self(ue)
示例#10
0
    def post(self, *args, **kwargs):
        """ Create a new tenant request.

        Args:
            None

        Request:
            version: protocol version (1.0)
            owner: the username of the requester
            tenant_id: the network name
            desc: a description for the new tenant
            bssid_type: shared or unique

        Example URLs:

            POST /api/v1/pending

        """

        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 "desc" not in request:
                raise ValueError("missing desc element")

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

            bssid_type = T_TYPE_UNIQUE
            if "bssid_type" in request:
                bssid_type = request['bssid_type']

            if "plmn_id" in request:
                plmn_id = PLMNID(request['plmn_id'])
            else:
                plmn_id = None

            if len(args) == 1:
                tenant_id = UUID(args[0])
            else:
                tenant_id = None

            tenant_name = SSID(request['tenant_name'])

            RUNTIME.request_tenant(self.account.username,
                                   request['desc'],
                                   tenant_name,
                                   bssid_type,
                                   tenant_id,
                                   plmn_id)

            self.set_header("Location", "/api/v1/pendig/%s" % tenant_id)

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

        self.set_status(201, None)
示例#11
0
    def _handle_ue_report_response(self, vbs, hdr, event, msg):
        """Handle an incoming UE_REPORT message.
        Args:
            hello, a UE_REPORT message
        Returns:
            None
        """

        for raw_entry in msg.options:

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

            prop = UE_REPORT_TYPES[raw_entry.type].name
            option = UE_REPORT_TYPES[raw_entry.type].parse(raw_entry.data)

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

            if raw_entry.type == EP_UE_REPORT_IDENTITY:

                plmn_id = PLMNID(option.plmn_id)
                tenant = RUNTIME.load_tenant_by_plmn_id(plmn_id)

                if not tenant:
                    self.log.info("Unknown tenant %s", plmn_id)
                    continue

                ue = RUNTIME.find_ue_by_rnti(option.rnti, hdr.cellid, vbs)

                # UE already known, update its parameters
                if ue:

                    ue.plmn_id = plmn_id
                    ue.tmsi = option.timsi

                else:

                    cell = vbs.cells[hdr.cellid]
                    ue_id = uuid.uuid4()

                    ue = UE(ue_id, option.rnti, option.imsi, option.timsi,
                            cell, tenant)

                    RUNTIME.ues[ue.ue_id] = ue
                    tenant.ues[ue.ue_id] = ue

                    self.server.send_ue_join_message_to_self(ue)

            elif raw_entry.type == EP_UE_REPORT_STATE:

                ue_id = uuid.uuid4()

                ue = RUNTIME.find_ue_by_rnti(option.rnti, hdr.cellid, vbs)

                if not ue:
                    continue

                try:
                    ue.state = UE_REPORT_STATES[option.state]
                except IOError:
                    self.log.error("Invalid transistion %s -> %s" \
                                    %(ue.state, UE_REPORT_STATES[option.state]))