fix the issue with the number of pending mme/s1ap connections
This commit is contained in:
@@ -68,6 +68,7 @@ typedef uint32_t frame_t;
|
||||
typedef int32_t sframe_t;
|
||||
typedef uint32_t sub_frame_t;
|
||||
typedef uint8_t module_id_t;
|
||||
typedef uint8_t configured_t;
|
||||
typedef uint8_t eNB_index_t;
|
||||
typedef uint16_t ue_id_t;
|
||||
typedef int16_t smodule_id_t;
|
||||
@@ -215,6 +216,7 @@ typedef struct protocol_ctxt_s {
|
||||
frame_t frame; /*!< \brief LTE frame number.*/
|
||||
sub_frame_t subframe; /*!< \brief LTE sub frame number.*/
|
||||
eNB_index_t eNB_index; /*!< \brief valid for UE indicating the index of connected eNB(s) */
|
||||
configured_t configured; /*!< \brief flag indicating whether the instance is configured or not */
|
||||
} protocol_ctxt_t;
|
||||
// warning time hardcoded
|
||||
#define PROTOCOL_CTXT_TIME_MILLI_SECONDS(CtXt_h) ((CtXt_h)->frame*10+(CtXt_h)->subframe)
|
||||
|
||||
@@ -255,6 +255,8 @@ static uint32_t eNB_app_register(uint32_t enb_id_start, uint32_t enb_id_end, con
|
||||
str = inet_ntoa(addr);
|
||||
strcpy(s1ap_register_eNB->enb_ip_address.ipv4_address, str);
|
||||
|
||||
LOG_I(ENB_APP,"[eNB %d] eNB_app_register for instance %d\n", enb_id, ENB_MODULE_ID_TO_INSTANCE(enb_id));
|
||||
|
||||
itti_send_msg_to_task (TASK_S1AP, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
|
||||
|
||||
register_enb_pending++;
|
||||
|
||||
@@ -29,8 +29,9 @@
|
||||
|
||||
/*! \file pdcp.c
|
||||
* \brief pdcp interface with RLC
|
||||
* \author Lionel GAUTHIER and Navid Nikaein
|
||||
* \author Navid Nikaein and Lionel GAUTHIER
|
||||
* \date 2009-2012
|
||||
* \email navid.nikaein@eurecom.fr
|
||||
* \version 1.0
|
||||
*/
|
||||
|
||||
@@ -83,7 +84,7 @@ extern int otg_enabled;
|
||||
* code at targets/TEST/PDCP/test_pdcp.c:test_pdcp_data_req()
|
||||
*/
|
||||
boolean_t pdcp_data_req(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
protocol_ctxt_t* ctxt_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const rb_id_t rb_idP,
|
||||
const mui_t muiP,
|
||||
@@ -105,7 +106,6 @@ boolean_t pdcp_data_req(
|
||||
rlc_op_status_t rlc_status;
|
||||
boolean_t ret = TRUE;
|
||||
|
||||
|
||||
hash_key_t key = HASHTABLE_NOT_A_KEY_VALUE;
|
||||
hashtable_rc_t h_rc;
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_IN);
|
||||
@@ -116,28 +116,6 @@ boolean_t pdcp_data_req(
|
||||
T(T_ENB_PDCP_DL, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->rnti), T_INT(rb_idP), T_INT(sdu_buffer_sizeP));
|
||||
#endif
|
||||
|
||||
if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) {
|
||||
AssertError (rb_idP < NB_RB_MBMS_MAX, return FALSE, "RB id is too high (%u/%d) %u %u!\n", rb_idP, NB_RB_MBMS_MAX, ctxt_pP->module_id, ctxt_pP->rnti);
|
||||
} else {
|
||||
if (srb_flagP) {
|
||||
AssertError (rb_idP < 3, return FALSE, "RB id is too high (%u/%d) %u %u!\n", rb_idP, 3, ctxt_pP->module_id, ctxt_pP->rnti);
|
||||
} else {
|
||||
AssertError (rb_idP < maxDRB, return FALSE, "RB id is too high (%u/%d) %u %u!\n", rb_idP, maxDRB, ctxt_pP->module_id, ctxt_pP->rnti);
|
||||
}
|
||||
}
|
||||
|
||||
key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
|
||||
h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);
|
||||
|
||||
if (h_rc != HASH_TABLE_OK) {
|
||||
if (modeP != PDCP_TRANSMISSION_MODE_TRANSPARENT) {
|
||||
LOG_W(PDCP, PROTOCOL_CTXT_FMT" Instance is not configured for rb_id %d Ignoring SDU...\n",
|
||||
PROTOCOL_CTXT_ARGS(ctxt_pP),
|
||||
rb_idP);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (sdu_buffer_sizeP == 0) {
|
||||
LOG_W(PDCP, "Handed SDU is of size 0! Ignoring...\n");
|
||||
return FALSE;
|
||||
@@ -153,14 +131,40 @@ boolean_t pdcp_data_req(
|
||||
// XXX What does following call do?
|
||||
mac_xface->macphy_exit("PDCP sdu buffer size > MAX_IP_PACKET_SIZE");
|
||||
}
|
||||
|
||||
if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) {
|
||||
AssertError (rb_idP < NB_RB_MBMS_MAX, return FALSE, "RB id is too high (%u/%d) %u %u!\n", rb_idP, NB_RB_MBMS_MAX, ctxt_pP->module_id, ctxt_pP->rnti);
|
||||
} else {
|
||||
if (srb_flagP) {
|
||||
AssertError (rb_idP < 3, return FALSE, "RB id is too high (%u/%d) %u %u!\n", rb_idP, 3, ctxt_pP->module_id, ctxt_pP->rnti);
|
||||
} else {
|
||||
AssertError (rb_idP < maxDRB, return FALSE, "RB id is too high (%u/%d) %u %u!\n", rb_idP, maxDRB, ctxt_pP->module_id, ctxt_pP->rnti);
|
||||
}
|
||||
}
|
||||
|
||||
key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
|
||||
h_rc = hashtable_get(pdcp_coll_p, key, (void**)&pdcp_p);
|
||||
|
||||
if (h_rc != HASH_TABLE_OK) {
|
||||
if (modeP != PDCP_TRANSMISSION_MODE_TRANSPARENT) {
|
||||
if ((ctxt_pP->configured == 0) && (ctxt_pP->frame%10 == 0))
|
||||
LOG_W(PDCP, PROTOCOL_CTXT_FMT" Instance is not configured for rb_id %d Ignoring SDU...\n",
|
||||
PROTOCOL_CTXT_ARGS(ctxt_pP),
|
||||
rb_idP);
|
||||
ctxt_pP->configured=0;
|
||||
return FALSE;
|
||||
}
|
||||
}else{
|
||||
// instance for a given RB is configured
|
||||
ctxt_pP->configured=1;
|
||||
}
|
||||
|
||||
if (ctxt_pP->enb_flag == ENB_FLAG_NO) {
|
||||
start_meas(&eNB_pdcp_stats[ctxt_pP->module_id].data_req);
|
||||
} else {
|
||||
start_meas(&UE_pdcp_stats[ctxt_pP->module_id].data_req);
|
||||
}
|
||||
|
||||
|
||||
// PDCP transparent mode for MBMS traffic
|
||||
|
||||
if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) {
|
||||
|
||||
@@ -221,7 +221,7 @@ typedef struct pdcp_mbms_s {
|
||||
* @ingroup _pdcp
|
||||
*/
|
||||
public_pdcp(boolean_t pdcp_data_req(
|
||||
const protocol_ctxt_t* const ctxt_pP,
|
||||
protocol_ctxt_t* ctxt_pP,
|
||||
const srb_flag_t srb_flagP,
|
||||
const rb_id_t rb_id,
|
||||
const mui_t muiP,
|
||||
|
||||
@@ -29,9 +29,10 @@
|
||||
|
||||
/*! \file pdcp_fifo.c
|
||||
* \brief pdcp interface with linux IP interface, have a look at http://man7.org/linux/man-pages/man7/netlink.7.html for netlink
|
||||
* \author Lionel GAUTHIER and Navid Nikaein
|
||||
* \date 2009
|
||||
* \author Navid Nikaein and Lionel GAUTHIER
|
||||
* \date 2009 - 2016
|
||||
* \version 0.5
|
||||
* \email navid.nikaein@eurecom.fr
|
||||
* \warning This component can be runned only in user-space
|
||||
* @ingroup pdcp
|
||||
*/
|
||||
|
||||
+59
-24
@@ -113,7 +113,8 @@ static void s1ap_eNB_register_mme(s1ap_eNB_instance_t *instance_p,
|
||||
MessageDef *message_p = NULL;
|
||||
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);
|
||||
|
||||
@@ -134,27 +135,58 @@ 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);
|
||||
|
||||
/* Create new MME descriptor */
|
||||
s1ap_mme_data_p = calloc(1, sizeof(*s1ap_mme_data_p));
|
||||
DevAssert(s1ap_mme_data_p != NULL);
|
||||
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.
|
||||
*/
|
||||
RB_INSERT(s1ap_mme_map, &instance_p->s1ap_mme_head, s1ap_mme_data_p);
|
||||
s1ap_mme_data_p->state = S1AP_ENB_STATE_WAITING;
|
||||
instance_p->s1ap_mme_nb ++;
|
||||
instance_p->s1ap_mme_pending_nb ++;
|
||||
} else if (mme->state == S1AP_ENB_STATE_WAITING) {
|
||||
instance_p->s1ap_mme_pending_nb ++;
|
||||
sctp_new_association_req_p->ulp_cnx_id = mme->cnx_id;
|
||||
|
||||
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.
|
||||
*/
|
||||
RB_INSERT(s1ap_mme_map, &instance_p->s1ap_mme_head, s1ap_mme_data_p);
|
||||
s1ap_mme_data_p->state = S1AP_ENB_STATE_WAITING;
|
||||
instance_p->s1ap_mme_nb ++;
|
||||
instance_p->s1ap_mme_pending_nb ++;
|
||||
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);
|
||||
|
||||
/*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);
|
||||
|
||||
}
|
||||
|
||||
S1AP_DEBUG("s1ap mme nb %d\n", instance_p->s1ap_mme_nb);
|
||||
|
||||
itti_send_msg_to_task(TASK_SCTP, instance_p->instance, message_p);
|
||||
}
|
||||
|
||||
@@ -163,13 +195,14 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *
|
||||
{
|
||||
s1ap_eNB_instance_t *new_instance;
|
||||
uint8_t index;
|
||||
|
||||
|
||||
DevAssert(s1ap_register_eNB != NULL);
|
||||
|
||||
/* 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);
|
||||
@@ -199,7 +232,7 @@ void s1ap_eNB_handle_register_eNB(instance_t instance, s1ap_register_enb_req_t *
|
||||
/* Add the new instance to the list of eNB (meaningfull in virtual mode) */
|
||||
s1ap_eNB_insert_new_instance(new_instance);
|
||||
|
||||
S1AP_DEBUG("Registered new eNB[%d] and %s eNB id %u\n",
|
||||
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);
|
||||
@@ -211,7 +244,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);
|
||||
@@ -228,6 +261,8 @@ void s1ap_eNB_handle_sctp_association_resp(instance_t instance, sctp_new_associa
|
||||
instance_p = s1ap_eNB_get_instance(instance);
|
||||
DevAssert(instance_p != NULL);
|
||||
|
||||
S1AP_WARN("s1ap cnx_id %d\n", sctp_new_association_resp->ulp_cnx_id);
|
||||
|
||||
s1ap_mme_data_p = s1ap_eNB_get_MME(instance_p, -1,
|
||||
sctp_new_association_resp->ulp_cnx_id);
|
||||
DevAssert(s1ap_mme_data_p != NULL);
|
||||
|
||||
@@ -27,6 +27,15 @@
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
/*! \file s1ap_eNB_management_procedures.c
|
||||
* \brief S1AP eNB task
|
||||
* \author S. Roux and Navid Nikaein
|
||||
* \date 2010 - 2016
|
||||
* \email: navid.nikaein@eurecom.fr
|
||||
* \version 1.0
|
||||
* @ingroup _s1ap
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
@@ -116,6 +125,23 @@ struct s1ap_eNB_mme_data_s *s1ap_eNB_get_MME(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct s1ap_eNB_mme_data_s *s1ap_eNB_get_MME_from_instance(
|
||||
s1ap_eNB_instance_t *instance_p)
|
||||
{
|
||||
|
||||
struct s1ap_eNB_mme_data_s *mme = NULL;
|
||||
struct s1ap_eNB_mme_data_s *mme_next = NULL;
|
||||
|
||||
for (mme = RB_MIN(s1ap_mme_map, &instance_p->s1ap_mme_head); mme!=NULL ; mme = mme_next) {
|
||||
mme_next = RB_NEXT(s1ap_mme_map, &instance_p->s1ap_mme_head, mme);
|
||||
if (mme->s1ap_eNB_instance == instance_p) {
|
||||
return mme;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s1ap_eNB_instance_t *s1ap_eNB_get_instance(instance_t instance)
|
||||
{
|
||||
s1ap_eNB_instance_t *temp = NULL;
|
||||
@@ -130,3 +156,41 @@ s1ap_eNB_instance_t *s1ap_eNB_get_instance(instance_t instance)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void s1ap_eNB_remove_mme_desc(s1ap_eNB_instance_t * instance)
|
||||
{
|
||||
|
||||
struct s1ap_eNB_mme_data_s *mme = NULL;
|
||||
struct s1ap_eNB_mme_data_s *mmeNext = NULL;
|
||||
struct plmn_identity_s* plmnInfo;
|
||||
struct served_group_id_s* groupInfo;
|
||||
struct served_gummei_s* gummeiInfo;
|
||||
struct mme_code_s* mmeCode;
|
||||
|
||||
for (mme = RB_MIN(s1ap_mme_map, &instance->s1ap_mme_head); mme; mme = mmeNext) {
|
||||
mmeNext = RB_NEXT(s1ap_mme_map, &instance->s1ap_mme_head, mme);
|
||||
RB_REMOVE(s1ap_mme_map, &instance->s1ap_mme_head, mme);
|
||||
while (!STAILQ_EMPTY(&mme->served_gummei)) {
|
||||
gummeiInfo = STAILQ_FIRST(&mme->served_gummei);
|
||||
STAILQ_REMOVE_HEAD(&mme->served_gummei, next);
|
||||
|
||||
while (!STAILQ_EMPTY(&gummeiInfo->served_plmns)) {
|
||||
plmnInfo = STAILQ_FIRST(&gummeiInfo->served_plmns);
|
||||
STAILQ_REMOVE_HEAD(&gummeiInfo->served_plmns, next);
|
||||
free(plmnInfo);
|
||||
}
|
||||
while (!STAILQ_EMPTY(&gummeiInfo->served_group_ids)) {
|
||||
groupInfo = STAILQ_FIRST(&gummeiInfo->served_group_ids);
|
||||
STAILQ_REMOVE_HEAD(&gummeiInfo->served_group_ids, next);
|
||||
free(groupInfo);
|
||||
}
|
||||
while (!STAILQ_EMPTY(&gummeiInfo->mme_codes)) {
|
||||
mmeCode = STAILQ_FIRST(&gummeiInfo->mme_codes);
|
||||
STAILQ_REMOVE_HEAD(&gummeiInfo->mme_codes, next);
|
||||
free(mmeCode);
|
||||
}
|
||||
free(gummeiInfo);
|
||||
}
|
||||
free(mme);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,10 @@ struct s1ap_eNB_mme_data_s *s1ap_eNB_get_MME(
|
||||
s1ap_eNB_instance_t *instance_p,
|
||||
int32_t assoc_id, uint16_t cnx_id);
|
||||
|
||||
struct s1ap_eNB_mme_data_s *s1ap_eNB_get_MME_from_instance(s1ap_eNB_instance_t *instance_p);
|
||||
|
||||
void s1ap_eNB_remove_mme_desc(s1ap_eNB_instance_t * instance);
|
||||
|
||||
void s1ap_eNB_insert_new_instance(s1ap_eNB_instance_t *new_instance_p);
|
||||
|
||||
s1ap_eNB_instance_t *s1ap_eNB_get_instance(uint8_t mod_id);
|
||||
|
||||
Reference in New Issue
Block a user