add path_switch req/ack/failure encoder/decoder

This commit is contained in:
Sukchan Lee 2017-09-11 21:14:55 +09:00
parent fc9857b3f0
commit b7c544c8db
10 changed files with 380 additions and 72 deletions

View File

@ -599,6 +599,81 @@ status_t s1ap_build_paging(pkbuf_t **s1apbuf, mme_ue_t *mme_ue)
return CORE_OK;
}
status_t s1ap_build_path_switch_ack(pkbuf_t **s1apbuf, mme_ue_t *mme_ue)
{
char buf[INET_ADDRSTRLEN];
int encoded;
s1ap_message_t message;
S1ap_PathSwitchRequestAcknowledgeIEs_t *ies =
&message.s1ap_PathSwitchRequestAcknowledgeIEs;
enb_ue_t *enb_ue = NULL;
d_assert(mme_ue, return CORE_ERROR, "Null param");
enb_ue = mme_ue->enb_ue;
d_assert(enb_ue, return CORE_ERROR, "Null param");
memset(&message, 0, sizeof(s1ap_message_t));
ies->mme_ue_s1ap_id = enb_ue->mme_ue_s1ap_id;
ies->eNB_UE_S1AP_ID = enb_ue->enb_ue_s1ap_id;
ies->securityContext.nextHopChainingCount = 0;
ies->securityContext.nextHopParameter.size = SHA256_DIGEST_SIZE;
ies->securityContext.nextHopParameter.buf =
core_calloc(ies->securityContext.nextHopParameter.size,
sizeof(c_uint8_t));
ies->securityContext.nextHopParameter.bits_unused = 0;
memcpy(ies->securityContext.nextHopParameter.buf,
mme_ue->kenb, ies->securityContext.nextHopParameter.size);
message.procedureCode = S1ap_ProcedureCode_id_PathSwitchRequest;
message.direction = S1AP_PDU_PR_successfulOutcome;
encoded = s1ap_encode_pdu(s1apbuf, &message);
s1ap_free_pdu(&message);
d_assert(s1apbuf && encoded >= 0,return CORE_ERROR,);
d_trace(3, "[S1AP] Path Switch Ack : "
"UE[mME-UE-S1AP-ID(%d)] <-- eNB[%s:%d]\n",
enb_ue->mme_ue_s1ap_id,
INET_NTOP(&enb_ue->enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb_ue->enb->enb_id);
return CORE_OK;
}
status_t s1ap_build_path_switch_failure(pkbuf_t **s1apbuf,
c_uint32_t enb_ue_s1ap_id, c_uint32_t mme_ue_s1ap_id, S1ap_Cause_t *cause)
{
int encoded;
s1ap_message_t message;
S1ap_PathSwitchRequestFailureIEs_t *ies =
&message.s1ap_PathSwitchRequestFailureIEs;
memset(&message, 0, sizeof(s1ap_message_t));
ies->mme_ue_s1ap_id = mme_ue_s1ap_id;
ies->eNB_UE_S1AP_ID = enb_ue_s1ap_id;
s1ap_build_cause(&ies->cause, cause);
message.procedureCode = S1ap_ProcedureCode_id_PathSwitchRequest;
message.direction = S1AP_PDU_PR_unsuccessfulOutcome;
encoded = s1ap_encode_pdu(s1apbuf, &message);
s1ap_free_pdu(&message);
d_assert(s1apbuf && encoded >= 0,return CORE_ERROR,);
d_trace(3, "[S1AP] PathSwitchFailure : "
"UE[eNB-UE-S1AP-ID(%d), mME-UE-S1AP-ID(%d)]",
enb_ue_s1ap_id, mme_ue_s1ap_id);
return CORE_OK;
}
static void s1ap_build_cause(S1ap_Cause_t *dst, S1ap_Cause_t *src)
{
d_assert(src, return, "Null param");

View File

@ -10,19 +10,24 @@ extern "C" {
CORE_DECLARE(status_t) s1ap_build_setup_rsp(pkbuf_t **pkbuf);
CORE_DECLARE(status_t) s1ap_build_setup_failure(
pkbuf_t **pkbuf, S1ap_Cause_t cause);
pkbuf_t **pkbuf, S1ap_Cause_t cause);
CORE_DECLARE(status_t) s1ap_build_downlink_nas_transport(
pkbuf_t **s1apbuf, enb_ue_t *enb_ue, pkbuf_t *emmbuf);
pkbuf_t **s1apbuf, enb_ue_t *enb_ue, pkbuf_t *emmbuf);
CORE_DECLARE(status_t) s1ap_build_initial_context_setup_request(
pkbuf_t **s1apbuf, mme_ue_t *mme_ue, pkbuf_t *emmbuf);
pkbuf_t **s1apbuf, mme_ue_t *mme_ue, pkbuf_t *emmbuf);
CORE_DECLARE(status_t) s1ap_build_e_rab_setup_request(
pkbuf_t **s1apbuf, mme_bearer_t *bearer, pkbuf_t *esmbuf);
pkbuf_t **s1apbuf, mme_bearer_t *bearer, pkbuf_t *esmbuf);
CORE_DECLARE(status_t) s1ap_build_e_rab_release_command(pkbuf_t **s1apbuf,
mme_bearer_t *bearer, pkbuf_t *esmbuf, S1ap_Cause_t *cause);
mme_bearer_t *bearer, pkbuf_t *esmbuf, S1ap_Cause_t *cause);
CORE_DECLARE(status_t) s1ap_build_ue_context_release_commmand(
pkbuf_t **s1apbuf, enb_ue_t *enb_ue, S1ap_Cause_t *cause);
pkbuf_t **s1apbuf, enb_ue_t *enb_ue, S1ap_Cause_t *cause);
CORE_DECLARE(status_t) s1ap_build_paging(pkbuf_t **s1apbuf, mme_ue_t *mme_ue);
CORE_DECLARE(status_t) s1ap_build_path_switch_ack(
pkbuf_t **s1apbuf, mme_ue_t *mme_ue);
CORE_DECLARE(status_t) s1ap_build_path_switch_failure(pkbuf_t **s1apbuf,
c_uint32_t enb_ue_s1ap_id, c_uint32_t mme_ue_s1ap_id, S1ap_Cause_t *cause);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -31,7 +31,6 @@ void s1ap_handle_s1_setup_request(mme_enb_t *enb, s1ap_message_t *message)
s1ap_ENB_ID_to_uint32(&ies->global_ENB_ID.eNB_ID, &enb_id);
/* Parse Supported TA */
for (i = 0; i < ies->supportedTAs.list.count; i++)
{
@ -120,7 +119,7 @@ void s1ap_handle_initial_ue_message(mme_enb_t *enb, s1ap_message_t *message)
enb_ue->enb_ue_s1ap_id = ies->eNB_UE_S1AP_ID;
/* Find MME_UE if s_tmsi included */
if (ies->presenceMask &S1AP_INITIALUEMESSAGE_IES_S_TMSI_PRESENT)
if (ies->presenceMask & S1AP_INITIALUEMESSAGE_IES_S_TMSI_PRESENT)
{
S1ap_S_TMSI_t *s_tmsi = &ies->s_tmsi;
served_gummei_t *served_gummei = &mme_self()->served_gummei[0];
@ -529,3 +528,125 @@ void s1ap_handle_paging(mme_ue_t *mme_ue)
enb = mme_enb_next(enb);
}
}
void s1ap_handle_path_switch_request(
mme_enb_t *enb, s1ap_message_t *message)
{
char buf[INET_ADDRSTRLEN];
int i;
enb_ue_t *enb_ue = NULL;
mme_ue_t *mme_ue = NULL;
S1ap_PathSwitchRequestIEs_t *ies = NULL;
S1ap_EUTRAN_CGI_t *eutran_cgi;
S1ap_PLMNidentity_t *pLMNidentity = NULL;
S1ap_CellIdentity_t *cell_ID = NULL;
S1ap_TAI_t *tai;
S1ap_TAC_t *tAC = NULL;
S1ap_UESecurityCapabilities_t *ueSecurityCapabilities = NULL;
S1ap_EncryptionAlgorithms_t *encryptionAlgorithms = NULL;
S1ap_IntegrityProtectionAlgorithms_t *integrityProtectionAlgorithms = NULL;
c_uint16_t eea = 0, eia = 0;
d_assert(enb, return, "Null param");
ies = &message->s1ap_PathSwitchRequestIEs;
d_assert(ies, return, "Null param");
eutran_cgi = &ies->eutran_cgi;
d_assert(eutran_cgi, return,);
pLMNidentity = &eutran_cgi->pLMNidentity;
d_assert(pLMNidentity && pLMNidentity->size == sizeof(plmn_id_t), return,);
cell_ID = &eutran_cgi->cell_ID;
d_assert(cell_ID, return,);
tai = &ies->tai;
d_assert(tai, return,);
pLMNidentity = &tai->pLMNidentity;
d_assert(pLMNidentity && pLMNidentity->size == sizeof(plmn_id_t), return,);
tAC = &tai->tAC;
d_assert(tAC && tAC->size == sizeof(c_uint16_t), return,);
ueSecurityCapabilities = &ies->ueSecurityCapabilities;
d_assert(ueSecurityCapabilities, return,);
encryptionAlgorithms =
&ueSecurityCapabilities->encryptionAlgorithms;
integrityProtectionAlgorithms =
&ueSecurityCapabilities->integrityProtectionAlgorithms;
enb_ue = enb_ue_find_by_mme_ue_s1ap_id(ies->sourceMME_UE_S1AP_ID);
if (!enb_ue)
{
S1ap_Cause_t cause;
d_error("Cannot find UE from sourceMME-UE-S1AP-ID[%d] and eNB[%s:%d]",
ies->sourceMME_UE_S1AP_ID,
INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb->enb_id);
cause.present = S1ap_Cause_PR_radioNetwork;
cause.choice.radioNetwork =
S1ap_CauseRadioNetwork_unknown_mme_ue_s1ap_id;
s1ap_send_path_switch_failure(enb, ies->eNB_UE_S1AP_ID,
ies->sourceMME_UE_S1AP_ID, &cause);
return;
}
mme_ue = enb_ue->mme_ue;
d_assert(mme_ue, return, "Null param");
enb_ue->enb_ue_s1ap_id = ies->eNB_UE_S1AP_ID;
memcpy(&enb_ue->tai.plmn_id, pLMNidentity->buf,
sizeof(enb_ue->tai.plmn_id));
memcpy(&enb_ue->tai.tac, tAC->buf, sizeof(enb_ue->tai.tac));
enb_ue->tai.tac = ntohs(enb_ue->tai.tac);
memcpy(&enb_ue->e_cgi.plmn_id, pLMNidentity->buf,
sizeof(enb_ue->e_cgi.plmn_id));
memcpy(&enb_ue->e_cgi.cell_id, cell_ID->buf, sizeof(enb_ue->e_cgi.cell_id));
enb_ue->e_cgi.cell_id = (ntohl(enb_ue->e_cgi.cell_id) >> 4);
memcpy(&eea, encryptionAlgorithms->buf, sizeof(eea));
eea = ntohs(eea);
if (eea == 0)
mme_ue->ue_network_capability.eea0 = 1;
else
mme_ue->ue_network_capability.eea0 = eea >> 9;
memcpy(&eia, integrityProtectionAlgorithms->buf, sizeof(eia));
eia = ntohs(eia);
if (eea == 0)
mme_ue->ue_network_capability.eia0 = 1;
else
mme_ue->ue_network_capability.eia0 = eia >> 9;
for (i = 0; i < ies->e_RABToBeSwitchedDLList.
s1ap_E_RABToBeSwitchedDLItem.count; i++)
{
mme_bearer_t *bearer = NULL;
S1ap_E_RABToBeSwitchedDLItem_t *e_rab = NULL;
e_rab = (S1ap_E_RABToBeSwitchedDLItem_t *)ies->e_RABToBeSwitchedDLList.
s1ap_E_RABToBeSwitchedDLItem.array[i];
d_assert(e_rab, return, "Null param");
bearer = mme_bearer_find_by_ue_ebi(mme_ue, e_rab->e_RAB_ID);
d_assert(bearer, return, "Null param");
memcpy(&bearer->enb_s1u_teid, e_rab->gTP_TEID.buf,
sizeof(bearer->enb_s1u_teid));
bearer->enb_s1u_teid = ntohl(bearer->enb_s1u_teid);
memcpy(&bearer->enb_s1u_addr, e_rab->transportLayerAddress.buf,
sizeof(bearer->enb_s1u_addr));
}
d_trace(3, "[S1AP] PathSwitchRequest : "
"UE[eNB-UE-S1AP-ID(%d)] --> eNB[%s:%d]\n",
enb_ue->enb_ue_s1ap_id,
INET_NTOP(&enb->s1ap_sock->remote.sin_addr.s_addr, buf),
enb->enb_id);
#if 0
s1ap_send_path_switch_ack(mme_ue);
#endif
}

View File

@ -26,9 +26,11 @@ CORE_DECLARE(void) s1ap_handle_ue_context_release_request(
CORE_DECLARE(void) s1ap_handle_ue_context_release_complete(
mme_enb_t *enb, s1ap_message_t *message);
/* FIXME : Can I move the function to EMM handler? */
CORE_DECLARE(void) s1ap_handle_paging(mme_ue_t *mme_ue);
CORE_DECLARE(void) s1ap_handle_path_switch_request(
mme_enb_t *enb, s1ap_message_t *message);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -383,8 +383,44 @@ status_t s1ap_send_ue_context_release_commmand(
rv = s1ap_build_ue_context_release_commmand(&s1apbuf, enb_ue, cause);
d_assert(rv == CORE_OK && s1apbuf, return CORE_ERROR, "s1ap build error");
d_assert(s1ap_send_to_enb(enb, s1apbuf) == CORE_OK,
return CORE_ERROR, "s1ap send error");
rv = s1ap_send_to_enb(enb, s1apbuf);
d_assert(rv == CORE_OK,, "s1ap send error");
return CORE_OK;
}
status_t s1ap_send_path_switch_ack(mme_ue_t *mme_ue)
{
status_t rv;
pkbuf_t *s1apbuf = NULL;
d_assert(mme_ue, return CORE_ERROR, "Null param");
rv = s1ap_build_path_switch_ack(&s1apbuf, mme_ue);
d_assert(rv == CORE_OK && s1apbuf, return CORE_ERROR, "s1ap build error");
rv = nas_send_to_enb(mme_ue, s1apbuf);
d_assert(rv == CORE_OK, return CORE_ERROR, "s1ap send error");
return CORE_OK;
}
status_t s1ap_send_path_switch_failure(mme_enb_t *enb,
c_uint32_t enb_ue_s1ap_id, c_uint32_t mme_ue_s1ap_id, S1ap_Cause_t *cause)
{
status_t rv;
pkbuf_t *s1apbuf = NULL;
d_assert(cause, return CORE_ERROR, "Null param");
d_assert(enb, return CORE_ERROR, "Null param");
rv = s1ap_build_path_switch_failure(&s1apbuf,
enb_ue_s1ap_id, mme_ue_s1ap_id, cause);
d_assert(rv == CORE_OK && s1apbuf, return CORE_ERROR, "s1ap build error");
rv = s1ap_send_to_enb(enb, s1apbuf);
d_assert(rv == CORE_OK,, "s1ap send error");
return rv;
}

View File

@ -25,6 +25,10 @@ CORE_DECLARE(status_t) s1ap_send_initial_context_setup_request(
CORE_DECLARE(status_t) s1ap_send_ue_context_release_commmand(
enb_ue_t *enb_ue, S1ap_Cause_t *cause);
CORE_DECLARE(status_t) s1ap_send_path_switch_ack(mme_ue_t *mme_ue);
CORE_DECLARE(status_t) s1ap_send_path_switch_failure(mme_enb_t *enb,
c_uint32_t enb_ue_s1ap_id, c_uint32_t mme_ue_s1ap_id, S1ap_Cause_t *cause);
int _s1ap_recv_cb(net_sock_t *net_sock, void *data);
#ifdef __cplusplus

View File

@ -86,6 +86,11 @@ void s1ap_state_operational(fsm_t *s, event_t *e)
enb, message);
break;
}
case S1ap_ProcedureCode_id_PathSwitchRequest:
{
s1ap_handle_path_switch_request(enb, message);
break;
}
default:
{
d_warn("Not implemented(choice:%d, proc:%d)",

View File

@ -74,10 +74,10 @@ static void handover_test1(abts_case *tc, void *data)
"\"downlink\" : { \"$numberLong\" : \"35840\" },"
"\"uplink\" : { \"$numberLong\" : \"15360\" } },"
"\"qos\" : {"
"\"qci\" : 6,"
"\"qci\" : 7,"
"\"arp\" : {"
"\"priority_level\" : 6,"
"\"pre_emption_vulnerability\" : 1,"
"\"priority_level\" : 1,"
"\"pre_emption_vulnerability\" : 0,"
"\"pre_emption_capability\" : 1 } },"
"\"type\" : 0 }"
"],"
@ -97,6 +97,9 @@ static void handover_test1(abts_case *tc, void *data)
"\"__v\" : 0"
"}";
mme_self()->mme_ue_s1ap_id = 16777689;
mme_self()->m_tmsi = 0x0400031f;
/* Two eNB connects to MME */
sock1 = tests1ap_enb_connect();
ABTS_PTR_NOTNULL(tc, sock1);
@ -247,6 +250,16 @@ static void handover_test1(abts_case *tc, void *data)
rv = tests1ap_enb_send(sock1, sendbuf);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
core_sleep(time_from_msec(300));
/* Send Path Switch Request */
rv = tests1ap_build_path_switch_request(&sendbuf, 0);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
rv = tests1ap_enb_send(sock2, sendbuf);
ABTS_INT_EQUAL(tc, CORE_OK, rv);
core_sleep(time_from_msec(300));
/********** Remove Subscriber in Database */
doc = BCON_NEW("imsi", BCON_UTF8("001010123456801"));
ABTS_PTR_NOTNULL(tc, doc);

View File

@ -785,6 +785,100 @@ status_t tests1ap_build_service_request(pkbuf_t **pkbuf, int i)
return CORE_OK;
}
status_t tests1ap_build_pdn_connectivity_request(
pkbuf_t **pkbuf, int i)
{
char *payload[TESTS1AP_MAX_MESSAGE] = {
"000d40680000"
"0500000005c08000 0107000800030001 00001a003b3a277c 81dab50a0205d011"
"281208696e746572 6e6574036e673204 6d6e6574271a8080 2110010000108106"
"0000000083060000 0000000d00000a00 006440080055f501 0019d01000434006"
"0055f5011022",
"000d40680000"
"0500000005c08000 0107000800030001 00001a003b3a2710 3fdafa0a0209d011"
"281208706e746572 6e6574036e673204 6d6e6574271a8080 2110010000108106"
"0000000083060000 0000000d00000a00 006440080055f501 0019d01000434006"
"0055f5011022",
"",
"",
"",
"",
"",
"",
"",
};
c_uint16_t len[TESTS1AP_MAX_MESSAGE] = {
108,
108,
0,
0,
0,
0,
0,
0,
0,
};
char hexbuf[MAX_SDU_LEN];
*pkbuf = pkbuf_alloc(0, MAX_SDU_LEN);
if (!(*pkbuf)) return CORE_ERROR;
(*pkbuf)->len = len[i];
memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf),
(*pkbuf)->len);
return CORE_OK;
}
status_t tests1ap_build_pdn_disconnectivity_request(
pkbuf_t **pkbuf, int i)
{
char *payload[TESTS1AP_MAX_MESSAGE] = {
"000d40380000"
"0500000005c08000 0108000800030001 00001a000b0a2732 423c53040206d206"
"006440080055f501 0019d01000434006 0055f5011022",
"",
"",
"",
"",
"",
"",
"",
"",
};
c_uint16_t len[TESTS1AP_MAX_MESSAGE] = {
60,
0,
0,
0,
0,
0,
0,
0,
0,
};
char hexbuf[MAX_SDU_LEN];
*pkbuf = pkbuf_alloc(0, MAX_SDU_LEN);
if (!(*pkbuf)) return CORE_ERROR;
(*pkbuf)->len = len[i];
memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf),
(*pkbuf)->len);
return CORE_OK;
}
status_t tests1ap_build_e_rab_setup_response(pkbuf_t **pkbuf, int i)
{
char *payload[TESTS1AP_MAX_MESSAGE] = {
@ -1013,63 +1107,14 @@ status_t tests1ap_build_deactivate_bearer_accept(
return CORE_OK;
}
status_t tests1ap_build_pdn_connectivity_request(
status_t tests1ap_build_path_switch_request(
pkbuf_t **pkbuf, int i)
{
char *payload[TESTS1AP_MAX_MESSAGE] = {
"000d40680000"
"0500000005c08000 0107000800030001 00001a003b3a277c 81dab50a0205d011"
"281208696e746572 6e6574036e673204 6d6e6574271a8080 2110010000108106"
"0000000083060000 0000000d00000a00 006440080055f501 0019d01000434006"
"0055f5011022",
"000d40680000"
"0500000005c08000 0107000800030001 00001a003b3a2710 3fdafa0a0209d011"
"281208706e746572 6e6574036e673204 6d6e6574271a8080 2110010000108106"
"0000000083060000 0000000d00000a00 006440080055f501 0019d01000434006"
"0055f5011022",
"",
"",
"",
"",
"",
"",
"",
};
c_uint16_t len[TESTS1AP_MAX_MESSAGE] = {
108,
108,
0,
0,
0,
0,
0,
0,
0,
};
char hexbuf[MAX_SDU_LEN];
*pkbuf = pkbuf_alloc(0, MAX_SDU_LEN);
if (!(*pkbuf)) return CORE_ERROR;
(*pkbuf)->len = len[i];
memcpy((*pkbuf)->payload, CORE_HEX(payload[i], strlen(payload[i]), hexbuf),
(*pkbuf)->len);
return CORE_OK;
}
status_t tests1ap_build_pdn_disconnectivity_request(
pkbuf_t **pkbuf, int i)
{
char *payload[TESTS1AP_MAX_MESSAGE] = {
"000d40380000"
"0500000005c08000 0108000800030001 00001a000b0a2732 423c53040206d206"
"006440080055f501 0019d01000434006 0055f5011022",
"0003"
"005d000007000800 0200010016001d01 0017000a0a1f0a01 2db0010000080017"
"000a0c1f0a012db0 0100001000580005 c0010001da006440 080000f1103631d6"
"20004340060000f1 105ba0006b400518 000c0000009d4007 0000f110000201",
"",
"",
@ -1083,7 +1128,7 @@ status_t tests1ap_build_pdn_disconnectivity_request(
};
c_uint16_t len[TESTS1AP_MAX_MESSAGE] = {
60,
97,
0,
0,

View File

@ -35,6 +35,10 @@ CORE_DECLARE(status_t) tests1ap_build_ue_context_release_complete(
pkbuf_t **pkbuf, int i);
CORE_DECLARE(status_t) tests1ap_build_service_request(
pkbuf_t **pkbuf, int i);
CORE_DECLARE(status_t) tests1ap_build_pdn_connectivity_request(
pkbuf_t **pkbuf, int i);
CORE_DECLARE(status_t) tests1ap_build_pdn_disconnectivity_request(
pkbuf_t **pkbuf, int i);
CORE_DECLARE(status_t) tests1ap_build_e_rab_setup_response(
pkbuf_t **pkbuf, int i);
CORE_DECLARE(status_t) tests1ap_build_e_rab_release_response(
@ -45,9 +49,7 @@ CORE_DECLARE(status_t) tests1ap_build_activate_dedicated_bearer_accept(
pkbuf_t **pkbuf, int i);
CORE_DECLARE(status_t) tests1ap_build_deactivate_bearer_accept(
pkbuf_t **pkbuf, int i);
CORE_DECLARE(status_t) tests1ap_build_pdn_connectivity_request(
pkbuf_t **pkbuf, int i);
CORE_DECLARE(status_t) tests1ap_build_pdn_disconnectivity_request(
CORE_DECLARE(status_t) tests1ap_build_path_switch_request(
pkbuf_t **pkbuf, int i);
#ifdef __cplusplus