Commit 9b61d3a7 authored by nikaeinn's avatar nikaeinn

* support for PLMN with 6 digits

* bug fixed for S1AP
* update the mme and enb configuration files



git-svn-id: http://svn.eurecom.fr/openair4G/trunk@5218 818b1a75-f10b-46b9-bf7c-635c3b92a50f
parent 4a930b7d
......@@ -88,6 +88,7 @@ typedef uint32_t SequenceNumber_t;
typedef uint32_t access_restriction_t;
typedef uint32_t context_identifier_t;
typedef uint32_t rau_tau_timer_t;
//typedef uint32_t in_addr_t; is network byte order
typedef uint32_t ard_t;
#define ARD_UTRAN_NOT_ALLOWED (1U)
......
......@@ -81,24 +81,28 @@ static inline int ue_context_compare_identifiers(
} else {
uint16_t mcc1;
uint16_t mnc1;
uint16_t mnc1_len;
uint16_t mcc2;
uint16_t mnc2;
uint16_t mnc2_len;
PLMN_T_TO_MCC_MNC(p1->guti.gummei.plmn, mcc1, mnc1);
PLMN_T_TO_MCC_MNC(p1->guti.gummei.plmn, mcc2, mnc2);
PLMN_T_TO_MCC_MNC(p1->guti.gummei.plmn, mcc1, mnc1, mnc1_len);
PLMN_T_TO_MCC_MNC(p1->guti.gummei.plmn, mcc2, mnc2, mnc2_len);
/* else compare by GUTI */
if ((p1->guti.m_tmsi < p2->guti.m_tmsi) &&
(p1->guti.gummei.MMEcode < p2->guti.gummei.MMEcode) &&
(p1->guti.gummei.MMEgid < p2->guti.gummei.MMEgid) &&
(mcc1 < mcc2) &&
(mnc1 < mnc2))
(mnc1 < mnc2) &&
(mnc1_len < mnc2_len))
return 1;
if ((p1->guti.m_tmsi > p2->guti.m_tmsi) &&
(p1->guti.gummei.MMEcode > p2->guti.gummei.MMEcode) &&
(p1->guti.gummei.MMEgid > p2->guti.gummei.MMEgid) &&
(mcc1 > mcc2) &&
(mnc1 > mnc2))
(mnc1 > mnc2) &&
(mnc1_len > mnc2_len))
return -1;
}
/* Match -> return 0 */
......
......@@ -120,7 +120,9 @@ typedef struct ue_context_s {
#define SUBSCRIPTION_KNOWN 0x1
unsigned subscription_known:1;
uint8_t msisdn[MSISDN_LENGTH];
uint8_t msisdn[MSISDN_LENGTH+1];
uint8_t msisdn_length;
mm_state_t mm_state;
/* Globally Unique Temporary Identity */
GUTI_t guti;
......
......@@ -153,6 +153,7 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *
DevCheck(new_instance->tac == s1ap_register_eNB->tac, new_instance->tac, s1ap_register_eNB->tac, 0);
DevCheck(new_instance->mcc == s1ap_register_eNB->mcc, new_instance->mcc, s1ap_register_eNB->mcc, 0);
DevCheck(new_instance->mnc == s1ap_register_eNB->mnc, new_instance->mnc, s1ap_register_eNB->mnc, 0);
DevCheck(new_instance->mnc_digit_length == s1ap_register_eNB->mnc_digit_length, new_instance->mnc_digit_length, s1ap_register_eNB->mnc_digit_length, 0);
DevCheck(new_instance->default_drx == s1ap_register_eNB->default_drx, new_instance->default_drx, s1ap_register_eNB->default_drx, 0);
} else {
new_instance = calloc(1, sizeof(s1ap_eNB_instance_t));
......@@ -162,14 +163,15 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *
RB_INIT(&new_instance->s1ap_mme_head);
/* Copy usefull parameters */
new_instance->instance = instance;
new_instance->eNB_name = s1ap_register_eNB->eNB_name;
new_instance->eNB_id = s1ap_register_eNB->eNB_id;
new_instance->cell_type = s1ap_register_eNB->cell_type;
new_instance->tac = s1ap_register_eNB->tac;
new_instance->mcc = s1ap_register_eNB->mcc;
new_instance->mnc = s1ap_register_eNB->mnc;
new_instance->default_drx = s1ap_register_eNB->default_drx;
new_instance->instance = instance;
new_instance->eNB_name = s1ap_register_eNB->eNB_name;
new_instance->eNB_id = s1ap_register_eNB->eNB_id;
new_instance->cell_type = s1ap_register_eNB->cell_type;
new_instance->tac = s1ap_register_eNB->tac;
new_instance->mcc = s1ap_register_eNB->mcc;
new_instance->mnc = s1ap_register_eNB->mnc;
new_instance->mnc_digit_length = s1ap_register_eNB->mnc_digit_length;
new_instance->default_drx = s1ap_register_eNB->default_drx;
/* Add the new instance to the list of eNB (meaningfull in virtual mode) */
s1ap_eNB_insert_new_instance(new_instance);
......@@ -310,15 +312,15 @@ void *s1ap_eNB_task(void *arg)
static int s1ap_eNB_generate_s1_setup_request(
s1ap_eNB_instance_t *instance_p, s1ap_eNB_mme_data_t *s1ap_mme_data_p)
{
s1ap_message message;
s1ap_message message;
S1ap_S1SetupRequestIEs_t *s1SetupRequest_p;
S1ap_PLMNidentity_t plmnIdentity;
S1ap_SupportedTAs_Item_t ta;
uint8_t *buffer;
uint32_t len;
int ret = 0;
uint32_t len;
int ret = 0;
DevAssert(instance_p != NULL);
DevAssert(s1ap_mme_data_p != NULL);
......@@ -339,13 +341,13 @@ static int s1ap_eNB_generate_s1_setup_request(
s1SetupRequest_p->global_ENB_ID.eNB_ID.present = S1ap_ENB_ID_PR_macroENB_ID;
MACRO_ENB_ID_TO_BIT_STRING(instance_p->eNB_id,
&s1SetupRequest_p->global_ENB_ID.eNB_ID.choice.macroENB_ID);
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc,
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
&s1SetupRequest_p->global_ENB_ID.pLMNidentity);
S1AP_INFO("%d -> %02x%02x%02x\n", instance_p->eNB_id, s1SetupRequest_p->global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[0], s1SetupRequest_p->global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[1], s1SetupRequest_p->global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[2]);
INT16_TO_OCTET_STRING(instance_p->tac, &ta.tAC);
MCC_MNC_TO_TBCD(instance_p->mcc, instance_p->mnc, &plmnIdentity);
MCC_MNC_TO_TBCD(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, &plmnIdentity);
ASN_SEQUENCE_ADD(&ta.broadcastPLMNs.list, &plmnIdentity);
ASN_SEQUENCE_ADD(&s1SetupRequest_p->supportedTAs.list, &ta);
......
......@@ -86,6 +86,7 @@ typedef enum {
struct plmn_identity_s {
uint16_t mcc;
uint16_t mnc;
uint8_t mnc_digit_length;
STAILQ_ENTRY(plmn_identity_s) next;
};
......@@ -208,6 +209,7 @@ typedef struct s1ap_eNB_instance_s {
*/
uint16_t mcc;
uint16_t mnc;
uint8_t mnc_digit_length;
/* Default Paging DRX of the eNB as defined in TS 36.304 */
paging_drx_t default_drx;
......
......@@ -301,7 +301,7 @@ int s1ap_eNB_handle_s1_setup_response(uint32_t assoc_id,
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, 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++;
}
......@@ -414,9 +414,9 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id,
{
int i;
s1ap_eNB_mme_data_t *mme_desc_p;
s1ap_eNB_ue_context_t *ue_desc_p;
MessageDef *message_p;
s1ap_eNB_mme_data_t *mme_desc_p = NULL;
s1ap_eNB_ue_context_t *ue_desc_p = NULL;
MessageDef *message_p = NULL;
S1ap_InitialContextSetupRequestIEs_t *initialContextSetupRequest_p;
DevAssert(s1ap_message_p != NULL);
......@@ -445,7 +445,7 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id,
ue_desc_p->mme_ue_s1ap_id = initialContextSetupRequest_p->mme_ue_s1ap_id;
message_p = itti_alloc_new_message(TASK_S1AP, S1AP_INITIAL_CONTEXT_SETUP_REQ);
message_p = itti_alloc_new_message(TASK_S1AP, S1AP_INITIAL_CONTEXT_SETUP_REQ);
S1AP_INITIAL_CONTEXT_SETUP_REQ(message_p).ue_initial_id = ue_desc_p->ue_initial_id;
ue_desc_p->ue_initial_id = 0;
......
......@@ -161,9 +161,12 @@ int s1ap_eNB_handle_nas_first_req(
if (s1ap_nas_first_req_p->ue_identity.presenceMask & UE_IDENTITIES_gummei) {
initial_ue_message_p->presenceMask |= S1AP_INITIALUEMESSAGEIES_GUMMEI_ID_PRESENT;
MCC_MNC_TO_PLMNID(s1ap_nas_first_req_p->ue_identity.gummei.mcc,
s1ap_nas_first_req_p->ue_identity.gummei.mnc,
&initial_ue_message_p->gummei_id.pLMN_Identity);
MCC_MNC_TO_PLMNID(
s1ap_nas_first_req_p->ue_identity.gummei.mcc,
s1ap_nas_first_req_p->ue_identity.gummei.mnc,
s1ap_nas_first_req_p->ue_identity.gummei.mnc_len,
&initial_ue_message_p->gummei_id.pLMN_Identity);
MME_GID_TO_OCTET_STRING(s1ap_nas_first_req_p->ue_identity.gummei.mme_group_id,
&initial_ue_message_p->gummei_id.mME_Group_ID);
MME_CODE_TO_OCTET_STRING(s1ap_nas_first_req_p->ue_identity.gummei.mme_code,
......@@ -172,8 +175,10 @@ int s1ap_eNB_handle_nas_first_req(
/* Assuming TAI is the TAI from the cell */
INT16_TO_OCTET_STRING(instance_p->tac, &initial_ue_message_p->tai.tAC);
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc,
&initial_ue_message_p->tai.pLMNidentity);
MCC_MNC_TO_PLMNID(instance_p->mcc,
instance_p->mnc,
instance_p->mnc_digit_length,
&initial_ue_message_p->tai.pLMNidentity);
/* Set the EUTRAN CGI
* The cell identity is defined on 28 bits but as we use macro enb id,
......@@ -181,8 +186,10 @@ int s1ap_eNB_handle_nas_first_req(
*/
MACRO_ENB_ID_TO_CELL_IDENTITY(instance_p->eNB_id,
&initial_ue_message_p->eutran_cgi.cell_ID);
MCC_MNC_TO_TBCD(instance_p->mcc, instance_p->mnc,
&initial_ue_message_p->eutran_cgi.pLMNidentity);
MCC_MNC_TO_TBCD(instance_p->mcc,
instance_p->mnc,
instance_p->mnc_digit_length,
&initial_ue_message_p->eutran_cgi.pLMNidentity);
if (s1ap_eNB_encode_pdu(&message, &buffer, &length) < 0) {
/* Failed to encode message */
......@@ -319,14 +326,22 @@ int s1ap_eNB_nas_uplink(instance_t instance, s1ap_uplink_nas_t *s1ap_uplink_nas_
uplink_NAS_transport_p->nas_pdu.buf = s1ap_uplink_nas_p->nas_pdu.buffer;
uplink_NAS_transport_p->nas_pdu.size = s1ap_uplink_nas_p->nas_pdu.length;
MCC_MNC_TO_PLMNID(s1ap_eNB_instance_p->mcc, s1ap_eNB_instance_p->mnc,
&uplink_NAS_transport_p->eutran_cgi.pLMNidentity);
MCC_MNC_TO_PLMNID(
s1ap_eNB_instance_p->mcc,
s1ap_eNB_instance_p->mnc,
s1ap_eNB_instance_p->mnc_digit_length,
&uplink_NAS_transport_p->eutran_cgi.pLMNidentity);
MACRO_ENB_ID_TO_CELL_IDENTITY(s1ap_eNB_instance_p->eNB_id,
&uplink_NAS_transport_p->eutran_cgi.cell_ID);
/* MCC/MNC should be repeated in TAI and EUTRAN CGI */
MCC_MNC_TO_PLMNID(s1ap_eNB_instance_p->mcc, s1ap_eNB_instance_p->mnc,
&uplink_NAS_transport_p->tai.pLMNidentity);
MCC_MNC_TO_PLMNID(
s1ap_eNB_instance_p->mcc,
s1ap_eNB_instance_p->mnc,
s1ap_eNB_instance_p->mnc_digit_length,
&uplink_NAS_transport_p->tai.pLMNidentity);
TAC_TO_ASN1(s1ap_eNB_instance_p->tac, &uplink_NAS_transport_p->tai.tAC);
if (s1ap_eNB_encode_pdu(&message, &buffer, &length) < 0) {
......
......@@ -290,6 +290,7 @@ int s1ap_mme_handle_s1_setup_request(uint32_t assoc_id, uint32_t stream,
/* eNB and MME have no common PLMN */
if (ta_ret != TA_LIST_RET_OK) {
S1AP_ERROR("No Common PLMN with eNB, generate_s1_setup_failure\n");
return s1ap_mme_generate_s1_setup_failure(assoc_id, S1ap_Cause_PR_misc,
S1ap_CauseMisc_unknown_PLMN,
S1ap_TimeToWait_v20s);
......@@ -374,9 +375,11 @@ int s1ap_generate_s1_setup_response(eNB_description_t *eNB_association)
/* FIXME: free object from list once encoded */
plmn = calloc(1, sizeof(*plmn));
MCC_MNC_TO_PLMNID(mme_config.gummei.plmn_mcc[i],
mme_config.gummei.plmn_mnc[i],
plmn);
MCC_MNC_TO_PLMNID(
mme_config.gummei.plmn_mcc[i],
mme_config.gummei.plmn_mnc[i],
mme_config.gummei.plmn_mnc_len[i],
plmn);
ASN_SEQUENCE_ADD(&servedGUMMEI.servedPLMNs.list, plmn);
}
for (i = 0; i < mme_config.gummei.nb_mme_gid; i++) {
......
......@@ -47,16 +47,23 @@ int s1ap_mme_compare_plmn(S1ap_PLMNidentity_t *plmn)
int i;
uint16_t mcc;
uint16_t mnc;
uint16_t mnc_len;
DevAssert(plmn != NULL);
TBCD_TO_MCC_MNC(plmn, mcc, mnc);
TBCD_TO_MCC_MNC(plmn, mcc, mnc, mnc_len);
config_read_lock(&mme_config);
for (i = 0; i < mme_config.gummei.nb_mme_gid; i++) {
if (mme_config.gummei.plmn_mcc[i] == mcc &&
mme_config.gummei.plmn_mnc[i] == mnc)
S1AP_DEBUG("Comparing plmn_mcc %d/%d, plmn_mnc %d/%d plmn_mnc_len %d/%d\n",
mme_config.gummei.plmn_mcc[i], mcc,
mme_config.gummei.plmn_mnc[i],mnc,
mme_config.gummei.plmn_mnc_len[i],mnc_len);
if ((mme_config.gummei.plmn_mcc[i] == mcc) &&
(mme_config.gummei.plmn_mnc[i] == mnc) &&
(mme_config.gummei.plmn_mnc_len[i] == mnc_len))
/* There is a matching plmn */
return TA_LIST_AT_LEAST_ONE_MATCH;
}
......@@ -104,7 +111,8 @@ int s1ap_mme_compare_tac(S1ap_TAC_t *tac)
config_read_lock(&mme_config);
for (i = 0; i < mme_config.gummei.nb_mme_gid; i++) {
for (i = 0; i < mme_config.gummei.nb_plmns; i++) {
S1AP_DEBUG("Comparing config tac %d, received tac = %d\n", mme_config.gummei.plmn_tac[i], tac_value);
if (mme_config.gummei.plmn_tac[i] == tac_value)
return TA_LIST_AT_LEAST_ONE_MATCH;
}
......
......@@ -549,12 +549,12 @@ inline void sctp_eNB_read_from_socket(struct sctp_cnx_list_elm_s *sctp_cnx)
} else {
sctp_cnx->nb_messages++;
if (ntohl(sinfo.sinfo_ppid) != sctp_cnx->ppid) {
if (sinfo.sinfo_ppid != sctp_cnx->ppid) {
/* Mismatch in Payload Protocol Identifier,
* may be we received unsollicited traffic from stack other than S1AP.
*/
SCTP_ERROR("Received data from peer with unsollicited PPID %d, expecting %d\n",
ntohl(sinfo.sinfo_ppid), sctp_cnx->ppid);
sinfo.sinfo_ppid, sctp_cnx->ppid);
}
SCTP_DEBUG("[%d][%d] Msg of length %d received from port %u, on stream %d, PPID %d\n",
......
......@@ -91,8 +91,13 @@ int sgw_lite_handle_create_session_request(SgwCreateSessionRequest *session_req_
return -1;
}
SPGW_APP_DEBUG("Rx CREATE-SESSION-REQUEST MME S11 teid %u S-GW S11 teid %u APN %s EPS bearer Id %d\n", new_endpoint->remote_teid, new_endpoint->local_teid, session_req_p->apn, session_req_p->bearer_to_create.eps_bearer_id);
SPGW_APP_DEBUG(" IMSI %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",IMSI(&session_req_p->imsi));
SPGW_APP_DEBUG("Rx CREATE-SESSION-REQUEST MME S11 teid %u S-GW S11 teid %u APN %s EPS bearer Id %d\n",
new_endpoint->remote_teid,
new_endpoint->local_teid,
session_req_p->apn,
session_req_p->bearer_to_create.eps_bearer_id);
SPGW_APP_DEBUG(" IMSI %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
IMSI(&session_req_p->imsi));
s_plus_p_gw_eps_bearer_context_information = sgw_lite_cm_create_bearer_context_information_in_collection(new_endpoint->local_teid);
if (s_plus_p_gw_eps_bearer_context_information != NULL) {
......@@ -115,7 +120,9 @@ int sgw_lite_handle_create_session_request(SgwCreateSessionRequest *session_req_
s_plus_p_gw_eps_bearer_context_information->sgw_eps_bearer_context_information.peer_ip = session_req_p->peer_ip;
// may use ntohl or reverse, will see
FTEID_T_2_IP_ADDRESS_T((&session_req_p->sender_fteid_for_cp) , (&s_plus_p_gw_eps_bearer_context_information->sgw_eps_bearer_context_information.mme_ip_address_for_S11));
FTEID_T_2_IP_ADDRESS_T(
(&session_req_p->sender_fteid_for_cp) ,
(&s_plus_p_gw_eps_bearer_context_information->sgw_eps_bearer_context_information.mme_ip_address_for_S11));
//--------------------------------------
// PDN connection
......@@ -252,11 +259,12 @@ int sgw_lite_handle_sgi_endpoint_created(SGICreateEndpointResp *resp_p)
create_session_response_p->bearer_context_created.cause = CONTEXT_NOT_FOUND;
}
SPGW_APP_DEBUG("Tx CREATE-SESSION-RESPONSE MME -> %s, teid %u S-GW teid %u S1U teid %u EPS bearer id %u status %d\n",
SPGW_APP_DEBUG("Tx CREATE-SESSION-RESPONSE MME -> %s, S11 MME teid %u S11 S-GW teid %u S1U teid %u S1U addr 0x%x EPS bearer id %u status %d\n",
to_task == TASK_MME_APP ? "TASK_MME_APP" : "TASK_S11",
create_session_response_p->teid,
create_session_response_p->s11_sgw_teid.teid,
create_session_response_p->bearer_context_created.s1u_sgw_fteid.teid,
create_session_response_p->bearer_context_created.s1u_sgw_fteid.ipv4_address,
create_session_response_p->bearer_context_created.eps_bearer_id,
create_session_response_p->bearer_context_created.cause);
return itti_send_msg_to_task(to_task, INSTANCE_DEFAULT, message_p);
......@@ -504,14 +512,19 @@ int sgw_lite_handle_modify_bearer_request(SgwModifyBearerRequest *modify_bearer_
sgw_lite_display_s11teid2mme_mappings();
sgw_lite_display_s11_bearer_context_information_mapping();
hash_rc = hashtable_get(sgw_app.s11_bearer_context_information_hashtable, modify_bearer_p->teid, (void**)&new_bearer_context_information_p);
hash_rc = hashtable_get(
sgw_app.s11_bearer_context_information_hashtable,
modify_bearer_p->teid,
(void**)&new_bearer_context_information_p);
if (hash_rc == HASH_TABLE_OK) {
new_bearer_context_information_p->sgw_eps_bearer_context_information.pdn_connection.default_bearer = modify_bearer_p->bearer_context_to_modify.eps_bearer_id;
new_bearer_context_information_p->sgw_eps_bearer_context_information.trxn = modify_bearer_p->trxn;
hash_rc = hashtable_is_key_exists (new_bearer_context_information_p->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers, modify_bearer_p->bearer_context_to_modify.eps_bearer_id);
hash_rc = hashtable_is_key_exists (
new_bearer_context_information_p->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers,
modify_bearer_p->bearer_context_to_modify.eps_bearer_id);
if (hash_rc == HASH_TABLE_KEY_NOT_EXISTS) {
message_p = itti_alloc_new_message(TASK_SPGW_APP, SGW_MODIFY_BEARER_RESPONSE);
......@@ -525,10 +538,16 @@ int sgw_lite_handle_modify_bearer_request(SgwModifyBearerRequest *modify_bearer_
modify_response_p->choice.bearer_for_removal.cause = CONTEXT_NOT_FOUND;
modify_response_p->cause = CONTEXT_NOT_FOUND;
modify_response_p->trxn = modify_bearer_p->trxn;
SPGW_APP_DEBUG("Rx MODIFY_BEARER_REQUEST, eps_bearer_id %u CONTEXT_NOT_FOUND\n",
modify_bearer_p->bearer_context_to_modify.eps_bearer_id);
return itti_send_msg_to_task(to_task, INSTANCE_DEFAULT, message_p);
} else if (hash_rc == HASH_TABLE_OK) {
// TO DO
hash_rc = hashtable_get (new_bearer_context_information_p->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers, modify_bearer_p->bearer_context_to_modify.eps_bearer_id, (void**)&eps_bearer_entry_p);
hash_rc = hashtable_get (
new_bearer_context_information_p->sgw_eps_bearer_context_information.pdn_connection.sgw_eps_bearers,
modify_bearer_p->bearer_context_to_modify.eps_bearer_id,
(void**)&eps_bearer_entry_p);
FTEID_T_2_IP_ADDRESS_T( (&modify_bearer_p->bearer_context_to_modify.s1_eNB_fteid) , (&eps_bearer_entry_p->enb_ip_address_for_S1u) );
eps_bearer_entry_p->enb_teid_for_S1u = modify_bearer_p->bearer_context_to_modify.s1_eNB_fteid.teid;
......@@ -564,6 +583,9 @@ int sgw_lite_handle_modify_bearer_request(SgwModifyBearerRequest *modify_bearer_
modify_response_p->choice.bearer_for_removal.cause = CONTEXT_NOT_FOUND;
modify_response_p->cause = CONTEXT_NOT_FOUND;
modify_response_p->trxn = modify_bearer_p->trxn;
SPGW_APP_DEBUG("Rx MODIFY_BEARER_REQUEST, teid %u CONTEXT_NOT_FOUND\n",
modify_bearer_p->teid);
return itti_send_msg_to_task(to_task, INSTANCE_DEFAULT, message_p);
}
return -1;
......
......@@ -242,7 +242,7 @@ void udp_eNB_receiver(struct udp_socket_desc_s *udp_sock_pP)
while (1) {
from_len = (socklen_t)sizeof(struct sockaddr_in);
LOG_I(UDP_, "before recvfrom sd %d\n", udp_sock_pP->sd);
LOG_D(UDP_, "before recvfrom sd %d\n", udp_sock_pP->sd);
if ((n = recvfrom(udp_sock_pP->sd, l_buffer, sizeof(l_buffer), 0,
(struct sockaddr *)&addr, &from_len)) < 0) {
LOG_E(UDP_, "Recvfrom failed %s\n", strerror(errno));
......@@ -261,7 +261,7 @@ void udp_eNB_receiver(struct udp_socket_desc_s *udp_sock_pP)
LOG_I(UDP_, "Msg of length %d received from %s:%u\n",
n, inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
if (itti_send_msg_to_task(udp_sock_pP->task_id, INSTANCE_DEFAULT, message_p) < 0) {
LOG_I(UDP_, "Failed to send message %d to task %d\n",
LOG_D(UDP_, "Failed to send message %d to task %d\n",
UDP_DATA_IND,
udp_sock_pP->task_id);
break;
......@@ -338,7 +338,7 @@ void *udp_eNB_task(void *args_p)
udp_sd = udp_sock_p->sd;
pthread_mutex_unlock(&udp_socket_list_mutex);
LOG_I(UDP_, "[%d] Sending message of size %u to "IPV4_ADDR" and port %u\n",
LOG_D(UDP_, "[%d] Sending message of size %u to "IPV4_ADDR" and port %u\n",
udp_sd,
udp_data_req_p->buffer_length,
IPV4_ADDR_FORMAT(udp_data_req_p->peer_address),
......@@ -366,7 +366,7 @@ void *udp_eNB_task(void *args_p)
} break;
default: {
LOG_I(UDP_, "Unkwnon message ID %d:%s\n",
LOG_D(UDP_, "Unkwnon message ID %d:%s\n",
ITTI_MSG_ID(received_message_p),
ITTI_MSG_NAME(received_message_p));
} break;
......
......@@ -152,8 +152,8 @@ do { \
#define MCC_HUNDREDS(vALUE) \
((vALUE) / 100)
/* When MNC is only composed of 2 digits, set the hundreds unit to 0xf */
#define MNC_HUNDREDS(vALUE) \
(((vALUE) / 100) == 0 ? 15 : (vALUE) / 100)
#define MNC_HUNDREDS(vALUE, mNCdIGITlENGTH) \
( mNCdIGITlENGTH == 2 ? 15 : (vALUE) / 100)
#define MCC_MNC_DECIMAL(vALUE) \
(((vALUE) / 10) % 10)
#define MCC_MNC_DIGIT(vALUE) \
......@@ -167,30 +167,36 @@ do { \
(bUFFER)[2] = MCC_MNC_DIGIT(mCC); \
} while(0)
#define MCC_MNC_TO_PLMNID(mCC, mNC, oCTETsTRING) \
#define MCC_MNC_TO_PLMNID(mCC, mNC, mNCdIGITlENGTH, oCTETsTRING) \
do { \
(oCTETsTRING)->buf = calloc(3, sizeof(uint8_t)); \
(oCTETsTRING)->buf[0] = (MCC_MNC_DECIMAL(mCC) << 4) | MCC_HUNDREDS(mCC); \
(oCTETsTRING)->buf[1] = (MNC_HUNDREDS(mNC) << 4) | MCC_MNC_DIGIT(mCC); \
(oCTETsTRING)->buf[1] = (MNC_HUNDREDS(mNC,mNCdIGITlENGTH) << 4) | MCC_MNC_DIGIT(mCC); \
(oCTETsTRING)->buf[2] = (MCC_MNC_DIGIT(mNC) << 4) | MCC_MNC_DECIMAL(mNC); \
(oCTETsTRING)->size = 3; \
} while(0)
#define MCC_MNC_TO_TBCD(mCC, mNC, tBCDsTRING) \
#define MCC_MNC_TO_TBCD(mCC, mNC, mNCdIGITlENGTH, tBCDsTRING) \
do { \
char _buf[3]; \
DevAssert((mNCdIGITlENGTH == 3) || (mNCdIGITlENGTH == 2)); \
_buf[0] = (MCC_MNC_DECIMAL(mCC) << 4) | MCC_HUNDREDS(mCC); \
_buf[1] = (MNC_HUNDREDS(mNC) << 4) | MCC_MNC_DIGIT(mCC); \
_buf[1] = (MNC_HUNDREDS(mNC,mNCdIGITlENGTH) << 4) | MCC_MNC_DIGIT(mCC);\
_buf[2] = (MCC_MNC_DIGIT(mNC) << 4) | MCC_MNC_DECIMAL(mNC); \
OCTET_STRING_fromBuf(tBCDsTRING, _buf, 3); \
} while(0)
#define TBCD_TO_MCC_MNC(tBCDsTRING, mCC, mNC) \
#define TBCD_TO_MCC_MNC(tBCDsTRING, mCC, mNC, mNCdIGITlENGTH) \
do { \
int mNC_hundred; \
DevAssert((tBCDsTRING)->size == 3); \
mNC_hundred = (((tBCDsTRING)->buf[1] & 0xf0) >> 4); \
if (mNC_hundred == 0xf) mNC_hundred = 0; \
if (mNC_hundred == 0xf) { \
mNC_hundred = 0; \
mNCdIGITlENGTH = 2; \
} else { \
mNCdIGITlENGTH = 3; \
} \
mCC = (((((tBCDsTRING)->buf[0]) & 0xf0) >> 4) * 10) + \
((((tBCDsTRING)->buf[0]) & 0x0f) * 100) + \
(((tBCDsTRING)->buf[1]) & 0x0f); \
......@@ -219,11 +225,12 @@ do { \
tBCDsTRING[2] = (pLMN.MNCdigit2 << 4) | pLMN.MNCdigit3; \
} while(0)
#define PLMN_T_TO_MCC_MNC(pLMN, mCC, mNC) \
do { \
#define PLMN_T_TO_MCC_MNC(pLMN, mCC, mNC, mNCdIGITlENGTH) \
do { \
mCC = pLMN.MCCdigit3 * 100 + pLMN.MCCdigit2 * 10 + pLMN.MCCdigit1; \
mNC = (pLMN.MNCdigit3 == 0xF ? 0 : pLMN.MNCdigit3 * 100) \
+ pLMN.MNCdigit2 * 10 + pLMN.MNCdigit1; \
mNCdIGITlENGTH = (pLMN.MNCdigit3 == 0xF ? 2 : 3); \
mNC = (mNCdIGITlENGTH == 2 ? 0 : pLMN.MNCdigit3 * 100) \
+ pLMN.MNCdigit2 * 10 + pLMN.MNCdigit1; \
} while(0)
#define MACRO_ENB_ID_TO_BIT_STRING(mACRO, bITsTRING) \
......
......@@ -113,16 +113,20 @@ void mme_config_init(mme_config_t *mme_config_p)
static int config_parse_file(mme_config_t *mme_config_p)
{
config_t cfg;
config_setting_t *setting_mme = NULL;
config_setting_t *setting = NULL;
config_setting_t *subsetting = NULL;
config_setting_t *sub2setting = NULL;
config_setting_t *setting_mme = NULL;
config_setting_t *setting = NULL;
config_setting_t *subsetting = NULL;
config_setting_t *sub2setting = NULL;
long int alongint;
int i, num;
char *astring = NULL;
char *address = NULL;
char *cidr = NULL;
char *astring = NULL;
char *address = NULL;
char *cidr = NULL;
const char* tac = NULL;
const char* mcc = NULL;
const char* mnc = NULL;
char *sgw_ip_address_for_S1u_S12_S4_up = NULL;
char *mme_interface_name_for_S1_MME = NULL;
......@@ -258,26 +262,33 @@ static int config_parse_file(mme_config_t *mme_config_p)
if (subsetting != NULL) {
num = config_setting_length(subsetting);
if (mme_config_p->gummei.nb_plmns != num) {
if (mme_config_p->gummei.plmn_mcc != NULL) free(mme_config_p->gummei.plmn_mcc);
if (mme_config_p->gummei.plmn_mnc != NULL) free(mme_config_p->gummei.plmn_mnc);
if (mme_config_p->gummei.plmn_tac != NULL) free(mme_config_p->gummei.plmn_tac);
mme_config_p->gummei.plmn_mcc = calloc(num, sizeof(*mme_config_p->gummei.plmn_mcc));
mme_config_p->gummei.plmn_mnc = calloc(num, sizeof(*mme_config_p->gummei.plmn_mnc));
mme_config_p->gummei.plmn_tac = calloc(num, sizeof(*mme_config_p->gummei.plmn_tac));
if (mme_config_p->gummei.plmn_mcc != NULL) free(mme_config_p->gummei.plmn_mcc);
if (mme_config_p->gummei.plmn_mnc != NULL) free(mme_config_p->gummei.plmn_mnc);
if (mme_config_p->gummei.plmn_mnc_len != NULL) free(mme_config_p->gummei.plmn_mnc_len);
if (mme_config_p->gummei.plmn_tac != NULL) free(mme_config_p->gummei.plmn_tac);
mme_config_p->gummei.plmn_mcc = calloc(num, sizeof(*mme_config_p->gummei.plmn_mcc));
mme_config_p->gummei.plmn_mnc = calloc(num, sizeof(*mme_config_p->gummei.plmn_mnc));
mme_config_p->gummei.plmn_mnc_len = calloc(num, sizeof(*mme_config_p->gummei.plmn_mnc_len));
mme_config_p->gummei.plmn_tac = calloc(num, sizeof(*mme_config_p->gummei.plmn_tac));
}
mme_config_p->gummei.nb_plmns = num;
for (i = 0; i < num; i++) {
sub2setting = config_setting_get_elem(subsetting, i);
if (sub2setting != NULL) {
if( (config_setting_lookup_int( sub2setting, MME_CONFIG_STRING_MCC, &alongint) )) {
mme_config_p->gummei.plmn_mcc[i] = (uint16_t)alongint;
if( (config_setting_lookup_string( sub2setting, MME_CONFIG_STRING_MCC, &mcc) )) {
mme_config_p->gummei.plmn_mcc[i] = (uint16_t)atoi(mcc);
}
if( (config_setting_lookup_int( sub2setting, MME_CONFIG_STRING_MNC, &alongint) )) {
mme_config_p->gummei.plmn_mnc[i] = (uint16_t)alongint;
if( (config_setting_lookup_string( sub2setting, MME_CONFIG_STRING_MNC, &mnc) )) {
mme_config_p->gummei.plmn_mnc[i] = (uint16_t)atoi(mnc);
mme_config_p->gummei.plmn_mnc_len[i] = strlen(mnc);
AssertFatal((mme_config_p->gummei.plmn_mnc_len[i] == 2) || (mme_config_p->gummei.plmn_mnc_len[i] == 3),
"Bad MNC length %u, must be 2 or 3", mme_config_p->gummei.plmn_mnc_len[i]);
}
if( (config_setting_lookup_int( sub2setting, MME_CONFIG_STRING_TAC, &alongint) )) {
mme_config_p->gummei.plmn_tac[i] = (uint16_t)alongint;
if( (config_setting_lookup_string( sub2setting, MME_CONFIG_STRING_TAC, &tac) )) {
mme_config_p->gummei.plmn_tac[i] = (uint16_t)atoi(tac);
AssertFatal(mme_config_p->gummei.plmn_tac[i] != 0,
"TAC must not be 0");
}
}
}
......@@ -355,6 +366,8 @@ do { \
static void config_display(mme_config_t *mme_config_p)
{
int j;
fprintf(stdout, "==== EURECOM %s v%s ====\n", PACKAGE_NAME, PACKAGE_VERSION);
fprintf(stdout, "Configuration:\n");
fprintf(stdout, "- File ...............: %s\n", mme_config_p->config_file);
......@@ -400,10 +413,20 @@ static void config_display(mme_config_t *mme_config_p)
DISPLAY_ARRAY(mme_config_p->gummei.nb_mme_gid, "| %u ", mme_config_p->gummei.mme_gid[i]);
fprintf(stdout, " mme codes ........:\n ");
DISPLAY_ARRAY(mme_config_p->gummei.nb_mmec, "| %u ", mme_config_p->gummei.mmec[i]);
fprintf(stdout, " plmns ............: (mcc.mnc:tac)\n ");
DISPLAY_ARRAY(mme_config_p->gummei.nb_plmns, "| %3u.%3u:%u ",
mme_config_p->gummei.plmn_mcc[i], mme_config_p->gummei.plmn_mnc[i],
mme_config_p->gummei.plmn_tac[i]);
fprintf(stdout, " plmns ............: (mcc.mnc:tac)\n");
for (j= 0; j < mme_config_p->gummei.nb_plmns; j++) {
if (mme_config_p->gummei.plmn_mnc_len[j] ==2 ) {
fprintf(stdout, " %3u.%3u:%u\n",
mme_config_p->gummei.plmn_mcc[j],
mme_config_p->gummei.plmn_mnc[j],
mme_config_p->gummei.plmn_tac[j]);
} else {
fprintf(stdout, " %3u.%03u:%u\n",
mme_config_p->gummei.plmn_mcc[j],
mme_config_p->gummei.plmn_mnc[j],
mme_config_p->gummei.plmn_tac[j]);
}
}
fprintf(stdout, "- S6A:\n");
fprintf(stdout, " conf file ........: %s\n", mme_config_p->s6a_config.conf_file);
}
......
......@@ -104,6 +104,7 @@ typedef struct mme_config_s {
uint8_t nb_plmns;
uint16_t *plmn_mcc;
uint16_t *plmn_mnc;
uint16_t *plmn_mnc_len;
uint16_t *plmn_tac;
} gummei;
......
......@@ -26,7 +26,7 @@ typedef struct gtpv1u_enb_create_tunnel_resp_s {
int num_tunnels;
teid_t enb_S1u_teid[GTPV1U_MAX_BEARERS_PER_UE]; ///< Tunnel Endpoint Identifier
ebi_t eps_bearer_id[GTPV1U_MAX_BEARERS_PER_UE];
transport_layer_addr_t enb_addr[GTPV1U_MAX_BEARERS_PER_UE];
transport_layer_addr_t enb_addr;
} gtpv1u_enb_create_tunnel_resp_t;
typedef struct gtpv1u_enb_update_tunnel_req_s {
......
......@@ -47,6 +47,10 @@ typedef boolean_t eNB_flag_t;
#define ENB_FLAG_NO FALSE
#define ENB_FLAG_YES TRUE
typedef boolean_t srb_flag_t;
#define SRB_FLAG_NO FALSE
#define SRB_FLAG_YES TRUE
typedef enum link_direction_e {
UNKNOWN_DIR = 0,
DIR_UPLINK = 1,
......
......@@ -64,6 +64,7 @@ typedef struct RrcConfigurationReq_s {
uint16_t mcc;
uint16_t mnc;
uint8_t mnc_digit_length;
paging_drx_t default_drx;
......
......@@ -141,6 +141,7 @@ typedef enum rrc_establishment_cause_e {
typedef struct s1ap_gummei_s {
uint16_t mcc;
uint16_t mnc;
uint8_t mnc_len;
uint8_t mme_code;
uint16_t mme_group_id;
} s1ap_gummei_t;
......@@ -193,6 +194,13 @@ typedef struct transport_layer_addr_s {
uint8_t buffer[20];
} transport_layer_addr_t;
#define TRANSPORT_LAYER_ADDR_COPY(dEST,sOURCE) \
do { \
AssertFatal(sOURCE.len <= 20); \
memcpy(dEST.buffer, sOURCE.buffer, sOURCE.len); \
dEST.length = sOURCE.length; \
} while (0)
typedef struct e_rab_level_qos_parameter_s {
uint8_t qci;
......@@ -266,6 +274,7 @@ typedef struct s1ap_register_enb_req_s {
*/
uint16_t mcc;
uint16_t mnc;
uint8_t mnc_digit_length;
/* Default Paging DRX of the eNB as defined in TS 36.304 */
paging_drx_t default_drx;
......
......@@ -87,7 +87,7 @@ static void configure_phy(uint32_t enb_id, const Enb_properties_array_t *enb_pro
/*------------------------------------------------------------------------------*/
static void configure_rrc(uint32_t enb_id, const Enb_properties_array_t *enb_properties)
{
MessageDef *msg_p;
MessageDef *msg_p = NULL;
msg_p = itti_alloc_new_message (TASK_ENB_APP, RRC_CONFIGURATION_REQ);
......@@ -95,6 +95,7 @@ static void configure_rrc(uint32_t enb_id, const Enb_properties_array_t *enb_pro
RRC_CONFIGURATION_REQ (msg_p).tac = enb_properties->properties[enb_id]->tac;