Use an un-official community collaboration version of asn1c
1. It's no need to modify LTE-RRC's ASN.1 file for enabling option group feature in generate_asn1. 2. It's no need to patch the C header files generated from LTE-RRC/S1AP/X2AP's ASN.1 in fix_asn1. 3. It's no need to pre-process S1AP/X2AP's ASN.1 for enabling information object class feature by asn1tostruct.py. This commit requires an un-official version of asn1c which are collaboration of asn1c community members and `build_helper` is modified in this commit accordingly : https://github.com/brchiu/asn1c/tree/velichkov_s1ap_plus_option_group This asn1c can also convert ASN.1 of 5G NR RRC (38.331, v15.1.0) and generate C files with -findirect-choice command line option without tweaking ASN.1 file. Examples for how to use this asn1c for S1AP are in S1AP files, e.g. s1ap_eNB_nas_procedures.c and s1ap_eNB_handler.c. There is an modified openair-cn (based on tag 0.5.0) with this new asn1c at : https://github.com/brchiu/openair-cn/tree/new-asn1c Basic S1AP interaction and data transfer operation between OAI eNB and this modified openair-cn has been tested. Note: Community version of asn1c is keeping evolved to provide better usage.
This commit is contained in:
+118
-65
@@ -20,8 +20,8 @@
|
||||
*/
|
||||
|
||||
/*! \file s1ap_eNB.c
|
||||
* \brief S1AP eNB task
|
||||
* \author S. Roux and Navid Nikaein
|
||||
* \brief S1AP eNB task
|
||||
* \author S. Roux and Navid Nikaein
|
||||
* \date 2010 - 2015
|
||||
* \email: navid.nikaein@eurecom.fr
|
||||
* \version 1.0
|
||||
@@ -42,7 +42,6 @@
|
||||
#include "s1ap_eNB_default_values.h"
|
||||
|
||||
#include "s1ap_common.h"
|
||||
#include "s1ap_ies_defs.h"
|
||||
|
||||
#include "s1ap_eNB_defs.h"
|
||||
#include "s1ap_eNB.h"
|
||||
@@ -104,7 +103,7 @@ static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p,
|
||||
sctp_new_association_req_t *sctp_new_association_req_p = NULL;
|
||||
s1ap_eNB_mme_data_t *s1ap_mme_data_p = NULL;
|
||||
struct s1ap_eNB_mme_data_s *mme = NULL;
|
||||
|
||||
|
||||
DevAssert(instance_p != NULL);
|
||||
DevAssert(mme_ip_address != NULL);
|
||||
|
||||
@@ -125,25 +124,25 @@ static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p,
|
||||
memcpy(&sctp_new_association_req_p->local_address,
|
||||
local_ip_addr,
|
||||
sizeof(*local_ip_addr));
|
||||
|
||||
|
||||
S1AP_INFO("[eNB %d] check the mme registration state\n",instance_p->instance);
|
||||
|
||||
|
||||
mme = s1ap_eNB_get_MME_from_instance(instance_p);
|
||||
|
||||
if ( mme == NULL ) {
|
||||
|
||||
|
||||
/* Create new MME descriptor */
|
||||
s1ap_mme_data_p = calloc(1, sizeof(*s1ap_mme_data_p));
|
||||
DevAssert(s1ap_mme_data_p != NULL);
|
||||
|
||||
|
||||
s1ap_mme_data_p->cnx_id = s1ap_eNB_fetch_add_global_cnx_id();
|
||||
sctp_new_association_req_p->ulp_cnx_id = s1ap_mme_data_p->cnx_id;
|
||||
|
||||
|
||||
s1ap_mme_data_p->assoc_id = -1;
|
||||
s1ap_mme_data_p->s1ap_eNB_instance = instance_p;
|
||||
|
||||
|
||||
STAILQ_INIT(&s1ap_mme_data_p->served_gummei);
|
||||
|
||||
|
||||
/* Insert the new descriptor in list of known MME
|
||||
* but not yet associated.
|
||||
*/
|
||||
@@ -156,25 +155,23 @@ static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p,
|
||||
sctp_new_association_req_p->ulp_cnx_id = mme->cnx_id;
|
||||
|
||||
S1AP_INFO("[eNB %d] MME already registered, retrive the data (state %d, cnx %d, mme_nb %d, mme_pending_nb %d)\n",
|
||||
instance_p->instance,
|
||||
mme->state, mme->cnx_id,
|
||||
instance_p->s1ap_mme_nb, instance_p->s1ap_mme_pending_nb);
|
||||
instance_p->instance,
|
||||
mme->state, mme->cnx_id,
|
||||
instance_p->s1ap_mme_nb, instance_p->s1ap_mme_pending_nb);
|
||||
|
||||
/*s1ap_mme_data_p->cnx_id = mme->cnx_id;
|
||||
sctp_new_association_req_p->ulp_cnx_id = mme->cnx_id;
|
||||
|
||||
|
||||
s1ap_mme_data_p->assoc_id = -1;
|
||||
s1ap_mme_data_p->s1ap_eNB_instance = instance_p;
|
||||
*/
|
||||
*/
|
||||
} else {
|
||||
|
||||
S1AP_WARN("[eNB %d] MME already registered but not in the waiting state, retrive the data (state %d, cnx %d, mme_nb %d, mme_pending_nb %d)\n",
|
||||
instance_p->instance,
|
||||
mme->state, mme->cnx_id,
|
||||
instance_p->s1ap_mme_nb, instance_p->s1ap_mme_pending_nb);
|
||||
|
||||
instance_p->instance,
|
||||
mme->state, mme->cnx_id,
|
||||
instance_p->s1ap_mme_nb, instance_p->s1ap_mme_pending_nb);
|
||||
}
|
||||
|
||||
|
||||
itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message_p);
|
||||
}
|
||||
|
||||
@@ -188,9 +185,8 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *
|
||||
|
||||
/* Look if the provided instance already exists */
|
||||
new_instance = s1ap_eNB_get_instance(instance);
|
||||
|
||||
|
||||
if (new_instance != NULL) {
|
||||
|
||||
if (new_instance != NULL) {
|
||||
/* Checks if it is a retry on the same eNB */
|
||||
DevCheck(new_instance->eNB_id == s1ap_register_eNB->eNB_id, new_instance->eNB_id, s1ap_register_eNB->eNB_id, 0);
|
||||
DevCheck(new_instance->cell_type == s1ap_register_eNB->cell_type, new_instance->cell_type, s1ap_register_eNB->cell_type, 0);
|
||||
@@ -221,9 +217,9 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *
|
||||
s1ap_eNB_insert_new_instance(new_instance);
|
||||
|
||||
S1AP_INFO("Registered new eNB[%d] and %s eNB id %u\n",
|
||||
instance,
|
||||
s1ap_register_eNB->cell_type == CELL_MACRO_ENB ? "macro" : "home",
|
||||
s1ap_register_eNB->eNB_id);
|
||||
instance,
|
||||
s1ap_register_eNB->cell_type == CELL_MACRO_ENB ? "macro" : "home",
|
||||
s1ap_register_eNB->eNB_id);
|
||||
}
|
||||
|
||||
DevCheck(s1ap_register_eNB->nb_mme <= S1AP_MAX_NB_MME_IP_ADDRESS,
|
||||
@@ -232,7 +228,7 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *
|
||||
/* Trying to connect to provided list of MME ip address */
|
||||
for (index = 0; index < s1ap_register_eNB->nb_mme; index++) {
|
||||
s1ap_eNB_register_mme(new_instance,
|
||||
&s1ap_register_eNB->mme_ip_address[index],
|
||||
&s1ap_register_eNB->mme_ip_address[index],
|
||||
&s1ap_register_eNB->enb_ip_address,
|
||||
s1ap_register_eNB->sctp_in_streams,
|
||||
s1ap_register_eNB->sctp_out_streams);
|
||||
@@ -425,12 +421,11 @@ 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_S1SetupRequestIEs_t *s1SetupRequest_p;
|
||||
S1ap_PLMNidentity_t plmnIdentity;
|
||||
S1ap_SupportedTAs_Item_t ta;
|
||||
|
||||
S1AP_S1AP_PDU_t pdu;
|
||||
S1AP_S1SetupRequest_t *out;
|
||||
S1AP_S1SetupRequestIEs_t *ie;
|
||||
S1AP_SupportedTAs_Item_t *ta;
|
||||
S1AP_PLMNidentity_t *plmn;
|
||||
uint8_t *buffer;
|
||||
uint32_t len;
|
||||
int ret = 0;
|
||||
@@ -438,43 +433,101 @@ static int s1ap_eNB_generate_s1_setup_request(
|
||||
DevAssert(instance_p != NULL);
|
||||
DevAssert(s1ap_mme_data_p != NULL);
|
||||
|
||||
memset(&message, 0, sizeof(s1ap_message));
|
||||
|
||||
message.direction = S1AP_PDU_PR_initiatingMessage;
|
||||
message.procedureCode = S1ap_ProcedureCode_id_S1Setup;
|
||||
message.criticality = S1ap_Criticality_reject;
|
||||
|
||||
s1SetupRequest_p = &message.msg.s1ap_S1SetupRequestIEs;
|
||||
memset((void *)&plmnIdentity, 0, sizeof(S1ap_PLMNidentity_t));
|
||||
|
||||
memset((void *)&ta, 0, sizeof(S1ap_SupportedTAs_Item_t));
|
||||
|
||||
s1ap_mme_data_p->state = S1AP_ENB_STATE_WAITING;
|
||||
|
||||
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);
|
||||
/* Prepare the S1AP message to encode */
|
||||
memset(&pdu, 0, sizeof(pdu));
|
||||
pdu.present = S1AP_S1AP_PDU_PR_initiatingMessage;
|
||||
pdu.choice.initiatingMessage.procedureCode = S1AP_ProcedureCode_id_S1Setup;
|
||||
pdu.choice.initiatingMessage.criticality = S1AP_Criticality_reject;
|
||||
pdu.choice.initiatingMessage.value.present = S1AP_InitiatingMessage__value_PR_S1SetupRequest;
|
||||
out = &pdu.choice.initiatingMessage.value.choice.S1SetupRequest;
|
||||
|
||||
/* mandatory */
|
||||
ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t));
|
||||
ie->id = S1AP_ProtocolIE_ID_id_Global_ENB_ID;
|
||||
ie->criticality = S1AP_Criticality_reject;
|
||||
ie->value.present = S1AP_S1SetupRequestIEs__value_PR_Global_ENB_ID;
|
||||
MCC_MNC_TO_PLMNID(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length,
|
||||
&s1SetupRequest_p->global_ENB_ID.pLMNidentity);
|
||||
&ie->value.choice.Global_ENB_ID.pLMNidentity);
|
||||
ie->value.choice.Global_ENB_ID.eNB_ID.present = S1AP_ENB_ID_PR_macroENB_ID;
|
||||
MACRO_ENB_ID_TO_BIT_STRING(instance_p->eNB_id,
|
||||
&ie->value.choice.Global_ENB_ID.eNB_ID.choice.macroENB_ID);
|
||||
S1AP_INFO("%d -> %02x%02x%02x\n", instance_p->eNB_id,
|
||||
ie->value.choice.Global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[0],
|
||||
ie->value.choice.Global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[1],
|
||||
ie->value.choice.Global_ENB_ID.eNB_ID.choice.macroENB_ID.buf[2]);
|
||||
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||
|
||||
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, instance_p->mnc_digit_length, &plmnIdentity);
|
||||
|
||||
ASN_SEQUENCE_ADD(&ta.broadcastPLMNs.list, &plmnIdentity);
|
||||
ASN_SEQUENCE_ADD(&s1SetupRequest_p->supportedTAs.list, &ta);
|
||||
|
||||
s1SetupRequest_p->defaultPagingDRX = instance_p->default_drx;
|
||||
|
||||
if (instance_p->eNB_name != NULL) {
|
||||
s1SetupRequest_p->presenceMask |= S1AP_S1SETUPREQUESTIES_ENBNAME_PRESENT;
|
||||
OCTET_STRING_fromBuf(&s1SetupRequest_p->eNBname, instance_p->eNB_name,
|
||||
/* optional */
|
||||
if (instance_p->eNB_name) {
|
||||
ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t));
|
||||
ie->id = S1AP_ProtocolIE_ID_id_eNBname;
|
||||
ie->criticality = S1AP_Criticality_ignore;
|
||||
ie->value.present = S1AP_S1SetupRequestIEs__value_PR_ENBname;
|
||||
OCTET_STRING_fromBuf(&ie->value.choice.ENBname, instance_p->eNB_name,
|
||||
strlen(instance_p->eNB_name));
|
||||
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||
}
|
||||
|
||||
if (s1ap_eNB_encode_pdu(&message, &buffer, &len) < 0) {
|
||||
/* mandatory */
|
||||
ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t));
|
||||
ie->id = S1AP_ProtocolIE_ID_id_SupportedTAs;
|
||||
ie->criticality = S1AP_Criticality_reject;
|
||||
ie->value.present = S1AP_S1SetupRequestIEs__value_PR_SupportedTAs;
|
||||
{
|
||||
ta = (S1AP_SupportedTAs_Item_t *)calloc(1, sizeof(S1AP_SupportedTAs_Item_t));
|
||||
INT16_TO_OCTET_STRING(instance_p->tac, &ta->tAC);
|
||||
{
|
||||
plmn = (S1AP_PLMNidentity_t *)calloc(1, sizeof(S1AP_PLMNidentity_t));
|
||||
MCC_MNC_TO_TBCD(instance_p->mcc, instance_p->mnc, instance_p->mnc_digit_length, plmn);
|
||||
ASN_SEQUENCE_ADD(&ta->broadcastPLMNs.list, plmn);
|
||||
}
|
||||
ASN_SEQUENCE_ADD(&ie->value.choice.SupportedTAs.list, ta);
|
||||
}
|
||||
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||
|
||||
/* mandatory */
|
||||
ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t));
|
||||
ie->id = S1AP_ProtocolIE_ID_id_DefaultPagingDRX;
|
||||
ie->criticality = S1AP_Criticality_ignore;
|
||||
ie->value.present = S1AP_S1SetupRequestIEs__value_PR_PagingDRX;
|
||||
ie->value.choice.PagingDRX = instance_p->default_drx;
|
||||
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||
|
||||
/* optional */
|
||||
if (0) {
|
||||
ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t));
|
||||
ie->id = S1AP_ProtocolIE_ID_id_CSG_IdList;
|
||||
ie->criticality = S1AP_Criticality_reject;
|
||||
ie->value.present = S1AP_S1SetupRequestIEs__value_PR_CSG_IdList;
|
||||
// ie->value.choice.CSG_IdList = ;
|
||||
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||
}
|
||||
|
||||
/* optional */
|
||||
#if (S1AP_VERSION >= MAKE_VERSION(13, 0, 0))
|
||||
if (0) {
|
||||
ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t));
|
||||
ie->id = S1AP_ProtocolIE_ID_id_UE_RetentionInformation;
|
||||
ie->criticality = S1AP_Criticality_ignore;
|
||||
ie->value.present = S1AP_S1SetupRequestIEs__value_PR_UE_RetentionInformation;
|
||||
// ie->value.choice.UE_RetentionInformation = ;
|
||||
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||
}
|
||||
|
||||
/* optional */
|
||||
if (0) {
|
||||
ie = (S1AP_S1SetupRequestIEs_t *)calloc(1, sizeof(S1AP_S1SetupRequestIEs_t));
|
||||
ie->id = S1AP_ProtocolIE_ID_id_NB_IoT_DefaultPagingDRX;
|
||||
ie->criticality = S1AP_Criticality_ignore;
|
||||
ie->value.present = S1AP_S1SetupRequestIEs__value_PR_NB_IoT_DefaultPagingDRX;
|
||||
// ie->value.choice.NB_IoT_DefaultPagingDRX = ;
|
||||
ASN_SEQUENCE_ADD(&out->protocolIEs.list, ie);
|
||||
}
|
||||
#endif /* #if (S1AP_VERSION >= MAKE_VERSION(14, 0, 0)) */
|
||||
|
||||
if (s1ap_eNB_encode_pdu(&pdu, &buffer, &len) < 0) {
|
||||
S1AP_ERROR("Failed to encode S1 setup request\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user