Revert "[MME] Gn: Introduce initial support for 4G->2G cell reselection"

This reverts commit 5a31af36e0.
This commit is contained in:
Pau Espin 2023-12-21 14:57:34 +01:00 committed by Sukchan Lee
parent 2390a22504
commit 6a9c7f16c1
15 changed files with 1 additions and 941 deletions

View File

@ -34,9 +34,6 @@
#define FC_FOR_KENB_DERIVATION 0x11
#define FC_FOR_NH_ENB_DERIVATION 0x12
#define FC_FOR_EPS_ALGORITHM_KEY_DERIVATION 0x15
#define FC_FOR_CK_IK_DERIVATION_HANDOVER 0x16
#define FC_FOR_NAS_TOKEN_DERIVATION 0x17
#define FC_FOR_CK_IK_DERIVATION_IDLE_MOBILITY 0x1B
typedef struct kdf_param_s {
const uint8_t *buf;
@ -382,56 +379,6 @@ void ogs_kdf_nas_eps(uint8_t algorithm_type_distinguishers,
memcpy(knas, output+16, 16);
}
/* TS33.401 Annex A.8: KASME to CK', IK' derivation at handover */
void ogs_kdf_ck_ik_handover(
uint32_t dl_count, const uint8_t *kasme, uint8_t *ck, uint8_t *ik)
{
kdf_param_t param;
uint8_t output[OGS_SHA256_DIGEST_SIZE];
memset(param, 0, sizeof(param));
param[0].buf = (uint8_t *)&dl_count;
param[0].len = 4;
ogs_kdf_common(kasme, OGS_SHA256_DIGEST_SIZE,
FC_FOR_CK_IK_DERIVATION_HANDOVER, param, output);
memcpy(ck, output, 16);
memcpy(ik, output+16, 16);
}
/* TS33.401 Annex A.9: NAS token derivation for inter-RAT mobility */
void ogs_kdf_nas_token(
uint32_t ul_count, const uint8_t *kasme, uint8_t *nas_token)
{
kdf_param_t param;
uint8_t output[OGS_SHA256_DIGEST_SIZE];
memset(param, 0, sizeof(param));
param[0].buf = (uint8_t *)&ul_count;
param[0].len = 4;
ogs_kdf_common(kasme, OGS_SHA256_DIGEST_SIZE,
FC_FOR_NAS_TOKEN_DERIVATION, param, output);
memcpy(nas_token, output, 2);
}
/* TS33.401 Annex A.13: KASME to CK', IK' derivation at idle mobility */
void ogs_kdf_ck_ik_idle_mobility(
uint32_t ul_count, const uint8_t *kasme, uint8_t *ck, uint8_t *ik)
{
kdf_param_t param;
uint8_t output[OGS_SHA256_DIGEST_SIZE];
memset(param, 0, sizeof(param));
param[0].buf = (uint8_t *)&ul_count;
param[0].len = 4;
ogs_kdf_common(kasme, OGS_SHA256_DIGEST_SIZE,
FC_FOR_CK_IK_DERIVATION_IDLE_MOBILITY, param, output);
memcpy(ck, output, 16);
memcpy(ik, output+16, 16);
}
/*
* TS33.401 Annex I Hash Functions
* Use the KDF given in TS33.220

View File

@ -101,18 +101,6 @@ void ogs_kdf_nh_enb(const uint8_t *kasme, const uint8_t *sync_input, uint8_t *ke
void ogs_kdf_nas_eps(uint8_t algorithm_type_distinguishers,
uint8_t algorithm_identity, const uint8_t *kasme, uint8_t *knas);
/* TS33.401 Annex A.8: KASME to CK', IK' derivation at handover */
void ogs_kdf_ck_ik_handover(
uint32_t dl_count, const uint8_t *kasme, uint8_t *ck, uint8_t *ik);
/* TS33.401 Annex A.9: NAS token derivation for inter-RAT mobility */
void ogs_kdf_nas_token(
uint32_t ul_count, const uint8_t *kasme, uint8_t *nas_token);
/* TS33.401 Annex A.13: KASME to CK', IK' derivation at idle mobility */
void ogs_kdf_ck_ik_idle_mobility(
uint32_t ul_count, const uint8_t *kasme, uint8_t *ck, uint8_t *ik);
/*
* TS33.401 Annex I Hash Functions
* Use the KDF given in TS33.220

View File

@ -104,34 +104,6 @@ int ogs_gtp1_gsn_addr_to_ip(const ogs_gtp1_gsn_addr_t *gsnaddr, uint16_t gsnaddr
return OGS_OK;
}
int ogs_gtp1_pdu_session_type_to_eua_ietf_type(uint8_t session_type)
{
switch (session_type) {
case OGS_PDU_SESSION_TYPE_IPV4:
return OGS_PDP_EUA_IETF_IPV4;
case OGS_PDU_SESSION_TYPE_IPV6:
return OGS_PDP_EUA_IETF_IPV6;
case OGS_PDU_SESSION_TYPE_IPV4V6:
return OGS_PDP_EUA_IETF_IPV4V6;
default:
return OGS_ERROR;
}
}
int ogs_gtp1_eua_ietf_type_to_pdu_session_type(uint8_t eua_ietf_type)
{
switch (eua_ietf_type) {
case OGS_PDP_EUA_IETF_IPV4:
return OGS_PDU_SESSION_TYPE_IPV4;
case OGS_PDP_EUA_IETF_IPV6:
return OGS_PDU_SESSION_TYPE_IPV6;
case OGS_PDP_EUA_IETF_IPV4V6:
return OGS_PDU_SESSION_TYPE_IPV4V6;
default:
return OGS_ERROR;
}
}
int ogs_gtp1_eua_to_ip(const ogs_eua_t *eua, uint16_t eua_len, ogs_ip_t *ip,
uint8_t *pdu_session_type)
{

View File

@ -35,9 +35,6 @@ int ogs_gtp1_sockaddr_to_gsn_addr(const ogs_sockaddr_t *addr,
int ogs_gtp1_gsn_addr_to_ip(const ogs_gtp1_gsn_addr_t *gsnaddr, uint16_t gsnaddr_len,
ogs_ip_t *ip);
int ogs_gtp1_pdu_session_type_to_eua_ietf_type(uint8_t session_type);
int ogs_gtp1_eua_ietf_type_to_pdu_session_type(uint8_t eua_ietf_type);
int ogs_gtp1_eua_to_ip(const ogs_eua_t *eua, uint16_t eua_len, ogs_ip_t *ip,
uint8_t *pdu_session_type);

View File

@ -398,318 +398,3 @@ int16_t ogs_gtp1_build_qos_profile(ogs_tlv_octet_t *octet,
octet->len = 6;
return octet->len;
}
/* 7.7.28 MM Context */
/* TODO: UMTS support, see Figure 41 and Figure 42. */
int ogs_gtp1_build_mm_context(ogs_gtp1_tlv_mm_context_t *octet,
const ogs_gtp1_mm_context_decoded_t *decoded, uint8_t *data, int data_len)
{
uint8_t *ptr = data;
unsigned int i;
uint16_t *len_ptr;
uint16_t val16;
ogs_assert(octet);
ogs_assert(data);
ogs_assert((size_t)data_len >= 1);
octet->data = data;
#define CHECK_SPACE_ERR(bytes) \
if ((ptr - data) + (bytes) > data_len) \
return OGS_ERROR
CHECK_SPACE_ERR(1);
*ptr++ = (decoded->gupii & 0x01) << 7 |
(decoded->ugipai & 0x01) << 6 |
(decoded->used_gprs_protection_algo & 0x07) << 3 |
(decoded->ksi & 0x07);
CHECK_SPACE_ERR(1);
*ptr++ = (decoded->sec_mode & 0x03) << 6 |
(decoded->num_vectors & 0x07) << 3 |
(decoded->sec_mode == OGS_GTP1_SEC_MODE_USED_CIPHER_VALUE_UMTS_KEY_AND_QUINTUPLETS ?
decoded->used_cipher & 0x07 : 0x07);
CHECK_SPACE_ERR(sizeof(decoded->ck));
memcpy(ptr, &decoded->ck[0], sizeof(decoded->ck));
ptr += sizeof(decoded->ck);
CHECK_SPACE_ERR(sizeof(decoded->ik));
memcpy(ptr, &decoded->ik[0], sizeof(decoded->ik));
ptr += sizeof(decoded->ik);
/* Quintuplet Length */
CHECK_SPACE_ERR(2);
len_ptr = (uint16_t *)ptr; /* will be filled later */
ptr += 2;
for (i = 0; i < decoded->num_vectors; i++) {
CHECK_SPACE_ERR(sizeof(decoded->auth_quintuplets[0]));
memcpy(ptr, &decoded->auth_quintuplets[i].rand, sizeof(decoded->auth_quintuplets[i].rand));
ptr += sizeof(decoded->auth_quintuplets[i].rand);
*ptr++ = decoded->auth_quintuplets[i].xres_len;
memcpy(ptr, &decoded->auth_quintuplets[i].xres[0], decoded->auth_quintuplets[i].xres_len);
ptr += decoded->auth_quintuplets[i].xres_len;
memcpy(ptr, &decoded->auth_quintuplets[i].ck, sizeof(decoded->auth_quintuplets[i].ck));
ptr += sizeof(decoded->auth_quintuplets[i].ck);
memcpy(ptr, &decoded->auth_quintuplets[i].ik, sizeof(decoded->auth_quintuplets[i].ik));
ptr += sizeof(decoded->auth_quintuplets[i].ik);
*ptr++ = decoded->auth_quintuplets[i].autn_len;
memcpy(ptr, &decoded->auth_quintuplets[i].autn[0], decoded->auth_quintuplets[i].autn_len);
ptr += decoded->auth_quintuplets[i].autn_len;
}
*len_ptr = htobe16(ptr - (((uint8_t *)len_ptr) + 2));
CHECK_SPACE_ERR(sizeof(decoded->drx_param));
memcpy(ptr, &decoded->drx_param, sizeof(decoded->drx_param));
ptr += sizeof(decoded->drx_param);
if (decoded->ms_network_capability_len != 0) {
/* MS Network Capability Length */
CHECK_SPACE_ERR(1 + decoded->ms_network_capability_len);
*ptr++ = decoded->ms_network_capability_len;
memcpy(ptr, &decoded->ms_network_capability, decoded->ms_network_capability_len);
ptr += decoded->ms_network_capability_len;
} else {
CHECK_SPACE_ERR(1);
*ptr++ = 0;
}
if (decoded->imeisv_len != 0) {
/* Container Len */
CHECK_SPACE_ERR(2);
val16 = htobe16(2 + decoded->imeisv_len);
memcpy(ptr, &val16, 2);
ptr += 2;
/* Container (Mobile Identity IMEISV), TS 29.060 Table 47A */
CHECK_SPACE_ERR(2 + decoded->imeisv_len);
*ptr++ = 0x23;
*ptr++ = decoded->imeisv_len; /* Length of mobile identity contents */
memcpy(ptr, &decoded->imeisv[0], decoded->imeisv_len);
ptr += decoded->imeisv_len;
} else {
/* Container Len */
CHECK_SPACE_ERR(2);
*ptr++ = 0;
*ptr++ = 0;
}
if (decoded->nrsrna) {
CHECK_SPACE_ERR(2);
*ptr++ = 1;
*ptr++ = 0x01;
}
octet->len = (ptr - data);
return OGS_OK;
#undef CHECK_SPACE_ERR
}
/* The format of EUA in PDP Context is not exactly the same for the entire EUA,
* hence a separate function is required to encode the value part of the address,
* instead of using regular ogs_gtp1_ip_to_eua(). */
static int enc_pdp_ctx_as_eua(uint8_t pdu_session_type, const ogs_ip_t *ip,
uint8_t *data, int data_len)
{
switch (pdu_session_type)
{
case OGS_PDU_SESSION_TYPE_IPV4:
if (!ip->ipv4) {
ogs_error("EUA type IPv4 but no IPv4 address available");
return OGS_ERROR;
}
if (data_len < OGS_IPV4_LEN)
return OGS_ERROR;
memcpy(data, &ip->addr, OGS_IPV4_LEN);
return OGS_IPV4_LEN;
case OGS_PDU_SESSION_TYPE_IPV6:
if (!ip->ipv6) {
ogs_error("EUA type IPv4 but no IPv6 address available");
return OGS_ERROR;
}
if (data_len < OGS_IPV6_LEN)
return OGS_ERROR;
memcpy(data, ip->addr6, OGS_IPV6_LEN);
return OGS_IPV6_LEN;
case OGS_PDU_SESSION_TYPE_IPV4V6:
if (ip->ipv4 && ip->ipv6) {
if (data_len < OGS_IPV4_LEN + OGS_IPV6_LEN)
return OGS_ERROR;
memcpy(data, &ip->addr, OGS_IPV4_LEN);
memcpy(data + OGS_IPV4_LEN, ip->addr6, OGS_IPV6_LEN);
return OGS_IPV4_LEN + OGS_IPV6_LEN;
} else if (ip->ipv4) {
if (data_len < OGS_IPV4_LEN)
return OGS_ERROR;
memcpy(data, &ip->addr, OGS_IPV4_LEN);
return OGS_IPV4_LEN;
} else if (ip->ipv6) {
if (data_len < OGS_IPV6_LEN)
return OGS_ERROR;
memcpy(data, ip->addr6, OGS_IPV6_LEN);
return OGS_IPV6_LEN;
} else {
ogs_error("EUA type IPv4 but no IPv4 nor IPv6 address available");
return OGS_ERROR;
}
break;
default:
ogs_error("Unexpected session type");
return OGS_ERROR;
}
return OGS_OK;
}
/* TS 29.060 7.7.29 PDP Context */
int ogs_gtp1_build_pdp_context(ogs_tlv_octet_t *octet,
const ogs_gtp1_pdp_context_decoded_t *decoded, uint8_t *data, int data_len)
{
uint8_t *ptr = data;
uint16_t val16;
uint32_t val32;
int rv;
ogs_tlv_octet_t qos_sub_tlv_unused;
ogs_assert(octet);
ogs_assert(data);
ogs_assert((size_t)data_len >= 1);
octet->data = data;
#define CHECK_SPACE_ERR(bytes) \
if ((ptr - data) + (bytes) > data_len) \
return OGS_ERROR
CHECK_SPACE_ERR(1);
*ptr++ = (decoded->ea << 7) | (decoded->vaa << 6) |
(decoded->asi << 5)| (decoded->order << 4) |
(decoded->nsapi & 0x0f);
CHECK_SPACE_ERR(1);
*ptr++ = (decoded->sapi & 0x0f);
/* Quality of Service Subscribed */
CHECK_SPACE_ERR(1 + OGS_GTP1_QOS_PROFILE_MAX_LEN);
rv = ogs_gtp1_build_qos_profile(&qos_sub_tlv_unused, &decoded->qos_sub,
ptr, (data + data_len) - (ptr + 1));
if (rv < 0)
return rv;
*ptr = rv;
ptr += 1 + rv;
/* Quality of Service Requested */
CHECK_SPACE_ERR(1 + OGS_GTP1_QOS_PROFILE_MAX_LEN);
rv = ogs_gtp1_build_qos_profile(&qos_sub_tlv_unused, &decoded->qos_req,
ptr, (data + data_len) - (ptr + 1));
if (rv < 0)
return rv;
*ptr = rv;
ptr += 1 + rv;
/* Quality of Service Negotiated */
CHECK_SPACE_ERR(1 + OGS_GTP1_QOS_PROFILE_MAX_LEN);
rv = ogs_gtp1_build_qos_profile(&qos_sub_tlv_unused, &decoded->qos_neg,
ptr, (data + data_len) - (ptr + 1));
if (rv < 0)
return rv;
*ptr = rv;
ptr += 1 + rv;
CHECK_SPACE_ERR(2);
val16 = htobe16(decoded->snd);
memcpy(ptr, &val16, 2);
ptr += 2;
CHECK_SPACE_ERR(2);
val16 = htobe16(decoded->snu);
memcpy(ptr, &val16, 2);
ptr += 2;
CHECK_SPACE_ERR(1);
*ptr++ = decoded->send_npdu_nr;
CHECK_SPACE_ERR(1);
*ptr++ = decoded->receive_npdu_nr;
CHECK_SPACE_ERR(4);
val32 = htobe32(decoded->ul_teic);
memcpy(ptr, &val32, 4);
ptr += 4;
CHECK_SPACE_ERR(4);
val32 = htobe32(decoded->ul_teid);
memcpy(ptr, &val32, 4);
ptr += 4;
CHECK_SPACE_ERR(1);
*ptr++ = decoded->pdp_ctx_id;
CHECK_SPACE_ERR(1);
*ptr++ = 0xf0 | decoded->pdp_type_org;
CHECK_SPACE_ERR(1);
*ptr++ = ogs_gtp1_pdu_session_type_to_eua_ietf_type(decoded->pdp_type_num[0]);
/* PDP Address Length filled after PDP Address */
CHECK_SPACE_ERR(1);
rv = enc_pdp_ctx_as_eua(decoded->pdp_type_num[0], &decoded->pdp_address[0],
ptr + 1, (data + data_len) - (ptr + 1));
if (rv < 0)
return rv;
*ptr = rv;
ptr += 1 + rv;
/* GGSN Address for control plane Length */
CHECK_SPACE_ERR(1);
*ptr = decoded->ggsn_address_c.ipv6 ? OGS_GTP_GSN_ADDRESS_IPV6_LEN : OGS_GTP_GSN_ADDRESS_IPV4_LEN;
CHECK_SPACE_ERR(1 + (*ptr));
memcpy(ptr + 1,
decoded->ggsn_address_c.ipv6 ?
(uint8_t *)decoded->ggsn_address_c.addr6 :
(uint8_t *)&decoded->ggsn_address_c.addr,
*ptr);
ptr += 1 + *ptr;
/* GGSN Address for User Traffic Length */
CHECK_SPACE_ERR(1);
*ptr = decoded->ggsn_address_u.ipv6 ? OGS_GTP_GSN_ADDRESS_IPV6_LEN : OGS_GTP_GSN_ADDRESS_IPV4_LEN;
CHECK_SPACE_ERR(1 + (*ptr));
memcpy(ptr + 1,
decoded->ggsn_address_u.ipv6 ?
(uint8_t *)decoded->ggsn_address_u.addr6 :
(uint8_t *)&decoded->ggsn_address_u.addr,
*ptr);
ptr += 1 + *ptr;
/* APN */
rv = strlen(decoded->apn);
CHECK_SPACE_ERR(1 + rv + 1);
*ptr = ogs_fqdn_build(
(char *)ptr + 1, decoded->apn, rv);
ptr += 1 + *ptr;
CHECK_SPACE_ERR(2);
*ptr++ = (decoded->trans_id >> 8) & 0x0f;
*ptr++ = decoded->trans_id & 0xff;
if (decoded->ea == OGS_GTP1_PDPCTX_EXT_EUA_YES) {
CHECK_SPACE_ERR(1);
*ptr++ = decoded->pdp_type_num[1];
/* PDP Address Length filled after PDP Address */
CHECK_SPACE_ERR(1);
rv = enc_pdp_ctx_as_eua(decoded->pdp_type_num[1], &decoded->pdp_address[1],
ptr + 1, (data + data_len) - (ptr + 1));
if (rv < 0)
return rv;
*ptr = rv;
ptr += 1 + rv;
}
octet->len = (ptr - data);
return OGS_OK;
#undef CHECK_SPACE_ERR
}

View File

@ -300,112 +300,4 @@ int16_t ogs_gtp1_parse_qos_profile(
int16_t ogs_gtp1_build_qos_profile(ogs_tlv_octet_t *octet,
const ogs_gtp1_qos_profile_decoded_t *decoded, void *data, int data_len);
/* 7.7.7 Authentication Triplet. FIXME: Not used in MME Gn scenario? */
# if 0
struct ogs_gtp1_auth_triplet_s {
uint8_t rand[16];
uint8_t sres[4];
uint8_t kc[8];
} __attribute__ ((packed)) ogs_gtp1_auth_triplet_t;
#endif
/* 7.7.35 Authentication Quintuplet */
typedef struct ogs_gtp1_auth_quintuplet_s {
uint8_t rand[OGS_RAND_LEN];
uint8_t xres_len;
uint8_t xres[OGS_MAX_RES_LEN];
uint8_t ck[128/8];
uint8_t ik[128/8];
uint8_t autn_len;
uint8_t autn[OGS_AUTN_LEN];
} ogs_gtp1_auth_quintuplet_t;
/* TS 24.008 10.5.5.6 DRX parameter (value part only) */
typedef struct ogs_gtp1_drx_param_val_s {
uint8_t split_pg_cycle_code; /* 0 = equivalent to no DRX */
ED3(uint8_t cn_drx_cycle_len_coeff:4;,
uint8_t split_on_ccch:1;,
uint8_t non_drx_timer:3;)
} __attribute__ ((packed)) ogs_gtp1_drx_param_val_t;
/* 7.7.28 MM Context (Figure 41) */
/* Table 47: Security Mode Values */
#define OGS_GTP1_SEC_MODE_GSM_KEY_AND_TRIPLETS 1
#define OGS_GTP1_SEC_MODE_GSM_KEY_AND_QUINTUPLETS 3
#define OGS_GTP1_SEC_MODE_UMTS_KEY_AND_QUINTUPLETS 2
#define OGS_GTP1_SEC_MODE_USED_CIPHER_VALUE_UMTS_KEY_AND_QUINTUPLETS 0
/* Table 47B: Used GPRS integrity protection algorithm Values */
#define OGS_GTP1_USED_GPRS_IP_NO_IP 0
#define OGS_GTP1_USED_GPRS_IP_GIA4 4
#define OGS_GTP1_USED_GPRS_IP_GIA5 5
typedef struct ogs_gtp1_mm_context_decoded_s {
uint8_t gupii:1;
uint8_t ugipai:1;
uint8_t used_gprs_protection_algo:3; /* OGS_GTP1_USED_GPRS_IP */
uint8_t ksi:3;
uint8_t sec_mode:2; /* OGS_GTP1_SEC_MODE_* */
uint8_t num_vectors:3;
uint8_t used_cipher:3; /* 0..7 -> GEA/... */
uint8_t ck[OGS_SHA256_DIGEST_SIZE/2];
uint8_t ik[OGS_SHA256_DIGEST_SIZE/2];
ogs_gtp1_auth_quintuplet_t auth_quintuplets[5];
ogs_gtp1_drx_param_val_t drx_param;
uint8_t ms_network_capability_len;
uint8_t ms_network_capability[6]; /* ogs_nas_ms_network_capability_t */
uint8_t imeisv_len;
uint8_t imeisv[10]; /* ogs_nas_mobile_identity_imeisv_t */
uint8_t nrsrna;
} ogs_gtp1_mm_context_decoded_t;
int ogs_gtp1_build_mm_context(ogs_gtp1_tlv_mm_context_t *octet,
const ogs_gtp1_mm_context_decoded_t *decoded, uint8_t *data, int data_len);
/* Extended End User Address. Not explicitly defined in a table: */
#define OGS_GTP1_PDPCTX_EXT_EUA_NO 0
#define OGS_GTP1_PDPCTX_EXT_EUA_YES 1
/* 7.7.29 Table 48 Reordering Required Values */
#define OGS_GTP1_PDPCTX_REORDERING_REQUIRED_NO 0
#define OGS_GTP1_PDPCTX_REORDERING_REQUIRED_YES 1
/* 7.7.29 Table 49 VPLMN Address Allowed Values */
#define OGS_GTP1_PDPCTX_VLPMN_ADDR_ALLOWED_NO 0
#define OGS_GTP1_PDPCTX_VLPMN_ADDR_ALLOWED_YES 1
/* 7.7.29 Table 49A Activity Status Indicator Value */
#define OGS_GTP1_PDPCTX_ACTIVITY_STATUS_IND_YES 0
#define OGS_GTP1_PDPCTX_ACTIVITY_STATUS_IND_NO 1
/* 7.7.29 PDP Context */
typedef struct ogs_gtp1_pdp_context_decoded_s {
uint8_t ea:1; /* OGS_GTP1_PDPCTX_EXT_EUA_* */
uint8_t vaa:1; /* OGS_GTP1_PDPCTX_VLPMN_ADDR_ALLOWED_* */
uint8_t asi:1; /* OGS_GTP1_PDPCTX_ACTIVITY_STATUS_IND_* */
uint8_t order:1; /* OGS_GTP1_PDPCTX_REORDERING_REQUIRED_* */
uint8_t nsapi:4;
uint8_t sapi:4;
ogs_gtp1_qos_profile_decoded_t qos_sub;
ogs_gtp1_qos_profile_decoded_t qos_req;
ogs_gtp1_qos_profile_decoded_t qos_neg;
uint16_t snd;
uint16_t snu;
uint8_t send_npdu_nr;
uint8_t receive_npdu_nr;
uint32_t ul_teic;
uint32_t ul_teid;
uint8_t pdp_ctx_id;
uint8_t pdp_type_org;
uint8_t pdp_type_num[2];
ogs_ip_t pdp_address[2];
ogs_ip_t ggsn_address_c;
ogs_ip_t ggsn_address_u;
char apn[OGS_MAX_APN_LEN+1];
uint16_t trans_id:12;
} ogs_gtp1_pdp_context_decoded_t;
int ogs_gtp1_build_pdp_context(ogs_gtp1_tlv_pdp_context_t *octet,
const ogs_gtp1_pdp_context_decoded_t *decoded, uint8_t *data, int data_len);
#endif /* OGS_GTP1_TYPES_H */

View File

@ -1012,7 +1012,6 @@ static ogs_gtp_xact_stage_t ogs_gtp1_xact_get_stage(uint8_t type, uint32_t xid)
case OGS_GTP1_NOTE_MS_GPRS_PRESENT_RESPONSE_TYPE:
case OGS_GTP1_IDENTIFICATION_RESPONSE_TYPE:
case OGS_GTP1_SGSN_CONTEXT_RESPONSE_TYPE:
case OGS_GTP1_SGSN_CONTEXT_ACKNOWLEDGE_TYPE:
case OGS_GTP1_FORWARD_RELOCATION_RESPONSE_TYPE:
case OGS_GTP1_RELOCATION_CANCEL_RESPONSE_TYPE:
case OGS_GTP1_UE_REGISTRATION_QUERY_RESPONSE_TYPE:

View File

@ -421,11 +421,6 @@ struct mme_ue_s {
char a_msisdn_bcd[OGS_MAX_MSISDN_BCD_LEN+1];
mme_p_tmsi_t p_tmsi;
struct {
uint32_t sgsn_gn_teid;
ogs_ip_t sgsn_gn_ip;
ogs_ip_t sgsn_gn_ip_alt;
} gn;
struct {
mme_m_tmsi_t *m_tmsi;

View File

@ -21,262 +21,6 @@
#include "mme-gn-build.h"
static int sess_fill_mm_context_decoded(mme_sess_t *sess, ogs_gtp1_mm_context_decoded_t *mmctx_dec)
{
mme_ue_t *mme_ue = sess->mme_ue;
mme_bearer_t *bearer = NULL;
*mmctx_dec = (ogs_gtp1_mm_context_decoded_t) {
.gupii = 1, /* Integrity Protection not required */
.ugipai = 1, /* Ignore "Used GPRS integrity protection algorithm" field" */
.ksi = mme_ue->nas_eps.ksi,
.sec_mode = OGS_GTP1_SEC_MODE_UMTS_KEY_AND_QUINTUPLETS,
.num_vectors = 0, /* TODO: figure out how to fill the quintuplets */
.drx_param = {
.split_pg_cycle_code = 0, /* equivalent to no DRX */
.cn_drx_cycle_len_coeff = 0,
.split_on_ccch = 0,
.non_drx_timer = 0,
},
.nrsrna = 0,
};
//TODO: derive cK Ki from mme_ue->kasme
ogs_kdf_ck_ik_idle_mobility(mme_ue->ul_count.i32, mme_ue->kasme, &mmctx_dec->ck[0], &mmctx_dec->ik[0]);
mmctx_dec->imeisv_len = sizeof(mme_ue->nas_mobile_identity_imeisv);
memcpy(&mmctx_dec->imeisv[0], &mme_ue->nas_mobile_identity_imeisv, sizeof(mme_ue->nas_mobile_identity_imeisv));
mmctx_dec->ms_network_capability_len = mme_ue->ms_network_capability.length;
memcpy(&mmctx_dec->ms_network_capability[0], ((uint8_t*)&mme_ue->ms_network_capability)+1, sizeof(mme_ue->ms_network_capability) - 1);
ogs_list_for_each(&sess->bearer_list, bearer) {
/* FIXME: only 1 PDP Context supported in the message so far. */
break;
}
return OGS_OK;
}
/* 3GPP TS 23.401 Annex E */
static void build_qos_profile_from_session(ogs_gtp1_qos_profile_decoded_t *qos_pdec,
const mme_sess_t *sess, const mme_bearer_t *bearer)
{
const mme_ue_t *mme_ue = sess->mme_ue;
const ogs_session_t *session = sess->session;
/* FIXME: Initialize with defaults: */
memset(qos_pdec, 0, sizeof(*qos_pdec));
qos_pdec->qos_profile.arp = session->qos.arp.priority_level;
/* 3GPP TS 23.401 Annex E table Table E.3 */
/* Also take into account table 7 in 3GPP TS 23.107 9.1.2.2 */
switch (session->qos.index) { /* QCI */
case 1:
qos_pdec->qos_profile.data.traffic_class = OGS_GTP1_QOS_TRAFFIC_CLASS_CONVERSATIONAL;
qos_pdec->qos_profile.data.source_statistics_descriptor = OGS_GTP1_QOS_SRC_STATS_DESC_SPEECH;
qos_pdec->dec_transfer_delay = 150;
qos_pdec->qos_profile.data.delay_class = 1;
break;
case 2:
qos_pdec->qos_profile.data.traffic_class = OGS_GTP1_QOS_TRAFFIC_CLASS_CONVERSATIONAL;
qos_pdec->qos_profile.data.source_statistics_descriptor = OGS_GTP1_QOS_SRC_STATS_DESC_UNKNOWN;
qos_pdec->dec_transfer_delay = 150;
qos_pdec->qos_profile.data.delay_class = 1;
break;
case 3:
qos_pdec->qos_profile.data.traffic_class = OGS_GTP1_QOS_TRAFFIC_CLASS_CONVERSATIONAL;
qos_pdec->qos_profile.data.source_statistics_descriptor = OGS_GTP1_QOS_SRC_STATS_DESC_UNKNOWN;
qos_pdec->dec_transfer_delay = 80;
qos_pdec->qos_profile.data.delay_class = 1;
break;
case 4:
qos_pdec->qos_profile.data.traffic_class = OGS_GTP1_QOS_TRAFFIC_CLASS_STREAMING;
qos_pdec->qos_profile.data.source_statistics_descriptor = OGS_GTP1_QOS_SRC_STATS_DESC_UNKNOWN;
qos_pdec->qos_profile.data.sdu_error_ratio = 5; /* 10^-5*/
qos_pdec->qos_profile.data.delay_class = 1;
break;
case 5:
qos_pdec->qos_profile.data.traffic_class = OGS_GTP1_QOS_TRAFFIC_CLASS_INTERACTIVE;
qos_pdec->qos_profile.data.traffic_handling_priority = 1;
qos_pdec->qos_profile.data.signalling_indication = 1;
qos_pdec->qos_profile.data.delay_class = qos_pdec->qos_profile.data.traffic_handling_priority;
break;
case 6:
qos_pdec->qos_profile.data.traffic_class = OGS_GTP1_QOS_TRAFFIC_CLASS_INTERACTIVE;
qos_pdec->qos_profile.data.traffic_handling_priority = 1;
qos_pdec->qos_profile.data.delay_class = qos_pdec->qos_profile.data.traffic_handling_priority;
break;
case 7:
qos_pdec->qos_profile.data.traffic_class = OGS_GTP1_QOS_TRAFFIC_CLASS_INTERACTIVE;
qos_pdec->qos_profile.data.traffic_handling_priority = 2;
qos_pdec->qos_profile.data.delay_class = qos_pdec->qos_profile.data.traffic_handling_priority;
break;
case 8:
qos_pdec->qos_profile.data.traffic_class = OGS_GTP1_QOS_TRAFFIC_CLASS_INTERACTIVE;
qos_pdec->qos_profile.data.traffic_handling_priority = 3;
qos_pdec->qos_profile.data.delay_class = qos_pdec->qos_profile.data.traffic_handling_priority;
break;
case 9:
default:
qos_pdec->qos_profile.data.traffic_class = OGS_GTP1_QOS_TRAFFIC_CLASS_BACKGROUND;
qos_pdec->qos_profile.data.delay_class = 4;
break;
}
qos_pdec->data_octet6_to_13_present = true;
qos_pdec->data_octet14_present = true;
qos_pdec->dec_mbr_kbps_dl = mme_ue->ambr.downlink / 1000;
qos_pdec->dec_mbr_kbps_ul = mme_ue->ambr.uplink / 1000;
qos_pdec->dec_gbr_kbps_dl = bearer->qos.gbr.downlink / 1000;
qos_pdec->dec_gbr_kbps_ul = bearer->qos.gbr.uplink / 1000;
}
static int sess_fill_pdp_context_decoded(mme_sess_t *sess, ogs_gtp1_pdp_context_decoded_t *pdpctx_dec)
{
mme_bearer_t *bearer = NULL;
*pdpctx_dec = (ogs_gtp1_pdp_context_decoded_t){
.ea = OGS_GTP1_PDPCTX_EXT_EUA_NO,
.vaa = OGS_GTP1_PDPCTX_VLPMN_ADDR_ALLOWED_YES,
.asi = OGS_GTP1_PDPCTX_ACTIVITY_STATUS_IND_NO,
.order = OGS_GTP1_PDPCTX_REORDERING_REQUIRED_NO,
.ul_teic = sess->pgw_s5c_teid,
};
pdpctx_dec->ggsn_address_c = sess->pgw_s5c_ip;
pdpctx_dec->pdp_type_org = OGS_PDP_EUA_ORG_IETF;
pdpctx_dec->pdp_type_num[0] = sess->session->session_type;
pdpctx_dec->pdp_address[0] = sess->session->ue_ip;
ogs_cpystrn(pdpctx_dec->apn, sess->session->name, sizeof(pdpctx_dec->apn));
pdpctx_dec->trans_id = sess->pti;
ogs_list_for_each(&sess->bearer_list, bearer) {
pdpctx_dec->nsapi = bearer->ebi;
pdpctx_dec->sapi = 3; /* FIXME. Using 3 = default for now. Maybe use 0 = UNASSIGNED ?*/
build_qos_profile_from_session(&pdpctx_dec->qos_sub, sess, bearer);
//FIXME: sort out where to get each one:
memcpy(&pdpctx_dec->qos_req, &pdpctx_dec->qos_sub, sizeof(pdpctx_dec->qos_sub));
memcpy(&pdpctx_dec->qos_neg, &pdpctx_dec->qos_sub, sizeof(pdpctx_dec->qos_sub));
pdpctx_dec->snd = 0; /* FIXME. */
pdpctx_dec->snu = 0; /* FIXME. */
pdpctx_dec->send_npdu_nr = 0; /* FIXME. */
pdpctx_dec->receive_npdu_nr = 0; /* FIXME. */
pdpctx_dec->ul_teid = bearer->pgw_s5u_teid;
pdpctx_dec->pdp_ctx_id = 0; /* FIXME. */
pdpctx_dec->ggsn_address_u = bearer->pgw_s5u_ip;
/* TODO: session->qos and bearer->qos to fill something in pdpctx_dec. */
/* FIXME: only 1 PDP Context supported in the message so far. */
break;
}
return OGS_OK;
}
/* 3GPP TS 29.060 7.5.4 SGSN Context Response */
ogs_pkbuf_t *mme_gn_build_sgsn_context_response(
mme_ue_t *mme_ue, uint8_t cause)
{
ogs_gtp1_message_t gtp1_message;
ogs_gtp1_sgsn_context_response_t *rsp = NULL;
mme_sess_t *sess = NULL;
ogs_gtp1_gsn_addr_t mme_gnc_gsnaddr;
int gsn_len;
int rv;
ogs_gtp1_mm_context_decoded_t mmctx_dec;
uint8_t mmctx_dec_buf[512];
ogs_gtp1_pdp_context_decoded_t pdpctx_dec;
uint8_t pdpctx_dec_buf[1024];
ogs_debug("[Gn] build SGSN Context Response");
rsp = &gtp1_message.sgsn_context_response;
memset(&gtp1_message, 0, sizeof(ogs_gtp1_message_t));
gtp1_message.h.type = OGS_GTP1_SGSN_CONTEXT_RESPONSE_TYPE;
/* 3GPP TS 29.060 7.7.1 Cause, Mandatory */
rsp->cause.presence = 1;
rsp->cause.u8 = cause;
/* 3GPP TS 29.060 7.7.2 IMSI, Conditional */
rsp->imsi.presence = !!mme_ue;
if (rsp->imsi.presence) {
rsp->imsi.data = mme_ue->imsi;
rsp->imsi.len = mme_ue->imsi_len;
}
if (cause != OGS_GTP1_CAUSE_REQUEST_ACCEPTED)
goto build_ret;
ogs_assert(mme_ue);
/* FIXME: Reuse S11 TEID as local Gn interface for now */
rsp->tunnel_endpoint_identifier_control_plane.presence = 1;
rsp->tunnel_endpoint_identifier_control_plane.u32 = mme_ue->mme_s11_teid;
ogs_list_for_each(&mme_ue->sess_list, sess) {
if (!MME_HAVE_SGW_S1U_PATH(sess))
continue;
/* 7.7.28 MM Context */
rv = sess_fill_mm_context_decoded(sess, &mmctx_dec);
if (rv != OGS_OK) {
ogs_error("sess_fill_mm_context_decoded() failed");
return NULL;
}
rsp->mm_context.presence = 1;
rv = ogs_gtp1_build_mm_context(&rsp->mm_context, &mmctx_dec,
&mmctx_dec_buf[0], sizeof(mmctx_dec_buf));
if (rv != OGS_OK) {
ogs_error("ogs_gtp1_build_mm_context() failed");
return NULL;
}
/* 7.7.29 PDP Context */
rv = sess_fill_pdp_context_decoded(sess, &pdpctx_dec);
if (rv != OGS_OK) {
ogs_error("sess_fill_pdp_context_decoded() failed");
return NULL;
}
rsp->pdp_context.presence = 1;
rv = ogs_gtp1_build_pdp_context(&rsp->pdp_context, &pdpctx_dec,
&pdpctx_dec_buf[0], sizeof(pdpctx_dec_buf));
if (rv != OGS_OK) {
ogs_error("ogs_gtp1_build_pdp_context() failed");
return NULL;
}
/* FIXME: right now we only support encoding 1 context in the message. */
break;
}
/* SGSN Address for Control Plane */
if (ogs_gtp_self()->gtpc_addr6 &&
(mme_ue->gn.sgsn_gn_ip.ipv6 || mme_ue->gn.sgsn_gn_ip_alt.ipv6)) {
rv = ogs_gtp1_sockaddr_to_gsn_addr(NULL, ogs_gtp_self()->gtpc_addr6,
&mme_gnc_gsnaddr, &gsn_len);
if (rv != OGS_OK) {
ogs_error("ogs_gtp1_sockaddr_to_gsn_addr() failed");
return NULL;
}
} else {
rv = ogs_gtp1_sockaddr_to_gsn_addr(ogs_gtp_self()->gtpc_addr, NULL,
&mme_gnc_gsnaddr, &gsn_len);
if (rv != OGS_OK) {
ogs_error("ogs_gtp1_sockaddr_to_gsn_addr() failed");
return NULL;
}
}
rsp->sgsn_address_for_control_plane.presence = 1;
rsp->sgsn_address_for_control_plane.data = &mme_gnc_gsnaddr;
rsp->sgsn_address_for_control_plane.len = gsn_len;
build_ret:
return ogs_gtp1_build_msg(&gtp1_message);
}
/* 3GPP TS 29.060 7.5.14.1 RAN Information Relay */
ogs_pkbuf_t *mme_gn_build_ran_information_relay(
uint8_t type, const uint8_t *buf, size_t len,
@ -315,4 +59,4 @@ ogs_pkbuf_t *mme_gn_build_ran_information_relay(
gtp1_message.h.type = type;
return ogs_gtp1_build_msg(&gtp1_message);
}
}

View File

@ -30,9 +30,6 @@ extern "C" {
}
#endif
ogs_pkbuf_t *mme_gn_build_sgsn_context_response(
mme_ue_t *mme_ue, uint8_t cause);
ogs_pkbuf_t *mme_gn_build_ran_information_relay(
uint8_t type, const uint8_t *buf, size_t len,
const ogs_nas_rai_t *rai, uint16_t cell_id);

View File

@ -68,117 +68,6 @@ static int decode_global_enb_id(S1AP_Global_ENB_ID_t *glob_enb_id, const uint8_t
return OGS_OK;
}
/* 3GPP TS 23.003 2.8.2.2 Mapping from RAI and P-TMSI to GUT */
static void rai_ptmsi_to_guti(const ogs_nas_rai_t *rai, mme_p_tmsi_t ptmsi, uint32_t ptmsi_sig, ogs_nas_eps_guti_t *nas_guti)
{
uint16_t lac = be16toh(rai->lai.lac);;
nas_guti->nas_plmn_id =rai->lai.nas_plmn_id;
nas_guti->mme_gid = lac;
nas_guti->mme_code = rai->rac;
nas_guti->m_tmsi = 0xC0000000 | (ptmsi & 0x3f000000) | (ptmsi_sig & 0x00ff0000) | (ptmsi & 0x0000ffff);
}
/* TS 29.060 7.5.3 SGSN Context Request */
void mme_gn_handle_sgsn_context_request(
ogs_gtp_xact_t *xact, ogs_gtp1_sgsn_context_request_t *req)
{
ogs_nas_eps_guti_t nas_guti;
ogs_nas_rai_t *rai;
mme_ue_t *mme_ue = NULL;
int rv;
ogs_debug("[Gn] Rx SGSN Context Request");
if (!req->routeing_area_identity.presence) {
ogs_warn("[Gn] Rx SGSN Context Request with no RAI!");
mme_gtp1_send_sgsn_context_response(NULL, OGS_GTP1_CAUSE_MANDATORY_IE_MISSING, xact);
return;
}
if (req->routeing_area_identity.len != sizeof(*rai)) {
ogs_warn("[Gn] Rx SGSN Context Request RAI wrong size %u vs exp %zu!",
req->routeing_area_identity.len, sizeof(*rai));
mme_gtp1_send_sgsn_context_response(NULL, OGS_GTP1_CAUSE_MANDATORY_IE_INCORRECT, xact);
return;
}
if (!req->tunnel_endpoint_identifier_control_plane.presence) {
ogs_warn("[Gn] Rx SGSN Context Request with no Tunnel Endpoint Identifier Control Plane!");
mme_gtp1_send_sgsn_context_response(NULL, OGS_GTP1_CAUSE_MANDATORY_IE_MISSING, xact);
return;
}
if (!req->sgsn_address_for_control_plane.presence) {
ogs_warn("[Gn] Rx SGSN Context Request with no SGSN Address for Control Plane!");
mme_gtp1_send_sgsn_context_response(NULL, OGS_GTP1_CAUSE_MANDATORY_IE_MISSING, xact);
return;
}
if (!req->imsi.presence &&
!req->temporary_logical_link_identifier.presence &&
!req->packet_tmsi.presence) {
ogs_warn("[Gn] Rx SGSN Context Request with no IMSI/TLLI/P-TMSI!");
mme_gtp1_send_sgsn_context_response(NULL, OGS_GTP1_CAUSE_MANDATORY_IE_MISSING, xact);
return;
}
if (req->ms_validated.presence &&
(req->ms_validated.u8 & 0x01) /* 1=> "Yes" */
&& !req->imsi.presence) {
ogs_warn("[Gn] Rx SGSN Context Request with 'MS Validated' but no IMSI!");
mme_gtp1_send_sgsn_context_response(NULL, OGS_GTP1_CAUSE_MANDATORY_IE_MISSING, xact);
return;
}
rai = req->routeing_area_identity.data;
if (req->imsi.presence) {
mme_ue = mme_ue_find_by_imsi(req->imsi.data, req->imsi.len);
} else if (req->packet_tmsi.presence) { /* P-TMSI */
if (!req->p_tmsi_signature.presence) {
ogs_warn("[Gn] Rx SGSN Context Request with 'P-TMSI' but no P-TMSI Signature! Assuming value 0.");
req->p_tmsi_signature.u24 = 0;
}
rai_ptmsi_to_guti(rai, req->packet_tmsi.u32, req->p_tmsi_signature.u24, &nas_guti);
mme_ue = mme_ue_find_by_guti(&nas_guti);
} else if (req->temporary_logical_link_identifier.presence) {
if (!req->p_tmsi_signature.presence) {
ogs_warn("[Gn] Rx SGSN Context Request with 'TLLI' but no P-TMSI Signature! Assuming value 0.");
req->p_tmsi_signature.u24 = 0;
}
/* TS 29.060 7.5.3 "The TLLI/P-TMSI and RAI is a foreign TLLI/P-TMSI and an RAI in the old SGSN."
* A foregin TLLI is "tlli = (p_tmsi & 0x3fffffff) | 0x80000000", and since we only use 0x3fffffff
* bits of P-TMSI to derive the GUTI, it's totally fine passing the TLLI as P-TMSI. */
rai_ptmsi_to_guti(rai, req->temporary_logical_link_identifier.u32, req->p_tmsi_signature.u24, &nas_guti);
mme_ue = mme_ue_find_by_guti(&nas_guti);
}
if (!mme_ue) {
mme_gtp1_send_sgsn_context_response(NULL, OGS_GTP1_CAUSE_IMSI_IMEI_NOT_KNOWN, xact);
return;
}
mme_ue->gn.sgsn_gn_teid = req->tunnel_endpoint_identifier_control_plane.u32;
rv = ogs_gtp1_gsn_addr_to_ip(req->sgsn_address_for_control_plane.data,
req->sgsn_address_for_control_plane.len,
&mme_ue->gn.sgsn_gn_ip);
ogs_assert(rv == OGS_OK);
if (req->alternative_sgsn_address_for_control_plane.presence) {
rv = ogs_gtp1_gsn_addr_to_ip(req->alternative_sgsn_address_for_control_plane.data,
req->alternative_sgsn_address_for_control_plane.len,
&mme_ue->gn.sgsn_gn_ip_alt);
ogs_assert(rv == OGS_OK);
}
mme_gtp1_send_sgsn_context_response(mme_ue, OGS_GTP1_CAUSE_REQUEST_ACCEPTED, xact);
}
/* TS 29.060 7.5.5 SGSN Context Acknowledge */
void mme_gn_handle_sgsn_context_acknowledge(
ogs_gtp_xact_t *xact, ogs_gtp1_sgsn_context_acknowledge_t *req)
{
/* FIXME: find out what to do here, 3GPP TS 23.401 D.3.5
* Probably release the Session on the SGW (without releasing in the PGW) */
}
/* TS 29.060 7.5.14.1 */
void mme_gn_handle_ran_information_relay(
ogs_gtp_xact_t *xact, ogs_gtp1_ran_information_relay_t *req)

View File

@ -32,12 +32,6 @@ void mme_gn_handle_echo_request(
void mme_gn_handle_echo_response(
ogs_gtp_xact_t *xact, ogs_gtp1_echo_response_t *req);
void mme_gn_handle_sgsn_context_request(
ogs_gtp_xact_t *xact, ogs_gtp1_sgsn_context_request_t *req);
void mme_gn_handle_sgsn_context_acknowledge(
ogs_gtp_xact_t *xact, ogs_gtp1_sgsn_context_acknowledge_t *req);
void mme_gn_handle_ran_information_relay(
ogs_gtp_xact_t *xact, ogs_gtp1_ran_information_relay_t *req);

View File

@ -758,36 +758,6 @@ int mme_gtp_send_bearer_resource_command(
return rv;
}
int mme_gtp1_send_sgsn_context_response(
mme_ue_t *mme_ue, uint8_t cause, ogs_gtp_xact_t *xact)
{
int rv;
ogs_gtp1_header_t h;
ogs_pkbuf_t *pkbuf = NULL;
memset(&h, 0, sizeof(ogs_gtp1_header_t));
h.type = OGS_GTP1_SGSN_CONTEXT_RESPONSE_TYPE;
h.teid = mme_ue ? mme_ue->gn.sgsn_gn_teid : 0;
pkbuf = mme_gn_build_sgsn_context_response(mme_ue, cause);
if (!pkbuf) {
ogs_error("mme_gn_build_sgsn_context_response() failed");
return OGS_ERROR;
}
/* FIXME: Reuse S11 TEID as local Gn interface for now */
xact->local_teid = mme_ue ? mme_ue->mme_s11_teid : 0;
rv = ogs_gtp1_xact_update_tx(xact, &h, pkbuf);
if (rv != OGS_OK) {
ogs_error("ogs_gtp1_xact_update_tx() failed");
return OGS_ERROR;
}
rv = ogs_gtp_xact_commit(xact);
ogs_expect(rv == OGS_OK);
return rv;
}
int mme_gtp1_send_ran_information_relay(
mme_sgsn_t *sgsn, const uint8_t *buf, size_t len,

View File

@ -55,9 +55,6 @@ int mme_gtp_send_delete_indirect_data_forwarding_tunnel_request(
int mme_gtp_send_bearer_resource_command(
mme_bearer_t *bearer, ogs_nas_eps_message_t *nas_message);
int mme_gtp1_send_sgsn_context_response(
mme_ue_t *mme_ue, uint8_t cause, ogs_gtp_xact_t *xact);
int mme_gtp1_send_ran_information_relay(
mme_sgsn_t *sgsn, const uint8_t *buf, size_t len,
const ogs_nas_rai_t *rai, uint16_t cell_id);

View File

@ -662,12 +662,6 @@ void mme_state_operational(ogs_fsm_t *s, mme_event_t *e)
case OGS_GTP1_ECHO_RESPONSE_TYPE:
mme_gn_handle_echo_response(xact, &gtp1_message.echo_response);
break;
case OGS_GTP1_SGSN_CONTEXT_REQUEST_TYPE:
mme_gn_handle_sgsn_context_request(xact, &gtp1_message.sgsn_context_request);
break;
case OGS_GTP1_SGSN_CONTEXT_ACKNOWLEDGE_TYPE:
mme_gn_handle_sgsn_context_acknowledge(xact, &gtp1_message.sgsn_context_acknowledge);
break;
case OGS_GTP1_RAN_INFORMATION_RELAY_TYPE:
mme_gn_handle_ran_information_relay(xact, &gtp1_message.ran_information_relay);
break;