diff --git a/openair-cn/S1AP/s1ap_eNB_handlers.c b/openair-cn/S1AP/s1ap_eNB_handlers.c index b44ce61f419588f445c54cd03a4fc42c624e98ee..037399388ff75b84a74fa215afe86cd58dfe503b 100644 --- a/openair-cn/S1AP/s1ap_eNB_handlers.c +++ b/openair-cn/S1AP/s1ap_eNB_handlers.c @@ -355,7 +355,7 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id, if ((ue_desc_p = s1ap_eNB_get_ue_context(mme_desc_p->s1ap_eNB_instance, initialContextSetupRequest_p->eNB_UE_S1AP_ID)) == NULL) { S1AP_ERROR("[SCTP %d] Received initial context setup request for non " - "existing UE context %06x\n", assoc_id, + "existing UE context 0x%06x\n", assoc_id, initialContextSetupRequest_p->eNB_UE_S1AP_ID); return -1; } diff --git a/openair-cn/S1AP/s1ap_eNB_nas_procedures.c b/openair-cn/S1AP/s1ap_eNB_nas_procedures.c index bc128b1546da4577024d484168ebce38273dbfb7..54d466320c5c56e71910b359c9d1e020a2487c5f 100644 --- a/openair-cn/S1AP/s1ap_eNB_nas_procedures.c +++ b/openair-cn/S1AP/s1ap_eNB_nas_procedures.c @@ -207,7 +207,7 @@ int s1ap_eNB_handle_nas_downlink(uint32_t assoc_id, } if ((mme_desc_p = s1ap_eNB_get_MME(NULL, assoc_id, 0)) == NULL) { - S1AP_ERROR("[SCTP %d] Received initial context setup request for non " + S1AP_ERROR("[SCTP %d] Received NAS downlink message for non " "existing MME context\n", assoc_id); return -1; } @@ -217,8 +217,9 @@ int s1ap_eNB_handle_nas_downlink(uint32_t assoc_id, if ((ue_desc_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance, downlink_NAS_transport_p->eNB_UE_S1AP_ID)) == NULL) { - S1AP_ERROR("[SCTP %d] Received initial context setup request for non " - "existing UE context\n", assoc_id); + S1AP_ERROR("[SCTP %d] Received NAS downlink message for non " + "existing UE context: %06x\n", assoc_id, + downlink_NAS_transport_p->eNB_UE_S1AP_ID); return -1; } @@ -230,7 +231,7 @@ int s1ap_eNB_handle_nas_downlink(uint32_t assoc_id, } else { /* We already have a mme ue s1ap id check the received is the same */ if (ue_desc_p->mme_ue_s1ap_id != downlink_NAS_transport_p->mme_ue_s1ap_id) { - S1AP_ERROR("[SCTP %d] Mismatch is MME UE S1AP ID (0x%08x != 0x%08x)\n", + S1AP_ERROR("[SCTP %d] Mismatch in MME UE S1AP ID (0x%08x != 0x%08x)\n", downlink_NAS_transport_p->mme_ue_s1ap_id, ue_desc_p->mme_ue_s1ap_id, assoc_id); @@ -265,7 +266,7 @@ int s1ap_eNB_nas_uplink(instance_t instance, s1ap_uplink_nas_t *s1ap_uplink_nas_ if ((ue_context_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance_p, s1ap_uplink_nas_p->eNB_ue_s1ap_id)) == NULL) { /* The context for this eNB ue s1ap id doesn't exist in the map of eNB UEs */ - S1AP_WARN("Failed to find ue context associated with eNB ue s1ap id: %u\n", + S1AP_WARN("Failed to find ue context associated with eNB ue s1ap id: %06x\n", s1ap_uplink_nas_p->eNB_ue_s1ap_id); return -1; } @@ -342,7 +343,7 @@ int s1ap_eNB_initial_ctxt_resp( initial_ctxt_resp_p->eNB_ue_s1ap_id)) == NULL) { /* The context for this eNB ue s1ap id doesn't exist in the map of eNB UEs */ - S1AP_WARN("Failed to find ue context associated with eNB ue s1ap id: %u\n", + S1AP_WARN("Failed to find ue context associated with eNB ue s1ap id: 0x%06x\n", initial_ctxt_resp_p->eNB_ue_s1ap_id); return -1; } @@ -354,7 +355,7 @@ int s1ap_eNB_initial_ctxt_resp( ue_context_p->ue_state == S1AP_UE_WAITING_CSR)) { S1AP_WARN("You are attempting to send NAS data over non-connected " - "eNB ue s1ap id: %u, current state: %d\n", + "eNB ue s1ap id: %06x, current state: %d\n", initial_ctxt_resp_p->eNB_ue_s1ap_id, ue_context_p->ue_state); return -1; } diff --git a/openair-cn/SCTP/sctp_eNB_itti_messaging.c b/openair-cn/SCTP/sctp_eNB_itti_messaging.c index e8371987c2a829ad8120557f5e56a506157a18ff..ffd5b2df3f15bcb210130f809e38310cda401a1d 100644 --- a/openair-cn/SCTP/sctp_eNB_itti_messaging.c +++ b/openair-cn/SCTP/sctp_eNB_itti_messaging.c @@ -24,3 +24,24 @@ int sctp_itti_send_new_message_ind(task_id_t task_id, uint32_t assoc_id, uint8_t return itti_send_msg_to_task(task_id, INSTANCE_DEFAULT, message_p); } + +int sctp_itti_send_association_resp(task_id_t task_id, instance_t instance, + int32_t assoc_id, + uint16_t cnx_id, enum sctp_state_e state, + uint16_t out_streams, uint16_t in_streams) +{ + MessageDef *message_p; + sctp_new_association_resp_t *sctp_new_association_resp_p; + + message_p = itti_alloc_new_message(TASK_SCTP, SCTP_NEW_ASSOCIATION_RESP); + + sctp_new_association_resp_p = &message_p->msg.sctp_new_association_resp; + + sctp_new_association_resp_p->in_streams = in_streams; + sctp_new_association_resp_p->out_streams = out_streams; + sctp_new_association_resp_p->sctp_state = state; + sctp_new_association_resp_p->assoc_id = assoc_id; + sctp_new_association_resp_p->ulp_cnx_id = cnx_id; + + return itti_send_msg_to_task(task_id, instance, message_p); +} diff --git a/openair-cn/SCTP/sctp_eNB_itti_messaging.h b/openair-cn/SCTP/sctp_eNB_itti_messaging.h index b077d8ac8fd2d3d7293020bde1aa21f06650a8ed..eba2d1993395a039a24d79916276d30c5d373b0a 100644 --- a/openair-cn/SCTP/sctp_eNB_itti_messaging.h +++ b/openair-cn/SCTP/sctp_eNB_itti_messaging.h @@ -4,4 +4,9 @@ int sctp_itti_send_new_message_ind(task_id_t task_id, uint32_t assoc_id, uint8_t *buffer, uint32_t buffer_length, uint16_t stream); +int sctp_itti_send_association_resp(task_id_t task_id, instance_t instance, + int32_t assoc_id, + uint16_t cnx_id, enum sctp_state_e state, + uint16_t out_streams, uint16_t in_streams); + #endif /* SCTP_ITTI_MESSAGING_H_ */ diff --git a/openair-cn/SCTP/sctp_eNB_task.c b/openair-cn/SCTP/sctp_eNB_task.c index 401919041818bf2f8a1d1a77977c2b037bfc3b7e..c59a185e6242c767761747ade45414fd46b0b5ab 100644 --- a/openair-cn/SCTP/sctp_eNB_task.c +++ b/openair-cn/SCTP/sctp_eNB_task.c @@ -112,6 +112,8 @@ void sctp_handle_new_association_req( struct sctp_initmsg init; struct sctp_event_subscribe events; + struct sctp_cnx_list_elm_s *sctp_cnx = NULL; + /* Prepare a new SCTP association as requested by upper layer and try to connect * to remote host. */ @@ -138,6 +140,7 @@ void sctp_handle_new_association_req( &init, (socklen_t)sizeof(struct sctp_initmsg)) < 0) { SCTP_ERROR("Setsockopt IPPROTO_SCTP_INITMSG failed: %s\n", strerror(errno)); + close(sd); return; } @@ -147,6 +150,15 @@ void sctp_handle_new_association_req( sizeof(struct sctp_event_subscribe)) < 0) { SCTP_ERROR("Setsockopt IPPROTO_SCTP_EVENTS failed: %s\n", strerror(errno)); + close(sd); + return; + } + + /* Mark the socket as non-blocking */ + if (fcntl(sd, F_SETFL, O_NONBLOCK) < 0) { + SCTP_ERROR("fcntl F_SETFL O_NONBLOCK failed: %s\n", + strerror(errno)); + close(sd); return; } @@ -169,6 +181,7 @@ void sctp_handle_new_association_req( SCTP_ERROR("Failed to convert ipv6 address %*s to network type\n", strlen(sctp_new_association_req_p->remote_address.ipv6_address), sctp_new_association_req_p->remote_address.ipv6_address); + close(sd); return; } @@ -187,6 +200,7 @@ void sctp_handle_new_association_req( SCTP_ERROR("Failed to convert ipv4 address %*s to network type\n", strlen(sctp_new_association_req_p->remote_address.ipv4_address), sctp_new_association_req_p->remote_address.ipv4_address); + close(sd); return; } @@ -202,58 +216,34 @@ void sctp_handle_new_association_req( SCTP_DEBUG("Connecting...\n"); /* Connect to remote host and port */ - if (sctp_connectx(sd, (struct sockaddr *)addr, used_address, &assoc_id) < 0) { - SCTP_ERROR("Connect failed: %s\n", strerror(errno)); - return; + if (sctp_connectx(sd, (struct sockaddr *)addr, used_address, &assoc_id) < 0) + { + /* sctp_connectx on non-blocking socket return EINPROGRESS */ + if (errno != EINPROGRESS) { + SCTP_ERROR("Connect failed: %s\n", strerror(errno)); + sctp_itti_send_association_resp( + requestor, instance, -1, sctp_new_association_req_p->ulp_cnx_id, + SCTP_STATE_UNREACHABLE, 0, 0); + close(sd); + return; + } } - - SCTP_DEBUG("Connected... assoc_id %u\n", assoc_id); } - if (sctp_get_peeraddresses(sd, NULL, NULL) != 0) { - /* TODO Failure -> notify upper layer */ - - } else { - MessageDef *new_message_p; - sctp_new_association_resp_t *sctp_new_association_resp; - struct sctp_cnx_list_elm_s *sctp_cnx = NULL; - - sctp_cnx = calloc(1, sizeof(*sctp_cnx)); - - sctp_cnx->sd = sd; - sctp_cnx->task_id = requestor; - sctp_cnx->cnx_id = sctp_new_association_req_p->ulp_cnx_id; - sctp_cnx->ppid = sctp_new_association_req_p->ppid; - sctp_cnx->instance = instance; - - /* Get socket info */ - sctp_get_sockinfo(sd, - &sctp_cnx->in_streams, - &sctp_cnx->out_streams, - &sctp_cnx->assoc_id); - - /* Insert new element at end of list */ - STAILQ_INSERT_TAIL(&sctp_cnx_list, sctp_cnx, entries); - sctp_nb_cnx++; - - SCTP_DEBUG("Inserted new descriptor for sd %d in list, nb elements %u, assoc_id %d\n", - sd, sctp_nb_cnx, assoc_id); + sctp_cnx = calloc(1, sizeof(*sctp_cnx)); - new_message_p = itti_alloc_new_message(TASK_SCTP, SCTP_NEW_ASSOCIATION_RESP); + sctp_cnx->sd = sd; + sctp_cnx->task_id = requestor; + sctp_cnx->cnx_id = sctp_new_association_req_p->ulp_cnx_id; + sctp_cnx->ppid = sctp_new_association_req_p->ppid; + sctp_cnx->instance = instance; - sctp_new_association_resp = &new_message_p->msg.sctp_new_association_resp; + /* Insert new element at end of list */ + STAILQ_INSERT_TAIL(&sctp_cnx_list, sctp_cnx, entries); + sctp_nb_cnx++; - sctp_new_association_resp->in_streams = sctp_cnx->in_streams; - sctp_new_association_resp->out_streams = sctp_cnx->out_streams; - sctp_new_association_resp->sctp_state = SCTP_STATE_ESTABLISHED; - sctp_new_association_resp->ulp_cnx_id = sctp_new_association_req_p->ulp_cnx_id; - sctp_new_association_resp->assoc_id = sctp_cnx->assoc_id; - - SCTP_DEBUG("Sending SCTP new association resp message to %s\n", - itti_get_task_name(requestor)); - - itti_send_msg_to_task(requestor, sctp_cnx->instance, new_message_p); - } + SCTP_DEBUG("Inserted new descriptor for sd %d in list, nb elements %u, assoc_id %d\n", + sd, sctp_nb_cnx, assoc_id); } void sctp_send_data(instance_t instance, task_id_t task_id, sctp_data_req_t *sctp_data_req_p) @@ -321,6 +311,9 @@ inline void sctp_eNB_read_from_socket(struct sctp_cnx_list_elm_s *sctp_cnx) union sctp_notification *snp; snp = (union sctp_notification *)buffer; + SCTP_DEBUG("Received notification for sd %d, type %u\n", + sctp_cnx->sd, snp->sn_header.sn_type); + /* Client deconnection */ if (SCTP_SHUTDOWN_EVENT == snp->sn_header.sn_type) { DevMessage("Other peer has requested a com down -> not handled\n"); @@ -337,34 +330,22 @@ inline void sctp_eNB_read_from_socket(struct sctp_cnx_list_elm_s *sctp_cnx) /* New physical association requested by a peer */ switch (sctp_assoc_changed->sac_state) { case SCTP_COMM_UP: { -// struct sctp_association_s *new_association; -// -// sctp_get_sockinfo(sd, NULL, NULL, NULL); -// -// SCTP_DEBUG("New connection\n"); -// if ((new_association = sctp_add_new_peer()) == NULL) { -// // TODO: handle this case -// DevMessage("Unexpected error...\n"); -// return SCTP_RC_ERROR; -// } else { -// new_association->sd = sd; -// new_association->ppid = ppid; -// new_association->instreams = sctp_assoc_changed->sac_inbound_streams; -// new_association->outstreams = sctp_assoc_changed->sac_outbound_streams; -// new_association->assoc_id = sctp_assoc_changed->sac_assoc_id; -// -// sctp_get_localaddresses(sd, NULL, NULL); -// sctp_get_peeraddresses(sd, &new_association->peer_addresses, -// &new_association->nb_peer_addresses); -// -// if (sctp_itti_send_new_association( -// new_association->assoc_id, new_association->instreams, -// new_association->outstreams) < 0) -// { -// SCTP_ERROR("Failed to send message to S1AP\n"); -// return SCTP_RC_ERROR; -// } -// } + if (sctp_get_peeraddresses(sctp_cnx->sd, NULL, NULL) != 0) + { + /* TODO Failure -> notify upper layer */ + } else { + sctp_get_sockinfo(sctp_cnx->sd, &sctp_cnx->in_streams, + &sctp_cnx->out_streams, &sctp_cnx->assoc_id); + } + + SCTP_DEBUG("Comm up notified for sd %d, assigned assoc_id %d\n", + sctp_cnx->sd, sctp_cnx->assoc_id); + + sctp_itti_send_association_resp( + sctp_cnx->task_id, sctp_cnx->instance, sctp_cnx->assoc_id, + sctp_cnx->cnx_id, SCTP_STATE_ESTABLISHED, + sctp_cnx->out_streams, sctp_cnx->in_streams); + } break; default: break;