Beispiel #1
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 _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)
Beispiel #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)
    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)
    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)
Beispiel #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)
    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"] = 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"] = \
                                                                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"] = \
                                                                    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"] = \
                                                                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 = int(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)
    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)
    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[ue["rnti"]] = {}
                if "imsi" in ue:
                    active_ues[ue["rnti"]]["imsi"] = ue["imsi"]
                else:
                    active_ues[ue["rnti"]]["imsi"] = None
                if "plmn_id" in ue:
                    active_ues[ue["rnti"]]["plmn_id"] = ue["plmn_id"]
                else:
                    active_ues[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[ue["rnti"]] = {}
                if "imsi" in ue:
                    inactive_ues[ue["rnti"]]["imsi"] = ue["imsi"]
                else:
                    inactive_ues[ue["rnti"]]["imsi"] = None
                if "plmn_id" in ue:
                    inactive_ues[ue["rnti"]]["plmn_id"] = ue["plmn_id"]
                else:
                    inactive_ues[ue["rnti"]]["plmn_id"] = None

        for rnti in active_ues:

            ue_id = hex_to_ether(rnti)

            if ue_id not in RUNTIME.ues:

                ue_id = hex_to_ether(rnti)
                imsi = active_ues[ue["rnti"]]["imsi"]
                new_ue = UE(ue_id, imsi, self.vbs)

                RUNTIME.ues[ue_id] = new_ue

            ue = RUNTIME.ues[ue_id]
            plmn_id = int(active_ues[rnti]["plmn_id"])

            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)

            if ue.plmn_id and not plmn_id:

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

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

                # setting tenant
                ue.tenant = None

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

        for ue_id in existing_ues:
            if ether_to_hex(ue_id) not in active_ues:
                RUNTIME.remove_ue(ue_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)

            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)
Beispiel #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)
                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)
    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]))
    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)