Refactor SCTP association response handler
* this function is used by both CU-CP and CU-UP * it behaves differently depending on the type of E1 instance: CU-CP: inform RRC of E1 connection loss with CU-UP CU-UP: trigger a new SCTP association request by sending an ITTI to the CU-UP task * after receiving the E1AP register request, the CU-UP will send a new association request to SCTP until new E1 connection is achieved by sending a TIMER_HAS_EXPIRED message to the CU-UP task. The function e1apHandleTimer() is basically triggering a new E1 association request until new E1 connection is achieved * print SCTP association state in e1ap.c whenever needed Related to #878
This commit is contained in:
@@ -36,11 +36,22 @@
|
||||
#define SCTP_INIT_MSG_MULTI_CNF(mSGpTR) (mSGpTR)->ittiMsg.sctp_init_msg_multi_cnf
|
||||
#define SCTP_CLOSE_ASSOCIATION(mSGpTR) (mSGpTR)->ittiMsg.sctp_close_association
|
||||
|
||||
enum sctp_state_e {
|
||||
SCTP_STATE_CLOSED,
|
||||
SCTP_STATE_SHUTDOWN,
|
||||
SCTP_STATE_ESTABLISHED,
|
||||
SCTP_STATE_UNREACHABLE
|
||||
#define SCTP_STATES \
|
||||
ITEM(SCTP_STATE_CLOSED) \
|
||||
ITEM(SCTP_STATE_SHUTDOWN) \
|
||||
ITEM(SCTP_STATE_ESTABLISHED) \
|
||||
ITEM(SCTP_STATE_UNREACHABLE)
|
||||
|
||||
typedef enum {
|
||||
#define ITEM(state) state,
|
||||
SCTP_STATES
|
||||
#undef ITEM
|
||||
} sctp_state_e;
|
||||
|
||||
static const char *sctp_state_s[] __attribute__((unused)) = {
|
||||
#define ITEM(state) #state,
|
||||
SCTP_STATES
|
||||
#undef ITEM
|
||||
};
|
||||
|
||||
typedef struct sctp_new_association_req_s {
|
||||
@@ -112,7 +123,7 @@ typedef struct sctp_new_association_resp_s {
|
||||
uint16_t in_streams;
|
||||
|
||||
/* State of the association at SCTP level */
|
||||
enum sctp_state_e sctp_state;
|
||||
sctp_state_e sctp_state;
|
||||
} sctp_new_association_resp_t;
|
||||
|
||||
typedef struct sctp_data_ind_s {
|
||||
|
||||
+36
-18
@@ -1281,6 +1281,13 @@ static void e1apCUUP_send_SETUP_REQUEST(sctp_assoc_t assoc_id, e1ap_setup_req_t
|
||||
e1ap_encode_send(UPtype, assoc_id, &pdu, 0, __func__);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SCTP association response handler (CU-CP to/from CU-UP)
|
||||
* it behaves differently depending on the type of E1 instance,
|
||||
* CUCP: informs RRC of E1 connection loss with CU-UP
|
||||
* CUUP: triggers a new SCTP association request by sending an ITTI to the CU-UP task
|
||||
* @param type indicates whether the handler is for the CU-CP or CU-UP
|
||||
*/
|
||||
static void e1_task_handle_sctp_association_resp(E1_t type,
|
||||
instance_t instance,
|
||||
sctp_new_association_resp_t *sctp_new_association_resp)
|
||||
@@ -1288,24 +1295,26 @@ static void e1_task_handle_sctp_association_resp(E1_t type,
|
||||
DevAssert(sctp_new_association_resp != NULL);
|
||||
getCxtE1(instance)->sockState = sctp_new_association_resp->sctp_state;
|
||||
|
||||
if (sctp_new_association_resp->sctp_state == SCTP_STATE_SHUTDOWN) {
|
||||
LOG_I(E1AP, "Received SCTP shutdown for assoc_id %d, removing CUCP endpoint\n", sctp_new_association_resp->assoc_id);
|
||||
/* inform RRC that the CU-UP is gone */
|
||||
MessageDef *message_p = itti_alloc_new_message(TASK_CUCP_E1, 0, E1AP_LOST_CONNECTION);
|
||||
message_p->ittiMsgHeader.originInstance = sctp_new_association_resp->assoc_id;
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, instance, message_p);
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle SCTP establishment failure
|
||||
if (sctp_new_association_resp->sctp_state != SCTP_STATE_ESTABLISHED) {
|
||||
LOG_W(E1AP,
|
||||
"Received unsuccessful result for SCTP association (%u), instance "
|
||||
"%ld, cnx_id %u\n",
|
||||
sctp_new_association_resp->sctp_state,
|
||||
instance,
|
||||
sctp_new_association_resp->ulp_cnx_id);
|
||||
long timer_id; // if we want to cancel timer
|
||||
timer_setup(1, 0, TASK_CUUP_E1, 0, TIMER_ONE_SHOT, NULL, &timer_id);
|
||||
if (type == CPtype) {
|
||||
// Inform RRC that the CU-UP is gone
|
||||
LOG_W(E1AP,
|
||||
"Lost connection (%s) with CU-UP (assoc_id %d)\n",
|
||||
sctp_state_s[sctp_new_association_resp->sctp_state],
|
||||
sctp_new_association_resp->assoc_id);
|
||||
MessageDef *message_p = itti_alloc_new_message(TASK_CUCP_E1, 0, E1AP_LOST_CONNECTION);
|
||||
message_p->ittiMsgHeader.originInstance = sctp_new_association_resp->assoc_id;
|
||||
itti_send_msg_to_task(TASK_RRC_GNB, instance, message_p);
|
||||
} else if (type == UPtype) {
|
||||
// Trigger new E1 association when no CU-CP is connected
|
||||
LOG_W(E1AP,
|
||||
"Lost connection (%s) with CU-CP (assoc_id %d): trigger new E1 association\n",
|
||||
sctp_state_s[sctp_new_association_resp->sctp_state],
|
||||
sctp_new_association_resp->assoc_id);
|
||||
long timer_id;
|
||||
timer_setup(1, 0, TASK_CUUP_E1, 0, TIMER_ONE_SHOT, NULL, &timer_id);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1373,7 +1382,11 @@ void e1_task_handle_sctp_association_ind(E1_t type, instance_t instance, sctp_ne
|
||||
inst->cuup.assoc_id = sctp_new_ind->assoc_id;
|
||||
}
|
||||
|
||||
void e1apHandleTimer(instance_t myInstance)
|
||||
/**
|
||||
* @brief Handle the timer triggered by a connection loss with CU-CP
|
||||
* it uses a stored network configuration and send a new SCTP association request
|
||||
*/
|
||||
static void e1apHandleTimer(instance_t myInstance)
|
||||
{
|
||||
LOG_W(E1AP, "Try to reconnect to CP\n");
|
||||
if (getCxtE1(myInstance)->sockState != SCTP_STATE_ESTABLISHED)
|
||||
@@ -1483,6 +1496,8 @@ void *E1AP_CUUP_task(void *arg)
|
||||
LOG_D(E1AP, "CUUP received %s for instance %ld\n", messages_info[msgType].name, myInstance);
|
||||
switch (msgType) {
|
||||
case E1AP_REGISTER_REQ: {
|
||||
/* E1AP Register Request triggered at startup
|
||||
create a new E1 instance and send the first association request */
|
||||
e1ap_register_req_t *reg_req = &E1AP_REGISTER_REQ(msg);
|
||||
createE1inst(UPtype, myInstance, reg_req->gnb_id, ®_req->net_config, ®_req->setup_req);
|
||||
e1_task_send_sctp_association_req(TASK_CUUP_E1, myInstance, ®_req->net_config);
|
||||
@@ -1490,6 +1505,8 @@ void *E1AP_CUUP_task(void *arg)
|
||||
|
||||
case SCTP_NEW_ASSOCIATION_RESP:
|
||||
e1_task_handle_sctp_association_resp(UPtype, myInstance, &msg->ittiMsg.sctp_new_association_resp);
|
||||
if (getCxtE1(myInstance)->sockState == SCTP_STATE_ESTABLISHED)
|
||||
LOG_A(E1AP, "E1 connection established (%s)\n", sctp_state_s[getCxtE1(myInstance)->sockState]);
|
||||
break;
|
||||
|
||||
case SCTP_DATA_IND:
|
||||
@@ -1497,6 +1514,7 @@ void *E1AP_CUUP_task(void *arg)
|
||||
break;
|
||||
|
||||
case TIMER_HAS_EXPIRED:
|
||||
// Timer triggered by a connection loss with CU-CP
|
||||
e1apHandleTimer(myInstance);
|
||||
break;
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ typedef struct e1ap_upcp_inst_s {
|
||||
instance_t instance;
|
||||
uint32_t gnb_id; // associated gNB's ID, unused in E1 but necessary for e.g. E2 agent
|
||||
E1_t type;
|
||||
enum sctp_state_e sockState;
|
||||
sctp_state_e sockState;
|
||||
struct {
|
||||
sctp_assoc_t assoc_id;
|
||||
e1ap_setup_req_t setupReq;
|
||||
|
||||
@@ -65,7 +65,7 @@ static void cu_task_handle_sctp_association_ind(instance_t instance,
|
||||
static void cu_task_handle_sctp_association_resp(instance_t instance, sctp_new_association_resp_t *sctp_new_association_resp) {
|
||||
DevAssert(sctp_new_association_resp != NULL);
|
||||
|
||||
enum sctp_state_e state = sctp_new_association_resp->sctp_state;
|
||||
sctp_state_e state = sctp_new_association_resp->sctp_state;
|
||||
if (state != SCTP_STATE_ESTABLISHED) {
|
||||
f1ap_cudu_inst_t *f1ap_cu_data = getCxt(instance);
|
||||
AssertFatal(f1ap_cu_data != NULL, "illegal state: SCTP shutdown for non-existing F1AP endpoint\n");
|
||||
|
||||
@@ -68,7 +68,7 @@ int sctp_itti_send_association_resp(task_id_t task_id,
|
||||
instance_t instance,
|
||||
sctp_assoc_t assoc_id,
|
||||
uint16_t cnx_id,
|
||||
enum sctp_state_e state,
|
||||
sctp_state_e state,
|
||||
uint16_t out_streams,
|
||||
uint16_t in_streams)
|
||||
{
|
||||
|
||||
@@ -35,7 +35,7 @@ int sctp_itti_send_association_resp(task_id_t task_id,
|
||||
instance_t instance,
|
||||
sctp_assoc_t assoc_id,
|
||||
uint16_t cnx_id,
|
||||
enum sctp_state_e state,
|
||||
sctp_state_e state,
|
||||
uint16_t out_streams,
|
||||
uint16_t in_streams);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user