Пример #1
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)
Пример #2
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)
Пример #3
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)
Пример #4
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)
Пример #5
0
    def _handle_ue_state_change(self, ue_state):

        ue_state_dict = protobuf_to_dict(ue_state)[PRT_UE_STATE_CHANGE]
        rnti = ue_state_dict["config"]["rnti"]

        if ue_state_dict["type"] != config_common_pb2.PRUESC_DEACTIVATED:
            if "capabilities" not in ue_state_dict["config"]:
                capabilities = {}
            else:
                capabilities = ue_state_dict["config"]["capabilities"]
                del ue_state_dict["config"]["capabilities"]
            del ue_state_dict["config"]["rnti"]
            self.vbsp.ues[rnti] = UE(rnti, self.vbsp, ue_state_dict["config"],
                                     capabilities)

        elif ue_state_dict[
                "type"] == config_common_pb2.PRUESC_DEACTIVATED and rnti in self.vbsp.ues:
            del self.vbsp.ues[rnti]
    def _handle_UEs_id_repl(self, main_msg):
        """Handle an incoming UEs ID reply.

        Args:
            message, a emage_msg containing UE IDs (RNTIs)
        Returns:
            None
        """

        enb_id = main_msg.head.b_id

        active_ues = {}
        inactive_ues = {}

        event_type = main_msg.WhichOneof("event_types")
        msg = protobuf_to_dict(main_msg)
        ues_id_msg_repl = msg[event_type]["mUEs_id"]["repl"]

        if ues_id_msg_repl["status"] != configs_pb2.CREQS_SUCCESS:
            return

        # List of active UEs
        if "active_ue_id" in ues_id_msg_repl:
            for ue in ues_id_msg_repl["active_ue_id"]:
                addr = rnti_to_ue_id(ue["rnti"], enb_id)
                active_ues[addr] = {}
                active_ues[addr]["addr"] = addr
                active_ues[addr]["rnti"] = ue["rnti"]
                if "imsi" in ue:
                    active_ues[addr]["imsi"] = int(ue["imsi"])
                if "plmn_id" in ue:
                    active_ues[addr]["plmn_id"] = ue["plmn_id"]

        # List of inactive UEs
        if "inactive_ue_id" in ues_id_msg_repl:
            for ue in ues_id_msg_repl["inactive_ue_id"]:
                addr = rnti_to_ue_id(ue["rnti"], enb_id)
                inactive_ues[addr] = {}
                inactive_ues[addr]["addr"] = addr
                inactive_ues[addr]["rnti"] = ue["rnti"]
                if "imsi" in ue:
                    inactive_ues[addr]["imsi"] = int(ue["imsi"])
                if "plmn_id" in ue:
                    inactive_ues[addr]["plmn_id"] = ue["plmn_id"]

        for new_ue in active_ues.values():

            if new_ue["addr"] not in RUNTIME.ues:

                ue = UE(new_ue["addr"], new_ue["rnti"], self.vbs)

                if "imsi" in new_ue:
                    ue.imsi = new_ue["imsi"]

                if "plmn_id" in new_ue:

                    ue.tenant = \
                        RUNTIME.load_tenant_by_plmn_id(new_ue["plmn_id"])

                RUNTIME.ues[new_ue["addr"]] = ue

                continue

            ue = RUNTIME.ues[new_ue["addr"]]

            if "plmn_id" in new_ue:
                ue.tenant = \
                    RUNTIME.load_tenant_by_plmn_id(new_ue["plmn_id"])

        for addr in list(RUNTIME.ues.keys()):
            if addr not in active_ues:
                RUNTIME.remove_ue(addr)
Пример #7
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)
Пример #8
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]))
Пример #9
0
    def _handle_UEs_id_repl(self, main_msg):
        """Handle an incoming UEs ID reply.

        Args:
            message, a emage_msg containing UE IDs (RNTIs)
        Returns:
            None
        """

        active_ues = {}
        inactive_ues = {}

        event_type = main_msg.WhichOneof("event_types")
        msg = protobuf_to_dict(main_msg)
        ues_id_msg_repl = msg[event_type]["mUEs_id"]["repl"]

        if ues_id_msg_repl["status"] != configs_pb2.CREQS_SUCCESS:
            return

        # List of active UEs
        if "active_ue_id" in ues_id_msg_repl:
            for ue in ues_id_msg_repl["active_ue_id"]:
                active_ues[(self.vbs.addr, ue["rnti"])] = {}
                if "imsi" in ue:
                    active_ues[(self.vbs.addr, ue["rnti"])]["imsi"] = \
                                                                int(ue["imsi"])
                else:
                    active_ues[(self.vbs.addr, ue["rnti"])]["imsi"] = None
                if "plmn_id" in ue:
                    active_ues[(self.vbs.addr, ue["rnti"])]["plmn_id"] = \
                                                            int(ue["plmn_id"])
                else:
                    active_ues[(self.vbs.addr, ue["rnti"])]["plmn_id"] = None

        # List of inactive UEs
        if "inactive_ue_id" in ues_id_msg_repl:
            for ue in ues_id_msg_repl["inactive_ue_id"]:
                inactive_ues[(self.vbs.addr, ue["rnti"])] = {}
                if "imsi" in ue:
                    inactive_ues[(self.vbs.addr, ue["rnti"])]["imsi"] = \
                                                                int(ue["imsi"])
                else:
                    inactive_ues[(self.vbs.addr, ue["rnti"])]["imsi"] = None
                if "plmn_id" in ue:
                    inactive_ues[(self.vbs.addr, ue["rnti"])]["plmn_id"] = \
                                                            int(ue["plmn_id"])
                else:
                    inactive_ues[(self.vbs.addr, ue["rnti"])]["plmn_id"] = None

        for vbs_id, rnti in active_ues.keys():

            ue_id = (self.vbs.addr, rnti)

            if ue_id not in RUNTIME.ues:
                new_ue = UE(ue_id, ue_id[1], self.vbs)
                RUNTIME.ues[ue_id] = new_ue

            ue = RUNTIME.ues[ue_id]

            imsi = active_ues[ue_id]["imsi"]
            plmn_id = active_ues[ue_id]["plmn_id"]

            # Setting IMSI of UE
            ue.imsi = imsi

            if not ue.plmn_id and plmn_id:

                # Setting tenant
                ue.tenant = RUNTIME.load_tenant_by_plmn_id(plmn_id)

                if ue.tenant:

                    # Adding UE to tenant
                    LOG.info("Adding %s to tenant %s", ue.addr,
                             ue.tenant.plmn_id)
                    ue.tenant.ues[ue.addr] = ue

                    # Raise UE join
                    self.server.send_ue_join_message_to_self(ue)

                    # Create a trigger for reporting RRC measurements config.
                    from empower.ue_confs.ue_rrc_meas_confs import ue_rrc_meas_confs

                    conf_req = {"event_type": "trigger"}

                    ue_rrc_meas_confs(tenant_id=ue.tenant.tenant_id,
                                      vbs=ue.vbs.addr,
                                      ue=ue.rnti,
                                      conf_req=conf_req)

            if ue.plmn_id and not plmn_id:

                # Raise UE leave
                self.server.send_ue_leave_message_to_self(ue)

                # Removing UE from tenant
                LOG.info("Removing %s from tenant %s", ue.addr,
                         ue.tenant.plmn_id)
                del ue.tenant.ues[ue.addr]

                # Resetting tenant
                ue.tenant = None

        existing_ues = []
        existing_ues.extend(RUNTIME.ues.keys())

        for ue_addr in existing_ues:
            if ue_addr not in active_ues:
                RUNTIME.remove_ue(ue_addr)