void *s1ap_eNB_task(void *arg) { MessageDef *received_msg = NULL; int result; S1AP_DEBUG("Starting S1AP layer\n"); s1ap_eNB_prepare_internal_data(); itti_mark_task_ready(TASK_S1AP); MSC_START_USE(); while (1) { itti_receive_msg(TASK_S1AP, &received_msg); switch (ITTI_MSG_ID(received_msg)) { case TERMINATE_MESSAGE: itti_exit_task(); break; case S1AP_REGISTER_ENB_REQ: { /* Register a new eNB. * in Virtual mode eNBs will be distinguished using the mod_id/ * Each eNB has to send an S1AP_REGISTER_ENB message with its * own parameters. */ s1ap_eNB_handle_register_eNB(ITTI_MESSAGE_GET_INSTANCE(received_msg), &S1AP_REGISTER_ENB_REQ(received_msg)); } break; case SCTP_NEW_ASSOCIATION_RESP: { s1ap_eNB_handle_sctp_association_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg), &received_msg->ittiMsg.sctp_new_association_resp); } break; case SCTP_DATA_IND: { s1ap_eNB_handle_sctp_data_ind(&received_msg->ittiMsg.sctp_data_ind); } break; case S1AP_NAS_FIRST_REQ: { s1ap_eNB_handle_nas_first_req(ITTI_MESSAGE_GET_INSTANCE(received_msg), &S1AP_NAS_FIRST_REQ(received_msg)); } break; case S1AP_UPLINK_NAS: { s1ap_eNB_nas_uplink(ITTI_MESSAGE_GET_INSTANCE(received_msg), &S1AP_UPLINK_NAS(received_msg)); } break; case S1AP_UE_CAPABILITIES_IND: { s1ap_eNB_ue_capabilities(ITTI_MESSAGE_GET_INSTANCE(received_msg), &S1AP_UE_CAPABILITIES_IND(received_msg)); } break; case S1AP_INITIAL_CONTEXT_SETUP_RESP: { s1ap_eNB_initial_ctxt_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg), &S1AP_INITIAL_CONTEXT_SETUP_RESP(received_msg)); } break; case S1AP_E_RAB_SETUP_RESP: { s1ap_eNB_e_rab_setup_resp(ITTI_MESSAGE_GET_INSTANCE(received_msg), &S1AP_E_RAB_SETUP_RESP(received_msg)); } break; case S1AP_NAS_NON_DELIVERY_IND: { s1ap_eNB_nas_non_delivery_ind(ITTI_MESSAGE_GET_INSTANCE(received_msg), &S1AP_NAS_NON_DELIVERY_IND(received_msg)); } break; case S1AP_UE_CONTEXT_RELEASE_COMPLETE: { s1ap_ue_context_release_complete(ITTI_MESSAGE_GET_INSTANCE(received_msg), &S1AP_UE_CONTEXT_RELEASE_COMPLETE(received_msg)); } break; case S1AP_UE_CONTEXT_RELEASE_REQ: { s1ap_eNB_instance_t *s1ap_eNB_instance_p = NULL; // test struct s1ap_eNB_ue_context_s *ue_context_p = NULL; // test s1ap_ue_context_release_req(ITTI_MESSAGE_GET_INSTANCE(received_msg), &S1AP_UE_CONTEXT_RELEASE_REQ(received_msg)); s1ap_eNB_instance_p = s1ap_eNB_get_instance(ITTI_MESSAGE_GET_INSTANCE(received_msg)); // test DevAssert(s1ap_eNB_instance_p != NULL); // test if ((ue_context_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance_p, S1AP_UE_CONTEXT_RELEASE_REQ(received_msg).eNB_ue_s1ap_id)) == NULL) { // test /* The context for this eNB ue s1ap id doesn't exist in the map of eNB UEs */ S1AP_ERROR("Failed to find ue context associated with eNB ue s1ap id: %u\n", S1AP_UE_CONTEXT_RELEASE_REQ(received_msg).eNB_ue_s1ap_id); // test } // test } break; default: S1AP_ERROR("Received unhandled message: %d:%s\n", ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg)); break; } result = itti_free (ITTI_MSG_ORIGIN_ID(received_msg), received_msg); AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); received_msg = NULL; } return NULL; }
static int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id, uint32_t stream, struct s1ap_message_s *message_p) { S1ap_S1SetupResponseIEs_t *s1SetupResponse_p; s1ap_eNB_mme_data_t *mme_desc_p; int i; DevAssert(message_p != NULL); s1SetupResponse_p = &message_p->msg.s1ap_S1SetupResponseIEs; /* S1 Setup Response == Non UE-related procedure -> stream 0 */ if (stream != 0) { S1AP_ERROR("[SCTP %d] Received s1 setup response on stream != 0 (%d)\n", assoc_id, stream); return -1; } if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { S1AP_ERROR("[SCTP %d] Received S1 setup response for non existing " "MME context\n", assoc_id); return -1; } /* The list of served gummei can contain at most 8 elements. * LTE related gummei is the first element in the list, i.e with an id of 0. */ DevAssert(s1SetupResponse_p->servedGUMMEIs.list.count == 1); for (i = 0; i < s1SetupResponse_p->servedGUMMEIs.list.count; i++) { struct S1ap_ServedGUMMEIsItem *gummei_item_p; struct served_gummei_s *new_gummei_p; int j; gummei_item_p = (struct S1ap_ServedGUMMEIsItem *) s1SetupResponse_p->servedGUMMEIs.list.array[i]; new_gummei_p = calloc(1, sizeof(struct served_gummei_s)); STAILQ_INIT(&new_gummei_p->served_plmns); STAILQ_INIT(&new_gummei_p->served_group_ids); STAILQ_INIT(&new_gummei_p->mme_codes); for (j = 0; j < gummei_item_p->servedPLMNs.list.count; j++) { S1ap_PLMNidentity_t *plmn_identity_p; struct plmn_identity_s *new_plmn_identity_p; plmn_identity_p = gummei_item_p->servedPLMNs.list.array[i]; new_plmn_identity_p = calloc(1, sizeof(struct plmn_identity_s)); TBCD_TO_MCC_MNC(plmn_identity_p, new_plmn_identity_p->mcc, new_plmn_identity_p->mnc, new_plmn_identity_p->mnc_digit_length); STAILQ_INSERT_TAIL(&new_gummei_p->served_plmns, new_plmn_identity_p, next); new_gummei_p->nb_served_plmns++; } for (j = 0; j < gummei_item_p->servedGroupIDs.list.count; j++) { S1ap_MME_Group_ID_t *mme_group_id_p; struct served_group_id_s *new_group_id_p; mme_group_id_p = gummei_item_p->servedGroupIDs.list.array[i]; new_group_id_p = calloc(1, sizeof(struct served_group_id_s)); OCTET_STRING_TO_INT16(mme_group_id_p, new_group_id_p->mme_group_id); STAILQ_INSERT_TAIL(&new_gummei_p->served_group_ids, new_group_id_p, next); new_gummei_p->nb_group_id++; } for (j = 0; j < gummei_item_p->servedMMECs.list.count; j++) { S1ap_MME_Code_t *mme_code_p; struct mme_code_s *new_mme_code_p; mme_code_p = gummei_item_p->servedMMECs.list.array[i]; new_mme_code_p = calloc(1, sizeof(struct mme_code_s)); OCTET_STRING_TO_INT8(mme_code_p, new_mme_code_p->mme_code); STAILQ_INSERT_TAIL(&new_gummei_p->mme_codes, new_mme_code_p, next); new_gummei_p->nb_mme_code++; } STAILQ_INSERT_TAIL(&mme_desc_p->served_gummei, new_gummei_p, next); } /* Free contents of the list */ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_S1ap_ServedGUMMEIs, (void *)&s1SetupResponse_p->servedGUMMEIs); /* Set the capacity of this MME */ mme_desc_p->relative_mme_capacity = s1SetupResponse_p->relativeMMECapacity; /* Optionaly set the mme name */ if (s1SetupResponse_p->presenceMask & S1AP_S1SETUPRESPONSEIES_MMENAME_PRESENT) { mme_desc_p->mme_name = calloc(s1SetupResponse_p->mmEname.size + 1, sizeof(char)); memcpy(mme_desc_p->mme_name, s1SetupResponse_p->mmEname.buf, s1SetupResponse_p->mmEname.size); /* Convert the mme name to a printable string */ mme_desc_p->mme_name[s1SetupResponse_p->mmEname.size] = '\0'; } /* The association is now ready as eNB and MME know parameters of each other. * Mark the association as UP to enable UE contexts creation. */ mme_desc_p->state = S1AP_ENB_STATE_CONNECTED; mme_desc_p->s1ap_eNB_instance->s1ap_mme_associated_nb ++; s1ap_handle_s1_setup_message(mme_desc_p, 0); #if 0 /* We call back our self * -> generate a dummy initial UE message */ { s1ap_nas_first_req_t s1ap_nas_first_req; memset(&s1ap_nas_first_req, 0, sizeof(s1ap_nas_first_req_t)); s1ap_nas_first_req.rnti = 0xC03A; s1ap_nas_first_req.establishment_cause = RRC_CAUSE_MO_DATA; s1ap_nas_first_req.ue_identity.presenceMask = UE_IDENTITIES_gummei; s1ap_nas_first_req.ue_identity.gummei.mcc = 208; s1ap_nas_first_req.ue_identity.gummei.mnc = 34; s1ap_nas_first_req.ue_identity.gummei.mme_code = 0; s1ap_nas_first_req.ue_identity.gummei.mme_group_id = 0; /* NAS Attach request with IMSI */ static uint8_t nas_attach_req_imsi[] = { 0x07, 0x41, /* EPS Mobile identity = IMSI */ 0x71, 0x08, 0x29, 0x80, 0x43, 0x21, 0x43, 0x65, 0x87, 0xF9, /* End of EPS Mobile Identity */ 0x02, 0xE0, 0xE0, 0x00, 0x20, 0x02, 0x03, 0xD0, 0x11, 0x27, 0x1A, 0x80, 0x80, 0x21, 0x10, 0x01, 0x00, 0x00, 0x10, 0x81, 0x06, 0x00, 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x0A, 0x00, 0x52, 0x12, 0xF2, 0x01, 0x27, 0x11, }; /* NAS Attach request with GUTI */ static uint8_t nas_attach_req_guti[] = { 0x07, 0x41, /* EPS Mobile identity = IMSI */ 0x71, 0x0B, 0xF6, 0x12, 0xF2, 0x01, 0x80, 0x00, 0x01, 0xE0, 0x00, 0xDA, 0x1F, /* End of EPS Mobile Identity */ 0x02, 0xE0, 0xE0, 0x00, 0x20, 0x02, 0x03, 0xD0, 0x11, 0x27, 0x1A, 0x80, 0x80, 0x21, 0x10, 0x01, 0x00, 0x00, 0x10, 0x81, 0x06, 0x00, 0x00, 0x00, 0x00, 0x83, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x0A, 0x00, 0x52, 0x12, 0xF2, 0x01, 0x27, 0x11, }; s1ap_nas_first_req.nas_pdu.buffer = nas_attach_req_guti; s1ap_nas_first_req.nas_pdu.length = sizeof(nas_attach_req_guti); s1ap_eNB_handle_nas_first_req(mme_desc_p->s1ap_eNB_instance->instance, &s1ap_nas_first_req); } #endif return 0; }