2017-04-04 01:49:19 +00:00
|
|
|
#define TRACE_MODULE _mme_s11_build
|
2017-03-26 15:48:33 +00:00
|
|
|
|
|
|
|
#include "core_debug.h"
|
|
|
|
|
|
|
|
#include "gtp_types.h"
|
2017-08-31 01:48:14 +00:00
|
|
|
#include "gtp_message.h"
|
2017-03-26 15:48:33 +00:00
|
|
|
|
2017-07-13 01:31:07 +00:00
|
|
|
#include "types.h"
|
2017-04-06 10:20:33 +00:00
|
|
|
#include "mme_context.h"
|
2017-04-04 01:49:19 +00:00
|
|
|
|
2017-09-01 04:51:31 +00:00
|
|
|
status_t mme_s11_build_create_session_request(
|
|
|
|
pkbuf_t **pkbuf, c_uint8_t type, mme_sess_t *sess)
|
2017-03-26 15:48:33 +00:00
|
|
|
{
|
2017-04-06 00:57:56 +00:00
|
|
|
status_t rv;
|
2017-04-11 12:38:24 +00:00
|
|
|
pdn_t *pdn = NULL;
|
2017-04-11 11:44:38 +00:00
|
|
|
mme_sgw_t *sgw = NULL;
|
2017-04-28 07:11:45 +00:00
|
|
|
mme_ue_t *mme_ue = NULL;
|
2017-04-06 00:57:56 +00:00
|
|
|
gtp_message_t gtp_message;
|
|
|
|
gtp_create_session_request_t *req = >p_message.create_session_request;
|
|
|
|
|
2017-03-26 15:48:33 +00:00
|
|
|
gtp_uli_t uli;
|
|
|
|
char uli_buf[GTP_MAX_ULI_LEN];
|
2017-04-14 00:36:14 +00:00
|
|
|
gtp_f_teid_t mme_s11_teid, pgw_s5c_teid;
|
2017-03-26 15:48:33 +00:00
|
|
|
gtp_ambr_t ambr;
|
|
|
|
gtp_bearer_qos_t bearer_qos;
|
|
|
|
char bearer_qos_buf[GTP_BEARER_QOS_LEN];
|
|
|
|
gtp_ue_timezone_t ue_timezone;
|
2017-08-19 11:16:00 +00:00
|
|
|
c_int8_t apn[MAX_APN_LEN];
|
2017-08-28 12:47:32 +00:00
|
|
|
c_uint32_t pgw_ipv4_addr = 0;
|
2017-03-26 15:48:33 +00:00
|
|
|
|
2017-08-11 06:21:03 +00:00
|
|
|
d_assert(sess, return CORE_ERROR, "Null param");
|
|
|
|
sgw = sess->sgw;
|
|
|
|
d_assert(sgw, return CORE_ERROR, "Null param");
|
2017-08-11 11:25:52 +00:00
|
|
|
pdn = sess->pdn;
|
2017-04-11 12:38:24 +00:00
|
|
|
d_assert(pdn, return CORE_ERROR, "Null param");
|
2017-08-28 12:47:32 +00:00
|
|
|
pgw_ipv4_addr = MME_SESSION_GET_PGW_IPV4_ADDR(sess);
|
|
|
|
d_assert(pgw_ipv4_addr, return CORE_ERROR, "Null param");
|
2017-04-28 07:11:45 +00:00
|
|
|
mme_ue = sess->mme_ue;
|
|
|
|
d_assert(mme_ue, return CORE_ERROR, "Null param");
|
|
|
|
d_assert(mme_ue->enb_ue, return CORE_ERROR, "Null param");
|
2017-04-11 11:44:38 +00:00
|
|
|
|
2017-04-06 00:57:56 +00:00
|
|
|
memset(>p_message, 0, sizeof(gtp_message_t));
|
2017-03-26 15:48:33 +00:00
|
|
|
|
2017-04-28 07:11:45 +00:00
|
|
|
d_assert(mme_ue->imsi_len, return CORE_ERROR, "Null param");
|
2017-04-02 13:30:58 +00:00
|
|
|
req->imsi.presence = 1;
|
2017-04-28 07:11:45 +00:00
|
|
|
req->imsi.data = mme_ue->imsi;
|
|
|
|
req->imsi.len = mme_ue->imsi_len;
|
2017-03-26 15:48:33 +00:00
|
|
|
|
|
|
|
memset(&uli, 0, sizeof(gtp_uli_t));
|
2017-04-11 11:44:38 +00:00
|
|
|
uli.flags.e_cgi = 1;
|
2017-03-26 15:48:33 +00:00
|
|
|
uli.flags.tai = 1;
|
2017-04-28 07:11:45 +00:00
|
|
|
memcpy(&uli.tai.plmn_id, &mme_ue->enb_ue->tai.plmn_id,
|
|
|
|
sizeof(uli.tai.plmn_id));
|
|
|
|
uli.tai.tac = mme_ue->enb_ue->tai.tac;
|
|
|
|
memcpy(&uli.e_cgi.plmn_id, &mme_ue->enb_ue->e_cgi.plmn_id,
|
2017-08-22 15:51:57 +00:00
|
|
|
sizeof(uli.e_cgi.plmn_id));
|
2017-04-28 07:11:45 +00:00
|
|
|
uli.e_cgi.cell_id = mme_ue->enb_ue->e_cgi.cell_id;
|
2017-04-02 13:30:58 +00:00
|
|
|
req->user_location_information.presence = 1;
|
|
|
|
gtp_build_uli(&req->user_location_information, &uli,
|
2017-03-26 15:48:33 +00:00
|
|
|
uli_buf, GTP_MAX_ULI_LEN);
|
|
|
|
|
2017-04-02 13:30:58 +00:00
|
|
|
req->serving_network.presence = 1;
|
2017-04-28 07:11:45 +00:00
|
|
|
req->serving_network.data = &mme_ue->visited_plmn_id;
|
|
|
|
req->serving_network.len = sizeof(mme_ue->visited_plmn_id);
|
2017-03-26 15:48:33 +00:00
|
|
|
|
2017-04-02 13:30:58 +00:00
|
|
|
req->rat_type.presence = 1;
|
|
|
|
req->rat_type.u8 = GTP_RAT_TYPE_EUTRAN;
|
2017-03-26 15:48:33 +00:00
|
|
|
|
2017-04-14 00:36:14 +00:00
|
|
|
memset(&mme_s11_teid, 0, sizeof(gtp_f_teid_t));
|
|
|
|
mme_s11_teid.ipv4 = 1;
|
|
|
|
mme_s11_teid.interface_type = GTP_F_TEID_S11_MME_GTP_C;
|
2017-09-01 12:35:45 +00:00
|
|
|
mme_s11_teid.teid = htonl(mme_ue->mme_s11_teid);
|
|
|
|
mme_s11_teid.ipv4_addr = mme_ue->mme_s11_addr;
|
2017-04-02 13:30:58 +00:00
|
|
|
req->sender_f_teid_for_control_plane.presence = 1;
|
2017-04-14 00:36:14 +00:00
|
|
|
req->sender_f_teid_for_control_plane.data = &mme_s11_teid;
|
2017-04-02 13:30:58 +00:00
|
|
|
req->sender_f_teid_for_control_plane.len = GTP_F_TEID_IPV4_LEN;
|
2017-03-26 15:48:33 +00:00
|
|
|
|
2017-04-14 00:36:14 +00:00
|
|
|
memset(&pgw_s5c_teid, 0, sizeof(gtp_f_teid_t));
|
|
|
|
pgw_s5c_teid.ipv4 = 1;
|
|
|
|
pgw_s5c_teid.interface_type = GTP_F_TEID_S5_S8_PGW_GTP_C;
|
2017-08-28 12:47:32 +00:00
|
|
|
pgw_s5c_teid.ipv4_addr = pgw_ipv4_addr;
|
2017-04-02 13:30:58 +00:00
|
|
|
req->pgw_s5_s8_address_for_control_plane_or_pmip.presence = 1;
|
2017-04-14 00:36:14 +00:00
|
|
|
req->pgw_s5_s8_address_for_control_plane_or_pmip.data = &pgw_s5c_teid;
|
2017-04-02 13:30:58 +00:00
|
|
|
req->pgw_s5_s8_address_for_control_plane_or_pmip.len = GTP_F_TEID_IPV4_LEN;
|
2017-03-26 15:48:33 +00:00
|
|
|
|
2017-04-02 13:30:58 +00:00
|
|
|
req->access_point_name.presence = 1;
|
2017-08-19 11:16:00 +00:00
|
|
|
req->access_point_name.len = apn_build(apn, pdn->apn, strlen(pdn->apn));
|
|
|
|
req->access_point_name.data = apn;
|
2017-03-26 15:48:33 +00:00
|
|
|
|
2017-04-02 13:30:58 +00:00
|
|
|
req->selection_mode.presence = 1;
|
2017-04-11 13:44:57 +00:00
|
|
|
req->selection_mode.u8 =
|
|
|
|
GTP_SELECTION_MODE_MS_OR_NETWORK_PROVIDED_APN | 0xfc;
|
2017-03-26 15:48:33 +00:00
|
|
|
|
2017-04-02 13:30:58 +00:00
|
|
|
req->pdn_type.presence = 1;
|
|
|
|
req->pdn_type.u8 = GTP_PDN_TYPE_IPV4;
|
2017-03-26 15:48:33 +00:00
|
|
|
|
2017-04-12 15:08:12 +00:00
|
|
|
pdn->paa.pdn_type = GTP_PDN_TYPE_IPV4;
|
2017-04-02 13:30:58 +00:00
|
|
|
req->pdn_address_allocation.presence = 1;
|
2017-04-12 01:05:23 +00:00
|
|
|
req->pdn_address_allocation.data = &pdn->paa;
|
|
|
|
req->pdn_address_allocation.len = PAA_IPV4_LEN;
|
2017-03-26 15:48:33 +00:00
|
|
|
|
2017-04-02 13:30:58 +00:00
|
|
|
req->maximum_apn_restriction.presence = 1;
|
|
|
|
req->maximum_apn_restriction.u8 = GTP_APN_NO_RESTRICTION;
|
2017-03-26 15:48:33 +00:00
|
|
|
|
2017-08-22 15:51:57 +00:00
|
|
|
if (pdn->ambr.uplink || pdn->ambr.downlink)
|
|
|
|
{
|
|
|
|
memset(&ambr, 0, sizeof(gtp_ambr_t));
|
|
|
|
ambr.uplink = htonl(pdn->ambr.uplink);
|
|
|
|
ambr.downlink = htonl(pdn->ambr.downlink);
|
|
|
|
req->aggregate_maximum_bit_rate.presence = 1;
|
|
|
|
req->aggregate_maximum_bit_rate.data = &ambr;
|
|
|
|
req->aggregate_maximum_bit_rate.len = sizeof(ambr);
|
|
|
|
}
|
2017-03-26 15:48:33 +00:00
|
|
|
|
2017-08-26 09:52:06 +00:00
|
|
|
if (sess->ue_pco_len)
|
2017-04-14 02:32:06 +00:00
|
|
|
{
|
|
|
|
req->protocol_configuration_options.presence = 1;
|
2017-08-26 09:52:06 +00:00
|
|
|
req->protocol_configuration_options.data = sess->ue_pco;
|
|
|
|
req->protocol_configuration_options.len = sess->ue_pco_len;
|
2017-04-14 02:32:06 +00:00
|
|
|
}
|
2017-03-26 15:48:33 +00:00
|
|
|
|
2017-04-02 13:30:58 +00:00
|
|
|
req->bearer_contexts_to_be_created.presence = 1;
|
|
|
|
req->bearer_contexts_to_be_created.eps_bearer_id.presence = 1;
|
2017-08-26 09:52:06 +00:00
|
|
|
req->bearer_contexts_to_be_created.eps_bearer_id.u8 = sess->ebi;
|
2017-03-26 15:48:33 +00:00
|
|
|
|
|
|
|
memset(&bearer_qos, 0, sizeof(bearer_qos));
|
2017-08-11 08:16:35 +00:00
|
|
|
bearer_qos.qci = pdn->qos.qci;
|
2017-08-22 05:07:37 +00:00
|
|
|
bearer_qos.priority_level = pdn->qos.arp.priority_level;
|
|
|
|
bearer_qos.pre_emption_capability = pdn->qos.arp.pre_emption_capability;
|
|
|
|
bearer_qos.pre_emption_vulnerability =
|
|
|
|
pdn->qos.arp.pre_emption_vulnerability;
|
2017-04-02 13:30:58 +00:00
|
|
|
req->bearer_contexts_to_be_created.bearer_level_qos.presence = 1;
|
|
|
|
gtp_build_bearer_qos(&req->bearer_contexts_to_be_created.bearer_level_qos,
|
2017-03-26 15:48:33 +00:00
|
|
|
&bearer_qos, bearer_qos_buf, GTP_BEARER_QOS_LEN);
|
|
|
|
|
2017-08-22 15:51:57 +00:00
|
|
|
/* FIXME : where did we receive this information from MS */
|
2017-03-26 15:48:33 +00:00
|
|
|
memset(&ue_timezone, 0, sizeof(ue_timezone));
|
|
|
|
ue_timezone.timezone = 0x40;
|
|
|
|
ue_timezone.daylight_saving_time =
|
|
|
|
GTP_UE_TIME_ZONE_NO_ADJUSTMENT_FOR_DAYLIGHT_SAVING_TIME;
|
2017-04-02 13:30:58 +00:00
|
|
|
req->ue_time_zone.presence = 1;
|
|
|
|
req->ue_time_zone.data = &ue_timezone;
|
|
|
|
req->ue_time_zone.len = sizeof(ue_timezone);
|
2017-03-26 15:48:33 +00:00
|
|
|
|
2017-04-02 13:30:58 +00:00
|
|
|
req->charging_characteristics.presence = 1;
|
|
|
|
req->charging_characteristics.data = (c_uint8_t *)"\x54\x00";
|
|
|
|
req->charging_characteristics.len = 2;
|
2017-03-26 15:48:33 +00:00
|
|
|
|
2017-09-01 04:51:31 +00:00
|
|
|
gtp_message.h.type = type;
|
2017-08-31 03:06:11 +00:00
|
|
|
rv = gtp_build_msg(pkbuf, >p_message);
|
2017-04-06 00:57:56 +00:00
|
|
|
d_assert(rv == CORE_OK, return CORE_ERROR, "gtp build failed");
|
|
|
|
|
2017-04-02 13:30:58 +00:00
|
|
|
return CORE_OK;
|
2017-03-26 15:48:33 +00:00
|
|
|
}
|
|
|
|
|
2017-04-13 16:26:50 +00:00
|
|
|
status_t mme_s11_build_modify_bearer_request(
|
2017-09-01 04:51:31 +00:00
|
|
|
pkbuf_t **pkbuf, c_uint8_t type, mme_bearer_t *bearer)
|
2017-04-13 16:26:50 +00:00
|
|
|
{
|
|
|
|
status_t rv;
|
|
|
|
gtp_message_t gtp_message;
|
|
|
|
gtp_modify_bearer_request_t *req = >p_message.modify_bearer_request;
|
|
|
|
|
2017-08-26 09:52:06 +00:00
|
|
|
mme_sess_t *sess = NULL;
|
|
|
|
|
2017-04-14 00:36:14 +00:00
|
|
|
gtp_f_teid_t enb_s1u_teid;
|
|
|
|
|
2017-08-26 09:52:06 +00:00
|
|
|
d_assert(bearer, return CORE_ERROR, "Null param");
|
|
|
|
sess = bearer->sess;
|
|
|
|
d_assert(sess, return CORE_ERROR, "Null param");
|
|
|
|
|
2017-04-13 16:26:50 +00:00
|
|
|
memset(>p_message, 0, sizeof(gtp_message_t));
|
|
|
|
|
2017-04-14 00:36:14 +00:00
|
|
|
req->bearer_contexts_to_be_modified.presence = 1;
|
|
|
|
req->bearer_contexts_to_be_modified.eps_bearer_id.presence = 1;
|
2017-08-26 09:52:06 +00:00
|
|
|
req->bearer_contexts_to_be_modified.eps_bearer_id.u8 = sess->ebi;
|
2017-04-14 00:36:14 +00:00
|
|
|
|
|
|
|
/* Send Data Plane(DL) : ENB-S1U */
|
|
|
|
memset(&enb_s1u_teid, 0, sizeof(gtp_f_teid_t));
|
|
|
|
enb_s1u_teid.ipv4 = 1;
|
|
|
|
enb_s1u_teid.interface_type = GTP_F_TEID_S1_U_ENODEB_GTP_U;
|
|
|
|
enb_s1u_teid.ipv4_addr = bearer->enb_s1u_addr;
|
|
|
|
enb_s1u_teid.teid = htonl(bearer->enb_s1u_teid);
|
|
|
|
req->bearer_contexts_to_be_modified.s1_u_enodeb_f_teid.presence = 1;
|
|
|
|
req->bearer_contexts_to_be_modified.s1_u_enodeb_f_teid.data = &enb_s1u_teid;
|
|
|
|
req->bearer_contexts_to_be_modified.s1_u_enodeb_f_teid.len =
|
|
|
|
GTP_F_TEID_IPV4_LEN;
|
2017-04-13 16:26:50 +00:00
|
|
|
|
2017-09-01 04:51:31 +00:00
|
|
|
gtp_message.h.type = type;
|
2017-08-31 03:06:11 +00:00
|
|
|
rv = gtp_build_msg(pkbuf, >p_message);
|
2017-04-13 16:26:50 +00:00
|
|
|
d_assert(rv == CORE_OK, return CORE_ERROR, "gtp build failed");
|
|
|
|
|
|
|
|
return CORE_OK;
|
|
|
|
}
|
2017-04-28 02:20:09 +00:00
|
|
|
|
2017-09-01 04:51:31 +00:00
|
|
|
status_t mme_s11_build_delete_session_request(
|
|
|
|
pkbuf_t **pkbuf, c_uint8_t type, mme_sess_t *sess)
|
2017-04-28 02:20:09 +00:00
|
|
|
{
|
|
|
|
status_t rv;
|
2017-04-28 07:11:45 +00:00
|
|
|
mme_ue_t *mme_ue = NULL;
|
2017-04-28 02:20:09 +00:00
|
|
|
gtp_message_t gtp_message;
|
|
|
|
gtp_delete_session_request_t *req = >p_message.delete_session_request;
|
|
|
|
|
2017-07-26 05:18:28 +00:00
|
|
|
gtp_uli_t uli;
|
|
|
|
char uli_buf[GTP_MAX_ULI_LEN];
|
2017-04-28 06:30:04 +00:00
|
|
|
gtp_indication_t indication;
|
2017-04-28 02:20:09 +00:00
|
|
|
|
2017-04-28 04:46:16 +00:00
|
|
|
d_assert(sess, return CORE_ERROR, "Null param");
|
2017-04-28 07:11:45 +00:00
|
|
|
mme_ue = sess->mme_ue;
|
|
|
|
d_assert(mme_ue, return CORE_ERROR, "Null param");
|
2017-04-28 02:20:09 +00:00
|
|
|
|
|
|
|
memset(>p_message, 0, sizeof(gtp_message_t));
|
|
|
|
|
2017-08-26 09:52:06 +00:00
|
|
|
req->linked_eps_bearer_id.presence = 1;
|
|
|
|
req->linked_eps_bearer_id.u8 = sess->ebi;
|
2017-04-28 06:30:04 +00:00
|
|
|
|
2017-07-26 05:18:28 +00:00
|
|
|
memset(&uli, 0, sizeof(gtp_uli_t));
|
|
|
|
uli.flags.e_cgi = 1;
|
|
|
|
uli.flags.tai = 1;
|
|
|
|
memcpy(&uli.tai.plmn_id, &mme_ue->enb_ue->tai.plmn_id,
|
|
|
|
sizeof(uli.tai.plmn_id));
|
|
|
|
uli.tai.tac = mme_ue->enb_ue->tai.tac;
|
|
|
|
memcpy(&uli.e_cgi.plmn_id, &mme_ue->enb_ue->e_cgi.plmn_id,
|
|
|
|
sizeof(uli.tai.plmn_id));
|
|
|
|
uli.e_cgi.cell_id = mme_ue->enb_ue->e_cgi.cell_id;
|
|
|
|
req->user_location_information.presence = 1;
|
|
|
|
gtp_build_uli(&req->user_location_information, &uli,
|
|
|
|
uli_buf, GTP_MAX_ULI_LEN);
|
|
|
|
|
2017-04-28 06:30:04 +00:00
|
|
|
memset(&indication, 0, sizeof(gtp_indication_t));
|
|
|
|
indication.oi = 1;
|
|
|
|
req->indication_flags.presence = 1;
|
|
|
|
req->indication_flags.data = &indication;
|
|
|
|
req->indication_flags.len = sizeof(gtp_indication_t);
|
|
|
|
|
2017-09-01 04:51:31 +00:00
|
|
|
gtp_message.h.type = type;
|
2017-08-31 03:06:11 +00:00
|
|
|
rv = gtp_build_msg(pkbuf, >p_message);
|
2017-04-28 02:20:09 +00:00
|
|
|
d_assert(rv == CORE_OK, return CORE_ERROR, "gtp build failed");
|
|
|
|
|
|
|
|
return CORE_OK;
|
|
|
|
}
|
2017-07-25 12:15:25 +00:00
|
|
|
|
2017-09-01 04:51:31 +00:00
|
|
|
status_t mme_s11_build_release_access_bearers_request(
|
|
|
|
pkbuf_t **pkbuf, c_uint8_t type)
|
2017-07-25 12:15:25 +00:00
|
|
|
{
|
|
|
|
status_t rv;
|
|
|
|
gtp_message_t gtp_message;
|
|
|
|
gtp_release_access_bearers_request_t *req =
|
|
|
|
>p_message.release_access_bearers_request;
|
|
|
|
|
|
|
|
memset(>p_message, 0, sizeof(gtp_message_t));
|
|
|
|
|
|
|
|
req->originating_node.presence = 1;
|
|
|
|
req->originating_node.u8 = GTP_NODE_TYPE_MME;
|
|
|
|
|
2017-09-01 04:51:31 +00:00
|
|
|
gtp_message.h.type = type;
|
2017-08-31 03:06:11 +00:00
|
|
|
rv = gtp_build_msg(pkbuf, >p_message);
|
2017-07-25 12:15:25 +00:00
|
|
|
d_assert(rv == CORE_OK, return CORE_ERROR, "gtp build failed");
|
|
|
|
|
|
|
|
return CORE_OK;
|
|
|
|
}
|
2017-08-02 23:18:19 +00:00
|
|
|
|
2017-09-01 04:51:31 +00:00
|
|
|
status_t mme_s11_build_downlink_data_notification_ack(
|
2017-09-01 12:35:45 +00:00
|
|
|
pkbuf_t **pkbuf, c_uint8_t type, mme_ue_t *mme_ue)
|
2017-08-02 23:18:19 +00:00
|
|
|
{
|
|
|
|
status_t rv;
|
|
|
|
gtp_message_t gtp_message;
|
|
|
|
gtp_downlink_data_notification_acknowledge_t *ack =
|
|
|
|
>p_message.downlink_data_notification_acknowledge;
|
|
|
|
|
|
|
|
gtp_cause_t cause;
|
|
|
|
|
|
|
|
d_assert(mme_ue, return CORE_ERROR, "Null param");
|
|
|
|
|
|
|
|
memset(>p_message, 0, sizeof(gtp_message_t));
|
|
|
|
|
|
|
|
memset(&cause, 0, sizeof(cause));
|
|
|
|
cause.value = GTP_CAUSE_REQUEST_ACCEPTED;
|
|
|
|
|
|
|
|
ack->cause.presence = 1;
|
|
|
|
ack->cause.data = &cause;
|
|
|
|
ack->cause.len = sizeof(cause);
|
|
|
|
|
2017-09-01 04:51:31 +00:00
|
|
|
gtp_message.h.type = type;
|
2017-08-31 03:06:11 +00:00
|
|
|
rv = gtp_build_msg(pkbuf, >p_message);
|
2017-08-02 23:18:19 +00:00
|
|
|
d_assert(rv == CORE_OK, return CORE_ERROR, "gtp build failed");
|
|
|
|
|
|
|
|
return CORE_OK;
|
|
|
|
}
|