Commit ebba5542 authored by Cedric Roux's avatar Cedric Roux

- Mark SCTP sockets as non-blocking to avoid locks in SCTP layer, particularly at connection

- Fixed some log points formats

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@4398 818b1a75-f10b-46b9-bf7c-635c3b92a50f
parent 8263063c
...@@ -355,7 +355,7 @@ int s1ap_eNB_handle_initial_context_request(uint32_t assoc_id, ...@@ -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, if ((ue_desc_p = s1ap_eNB_get_ue_context(mme_desc_p->s1ap_eNB_instance,
initialContextSetupRequest_p->eNB_UE_S1AP_ID)) == NULL) { initialContextSetupRequest_p->eNB_UE_S1AP_ID)) == NULL) {
S1AP_ERROR("[SCTP %d] Received initial context setup request for non " 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); initialContextSetupRequest_p->eNB_UE_S1AP_ID);
return -1; return -1;
} }
......
...@@ -207,7 +207,7 @@ int s1ap_eNB_handle_nas_downlink(uint32_t assoc_id, ...@@ -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) { 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); "existing MME context\n", assoc_id);
return -1; return -1;
} }
...@@ -217,8 +217,9 @@ int s1ap_eNB_handle_nas_downlink(uint32_t assoc_id, ...@@ -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, if ((ue_desc_p = s1ap_eNB_get_ue_context(s1ap_eNB_instance,
downlink_NAS_transport_p->eNB_UE_S1AP_ID)) == NULL) downlink_NAS_transport_p->eNB_UE_S1AP_ID)) == NULL)
{ {
S1AP_ERROR("[SCTP %d] Received initial context setup request for non " S1AP_ERROR("[SCTP %d] Received NAS downlink message for non "
"existing UE context\n", assoc_id); "existing UE context: %06x\n", assoc_id,
downlink_NAS_transport_p->eNB_UE_S1AP_ID);
return -1; return -1;
} }
...@@ -230,7 +231,7 @@ int s1ap_eNB_handle_nas_downlink(uint32_t assoc_id, ...@@ -230,7 +231,7 @@ int s1ap_eNB_handle_nas_downlink(uint32_t assoc_id,
} else { } else {
/* We already have a mme ue s1ap id check the received is the same */ /* 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) { 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, downlink_NAS_transport_p->mme_ue_s1ap_id,
ue_desc_p->mme_ue_s1ap_id, ue_desc_p->mme_ue_s1ap_id,
assoc_id); assoc_id);
...@@ -265,7 +266,7 @@ int s1ap_eNB_nas_uplink(instance_t instance, s1ap_uplink_nas_t *s1ap_uplink_nas_ ...@@ -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) 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 */ /* 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); s1ap_uplink_nas_p->eNB_ue_s1ap_id);
return -1; return -1;
} }
...@@ -342,7 +343,7 @@ int s1ap_eNB_initial_ctxt_resp( ...@@ -342,7 +343,7 @@ int s1ap_eNB_initial_ctxt_resp(
initial_ctxt_resp_p->eNB_ue_s1ap_id)) == NULL) 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 */ /* 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); initial_ctxt_resp_p->eNB_ue_s1ap_id);
return -1; return -1;
} }
...@@ -354,7 +355,7 @@ int s1ap_eNB_initial_ctxt_resp( ...@@ -354,7 +355,7 @@ int s1ap_eNB_initial_ctxt_resp(
ue_context_p->ue_state == S1AP_UE_WAITING_CSR)) ue_context_p->ue_state == S1AP_UE_WAITING_CSR))
{ {
S1AP_WARN("You are attempting to send NAS data over non-connected " 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); initial_ctxt_resp_p->eNB_ue_s1ap_id, ue_context_p->ue_state);
return -1; return -1;
} }
......
...@@ -24,3 +24,24 @@ int sctp_itti_send_new_message_ind(task_id_t task_id, uint32_t assoc_id, uint8_t ...@@ -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); 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);
}
...@@ -4,4 +4,9 @@ ...@@ -4,4 +4,9 @@
int sctp_itti_send_new_message_ind(task_id_t task_id, uint32_t assoc_id, uint8_t *buffer, 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); 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_ */ #endif /* SCTP_ITTI_MESSAGING_H_ */
...@@ -112,6 +112,8 @@ void sctp_handle_new_association_req( ...@@ -112,6 +112,8 @@ void sctp_handle_new_association_req(
struct sctp_initmsg init; struct sctp_initmsg init;
struct sctp_event_subscribe events; 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 /* Prepare a new SCTP association as requested by upper layer and try to connect
* to remote host. * to remote host.
*/ */
...@@ -138,6 +140,7 @@ void sctp_handle_new_association_req( ...@@ -138,6 +140,7 @@ void sctp_handle_new_association_req(
&init, (socklen_t)sizeof(struct sctp_initmsg)) < 0) { &init, (socklen_t)sizeof(struct sctp_initmsg)) < 0) {
SCTP_ERROR("Setsockopt IPPROTO_SCTP_INITMSG failed: %s\n", SCTP_ERROR("Setsockopt IPPROTO_SCTP_INITMSG failed: %s\n",
strerror(errno)); strerror(errno));
close(sd);
return; return;
} }
...@@ -147,6 +150,15 @@ void sctp_handle_new_association_req( ...@@ -147,6 +150,15 @@ void sctp_handle_new_association_req(
sizeof(struct sctp_event_subscribe)) < 0) { sizeof(struct sctp_event_subscribe)) < 0) {
SCTP_ERROR("Setsockopt IPPROTO_SCTP_EVENTS failed: %s\n", SCTP_ERROR("Setsockopt IPPROTO_SCTP_EVENTS failed: %s\n",
strerror(errno)); 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; return;
} }
...@@ -169,6 +181,7 @@ void sctp_handle_new_association_req( ...@@ -169,6 +181,7 @@ void sctp_handle_new_association_req(
SCTP_ERROR("Failed to convert ipv6 address %*s to network type\n", SCTP_ERROR("Failed to convert ipv6 address %*s to network type\n",
strlen(sctp_new_association_req_p->remote_address.ipv6_address), strlen(sctp_new_association_req_p->remote_address.ipv6_address),
sctp_new_association_req_p->remote_address.ipv6_address); sctp_new_association_req_p->remote_address.ipv6_address);
close(sd);
return; return;
} }
...@@ -187,6 +200,7 @@ void sctp_handle_new_association_req( ...@@ -187,6 +200,7 @@ void sctp_handle_new_association_req(
SCTP_ERROR("Failed to convert ipv4 address %*s to network type\n", SCTP_ERROR("Failed to convert ipv4 address %*s to network type\n",
strlen(sctp_new_association_req_p->remote_address.ipv4_address), strlen(sctp_new_association_req_p->remote_address.ipv4_address),
sctp_new_association_req_p->remote_address.ipv4_address); sctp_new_association_req_p->remote_address.ipv4_address);
close(sd);
return; return;
} }
...@@ -202,58 +216,34 @@ void sctp_handle_new_association_req( ...@@ -202,58 +216,34 @@ void sctp_handle_new_association_req(
SCTP_DEBUG("Connecting...\n"); SCTP_DEBUG("Connecting...\n");
/* Connect to remote host and port */ /* Connect to remote host and port */
if (sctp_connectx(sd, (struct sockaddr *)addr, used_address, &assoc_id) < 0) { if (sctp_connectx(sd, (struct sockaddr *)addr, used_address, &assoc_id) < 0)
SCTP_ERROR("Connect failed: %s\n", strerror(errno)); {
return; /* 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) { sctp_cnx = calloc(1, sizeof(*sctp_cnx));
/* 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);
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_DEBUG("Inserted new descriptor for sd %d in list, nb elements %u, assoc_id %d\n",
sctp_new_association_resp->out_streams = sctp_cnx->out_streams; sd, sctp_nb_cnx, assoc_id);
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);
}
} }
void sctp_send_data(instance_t instance, task_id_t task_id, sctp_data_req_t *sctp_data_req_p) 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) ...@@ -321,6 +311,9 @@ inline void sctp_eNB_read_from_socket(struct sctp_cnx_list_elm_s *sctp_cnx)
union sctp_notification *snp; union sctp_notification *snp;
snp = (union sctp_notification *)buffer; 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 */ /* Client deconnection */
if (SCTP_SHUTDOWN_EVENT == snp->sn_header.sn_type) { if (SCTP_SHUTDOWN_EVENT == snp->sn_header.sn_type) {
DevMessage("Other peer has requested a com down -> not handled\n"); 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) ...@@ -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 */ /* New physical association requested by a peer */
switch (sctp_assoc_changed->sac_state) { switch (sctp_assoc_changed->sac_state) {
case SCTP_COMM_UP: { case SCTP_COMM_UP: {
// struct sctp_association_s *new_association; if (sctp_get_peeraddresses(sctp_cnx->sd, NULL, NULL) != 0)
// {
// sctp_get_sockinfo(sd, NULL, NULL, NULL); /* TODO Failure -> notify upper layer */
// } else {
// SCTP_DEBUG("New connection\n"); sctp_get_sockinfo(sctp_cnx->sd, &sctp_cnx->in_streams,
// if ((new_association = sctp_add_new_peer()) == NULL) { &sctp_cnx->out_streams, &sctp_cnx->assoc_id);
// // TODO: handle this case }
// DevMessage("Unexpected error...\n");
// return SCTP_RC_ERROR; SCTP_DEBUG("Comm up notified for sd %d, assigned assoc_id %d\n",
// } else { sctp_cnx->sd, sctp_cnx->assoc_id);
// new_association->sd = sd;
// new_association->ppid = ppid; sctp_itti_send_association_resp(
// new_association->instreams = sctp_assoc_changed->sac_inbound_streams; sctp_cnx->task_id, sctp_cnx->instance, sctp_cnx->assoc_id,
// new_association->outstreams = sctp_assoc_changed->sac_outbound_streams; sctp_cnx->cnx_id, SCTP_STATE_ESTABLISHED,
// new_association->assoc_id = sctp_assoc_changed->sac_assoc_id; sctp_cnx->out_streams, sctp_cnx->in_streams);
//
// 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;
// }
// }
} break; } break;
default: default:
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment