[SMF] Improve 3GPP-User-Location-Info in Gn,Gx,Gy (#1539)

* [GTP] Fix trailing whitespace

* [SMF] Improve 3GPP-User-Location-Info in Gn,Gx,Gy
This commit is contained in:
Pau Espin 2022-05-17 03:29:11 +02:00 committed by GitHub
parent b2f2016a67
commit 46621538af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 156 additions and 100 deletions

View File

@ -125,9 +125,16 @@ extern struct dict_object *ogs_diam_gy_pre_emption_vulnerability;
extern struct dict_object *ogs_diam_gy_apn_aggregate_max_bitrate_ul;
extern struct dict_object *ogs_diam_gy_apn_aggregate_max_bitrate_dl;
extern struct dict_object *ogs_diam_gy_3gpp_rat_type;
#define OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_TAI 128
#define OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_ECGI 129
#define OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_TAI_AND_ECGI 130
#define OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_CGI 0
#define OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_SAI 1
#define OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_RAI 2
#define OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_TAI 128
#define OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_ECGI 129
#define OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_TAI_AND_ECGI 130
#define OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_ENODEB_ID 131
#define OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_TAI_AND_ENODEB_ID 132
#define OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_EXT_ENODEB_ID 133
#define OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_TAI_AND_EXT_ENODEB_ID 134
extern struct dict_object *ogs_diam_gy_3gpp_user_location_info;
extern struct dict_object *ogs_diam_gy_called_station_id;
extern struct dict_object *ogs_diam_gy_3gpp_ms_timezone;

View File

@ -19,7 +19,7 @@
#include "ogs-gtp.h"
/* 8.13 Protocol Configuration Options (PCO)
/* 8.13 Protocol Configuration Options (PCO)
* 10.5.6.3 Protocol configuration options in 3GPP TS 24.008 */
/* 8.15 Bearer Quality of Service (Bearer QoS) */
@ -63,7 +63,7 @@ int16_t ogs_gtp2_parse_bearer_qos(
size += 5;
ogs_assert(size == octet->len);
return size;
}
int16_t ogs_gtp2_build_bearer_qos(ogs_tlv_octet_t *octet,
@ -233,7 +233,7 @@ int16_t ogs_gtp2_parse_flow_qos(
size += 5;
ogs_assert(size == octet->len);
return size;
}
int16_t ogs_gtp2_build_flow_qos(ogs_tlv_octet_t *octet,
@ -277,7 +277,7 @@ int16_t ogs_gtp2_build_flow_qos(ogs_tlv_octet_t *octet,
return octet->len;
}
/* 8.19 EPS Bearer Level Traffic Flow Template (Bearer TFT)
/* 8.19 EPS Bearer Level Traffic Flow Template (Bearer TFT)
* See subclause 10.5.6.12 in 3GPP TS 24.008 [13]. */
int16_t ogs_gtp2_parse_tft(ogs_gtp2_tft_t *tft, ogs_tlv_octet_t *octet)
{
@ -673,6 +673,16 @@ int16_t ogs_gtp2_parse_uli(ogs_gtp2_uli_t *uli, ogs_tlv_octet_t *octet)
uli->lai.lac = be16toh(uli->lai.lac);
size += sizeof(uli->lai);
}
if (uli->flags.enodeb_id) {
ogs_assert(size + sizeof(uli->enodeb_id) <= octet->len);
memcpy(&uli->enodeb_id,
(unsigned char *)octet->data + size, sizeof(uli->enodeb_id));
uli->enodeb_id.enodeb_id = be16toh(uli->enodeb_id.enodeb_id);
size += sizeof(uli->enodeb_id);
}
if (uli->flags.ext_enodeb_id) { /* TODO */
ogs_error("Extended Macro eNodeB ID in ULI not implemented! see 3GPP TS 29.274 8.21.8");
}
ogs_assert(size == octet->len);
@ -714,7 +724,7 @@ int16_t ogs_gtp2_build_uli(
size += sizeof(target.sai);
}
if (target.flags.rai) {
ogs_assert(size + sizeof(target.rai) <= data_len);
ogs_assert(size + sizeof(target.rai) <= data_len);
target.rai.lac = htobe16(target.rai.lac);
target.rai.rac = htobe16(target.rai.rac);
memcpy((unsigned char *)octet->data + size,
@ -742,6 +752,16 @@ int16_t ogs_gtp2_build_uli(
&target.lai, sizeof(target.lai));
size += sizeof(target.lai);
}
if (target.flags.enodeb_id) {
ogs_assert(size + sizeof(target.enodeb_id) <= data_len);
target.enodeb_id.enodeb_id = htobe16(target.enodeb_id.enodeb_id);
memcpy((unsigned char *)octet->data + size,
&target.enodeb_id, sizeof(target.enodeb_id));
size += sizeof(target.enodeb_id);
}
if (uli->flags.ext_enodeb_id) { /* TODO */
ogs_error("Extended Macro eNodeB ID in ULI not implemented! see 3GPP TS 29.274 8.21.8");
}
octet->len = size;

View File

@ -389,15 +389,29 @@ typedef struct ogs_gtp2_uli_e_cgi_s {
uint32_t cell_id;
} __attribute__ ((packed)) ogs_gtp2_uli_e_cgi_t;
typedef struct ogs_gtp2_uli_enodeb_id_s {
ogs_nas_plmn_id_t nas_plmn_id;
uint16_t enodeb_id;
} __attribute__ ((packed)) ogs_gtp2_uli_enodeb_id_t;
typedef struct ogs_gtp2_uli_ext_enodeb_id_s {
ogs_nas_plmn_id_t nas_plmn_id;
uint32_t enodeb_id;
} __attribute__ ((packed)) ogs_gtp2_uli_ext_enodeb_id_t;
typedef struct ogs_gtp2_uli_s {
struct {
ED7(uint8_t spare:2;,
uint8_t lai:1;,
uint8_t e_cgi:1;,
uint8_t tai:1;,
uint8_t rai:1;,
uint8_t sai:1;,
uint8_t cgi:1;)
union {
struct {
ED8(uint8_t ext_enodeb_id:1;,
uint8_t enodeb_id:1;,
uint8_t lai:1;,
uint8_t e_cgi:1;,
uint8_t tai:1;,
uint8_t rai:1;,
uint8_t sai:1;,
uint8_t cgi:1;)
};
uint8_t octet;
} flags;
ogs_gtp2_uli_cgi_t cgi;
ogs_gtp2_uli_sai_t sai;
@ -405,6 +419,8 @@ typedef struct ogs_gtp2_uli_s {
ogs_gtp2_uli_tai_t tai;
ogs_gtp2_uli_e_cgi_t e_cgi;
ogs_gtp2_uli_lai_t lai;
ogs_gtp2_uli_enodeb_id_t enodeb_id;
ogs_gtp2_uli_ext_enodeb_id_t ext_enodeb_id;
} ogs_gtp2_uli_t;
int16_t ogs_gtp2_parse_uli(ogs_gtp2_uli_t *uli, ogs_tlv_octet_t *octet);

View File

@ -59,3 +59,89 @@ void smf_fd_final(void)
ogs_diam_final();
}
/* Append 3GPP-User-Location-Info, 3GPP TS 29.061 16.4.7.2 22 */
void smf_fd_msg_avp_add_3gpp_uli(smf_sess_t *sess, struct avp *avp)
{
struct avp *avpch1;
union avp_value val;
ogs_gtp2_uli_t uli;
int16_t uli_len;
uint8_t uli_buf[OGS_GTP2_MAX_ULI_LEN], reencoded_uli_buf[OGS_GTP2_MAX_ULI_LEN];
uint8_t uli_type;
int ret;
ogs_gtp2_tlv_uli_t reencoded_uli;
if (sess->gtp.user_location_information.presence == 0)
return;
if (sess->gtp.version == 1) {
/* For GTPv1C, it's a 1-1 coding match with TS 29.060 7.7.51: */
ret = fd_msg_avp_new(
ogs_diam_gy_3gpp_user_location_info, 0, &avpch1);
ogs_assert(ret == 0);
val.os.data = sess->gtp.user_location_information.data;
val.os.len = sess->gtp.user_location_information.len;
ret = fd_msg_avp_setvalue(avpch1, &val);
ogs_assert(ret == 0);
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avpch1);
ogs_assert(ret == 0);
return;
}
/* GTPv2C and Diameter 3GPP-User-Location-Information encoding don't match */
uli_len = ogs_gtp2_parse_uli(
&uli, &sess->gtp.user_location_information);
ogs_assert(sess->gtp.user_location_information.len == uli_len);
ogs_assert(sess->gtp.user_location_information.data);
ogs_assert(sess->gtp.user_location_information.len);
memcpy(&uli_buf, sess->gtp.user_location_information.data,
sess->gtp.user_location_information.len);
/* Update Gy ULI Type */
if (uli.flags.cgi) {
uli_type = OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_CGI;
uli.flags.octet = 0; uli.flags.cgi = 1;
} else if (uli.flags.sai) {
uli_type = OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_SAI;
uli.flags.octet = 0; uli.flags.sai = 1;
} else if (uli.flags.rai) {
uli_type = OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_RAI;
uli.flags.octet = 0; uli.flags.rai = 1;
} else if (uli.flags.tai && uli.flags.e_cgi) {
uli_type = OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_TAI_AND_ECGI;
uli.flags.octet = 0; uli.flags.tai = 1; uli.flags.e_cgi = 1;
} else if (uli.flags.tai && uli.flags.enodeb_id) {
uli_type = OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_TAI_AND_ENODEB_ID;
uli.flags.octet = 0; uli.flags.tai = 1; uli.flags.enodeb_id = 1;
} else if (uli.flags.tai && uli.flags.ext_enodeb_id) {
uli_type = OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_TAI_AND_EXT_ENODEB_ID;
uli.flags.octet = 0; uli.flags.tai = 1; uli.flags.ext_enodeb_id = 1;
} else if (uli.flags.tai) {
uli_type = OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_TAI;
uli.flags.octet = 0; uli.flags.tai = 1;
} else if (uli.flags.e_cgi) {
uli_type = OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_ECGI;
uli.flags.octet = 0; uli.flags.e_cgi = 1;
} else {
ogs_error("Unexpected ULI content, unable to convert to Diameter!");
return;
}
/* Reencode ULI dropping unrelated values: */
uli_len = ogs_gtp2_build_uli(&reencoded_uli, &uli,
reencoded_uli_buf, sizeof(reencoded_uli_buf));
reencoded_uli_buf[0] = uli_type;
ret = fd_msg_avp_new(
ogs_diam_gy_3gpp_user_location_info, 0, &avpch1);
ogs_assert(ret == 0);
val.os.data = (uint8_t *)&reencoded_uli_buf;
val.os.len = uli_len;
ret = fd_msg_avp_setvalue(avpch1, &val);
ogs_assert(ret == 0);
ret = fd_msg_avp_add(avp, MSG_BRW_LAST_CHILD, avpch1);
ogs_assert(ret == 0);
}

View File

@ -46,6 +46,8 @@ void smf_gy_send_ccr(smf_sess_t *sess, void *xact,
void smf_s6b_send_aar(smf_sess_t *sess, ogs_gtp_xact_t *xact);
void smf_s6b_send_str(smf_sess_t *sess, ogs_gtp_xact_t *xact, uint32_t cause);
void smf_fd_msg_avp_add_3gpp_uli(smf_sess_t *sess, struct avp *avp);
#ifdef __cplusplus
}
#endif

View File

@ -141,10 +141,13 @@ uint8_t smf_gn_handle_create_pdp_context_request(
ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]",
sess->sgw_s5c_teid, sess->smf_n4_teid);
/* User Location Information, TS 29.060 sec 7.7.51 */
/* Note: the IE is content is different in GTPv1C and GTPv2C */
OGS_TLV_STORE_DATA(&sess->gtp.user_location_information,
&req->user_location_information);
if (ogs_gtp1_parse_uli(&uli, &req->user_location_information) == 0)
return OGS_GTP1_CAUSE_MANDATORY_IE_INCORRECT;
/* TODO: Copy uli->cgi/sai/rai into sess-> */
switch (uli.geo_loc_type) {
case OGS_GTP1_GEO_LOC_TYPE_CGI:
ogs_nas_to_plmn_id(&sess->plmn_id, &uli.cgi.nas_plmn_id);
@ -155,6 +158,7 @@ uint8_t smf_gn_handle_create_pdp_context_request(
case OGS_GTP1_GEO_LOC_TYPE_RAI:
ogs_nas_to_plmn_id(&sess->plmn_id, &uli.rai.nas_plmn_id);
break;
/* default: should not happen */
}
/* Set MSISDN: */
@ -203,15 +207,6 @@ uint8_t smf_gn_handle_create_pdp_context_request(
&req->protocol_configuration_options);
}
#if 0
/* Set User Location Information */
/* TODO: the IE is probably different between GTPv1C and GTPv2, see what needs to be adapted */
if (req->user_location_information.presence) {
OGS_TLV_STORE_DATA(&sess->gtp.user_location_information,
&req->user_location_information);
}
#endif
/* Set UE Timezone */
if (req->ms_time_zone.presence) {
/* value part is compatible between UE Time Zone and MS Time Zone */

View File

@ -486,43 +486,8 @@ void smf_gx_send_ccr(smf_sess_t *sess, ogs_gtp_xact_t *xact,
ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp);
ogs_assert(ret == 0);
/* Set 3GPP-User-Location-Info */
if (sess->gtp.user_location_information.presence) {
ogs_gtp2_uli_t uli;
int16_t uli_len;
uint8_t uli_buf[OGS_GTP2_MAX_ULI_LEN];
uli_len = ogs_gtp2_parse_uli(
&uli, &sess->gtp.user_location_information);
ogs_assert(sess->gtp.user_location_information.len == uli_len);
ogs_assert(sess->gtp.user_location_information.data);
ogs_assert(sess->gtp.user_location_information.len);
memcpy(&uli_buf, sess->gtp.user_location_information.data,
sess->gtp.user_location_information.len);
/* Update Gx ULI Type */
if (uli.flags.tai && uli.flags.e_cgi)
uli_buf[0] =
OGS_DIAM_GX_3GPP_USER_LOCATION_INFO_TYPE_TAI_AND_ECGI;
else if (uli.flags.tai)
uli_buf[0] = OGS_DIAM_GX_3GPP_USER_LOCATION_INFO_TYPE_TAI;
else if (uli.flags.e_cgi)
uli_buf[0] = OGS_DIAM_GX_3GPP_USER_LOCATION_INFO_TYPE_ECGI;
if (uli_buf[0]) {
ret = fd_msg_avp_new(
ogs_diam_gx_3gpp_user_location_info, 0, &avp);
ogs_assert(ret == 0);
val.os.data = (uint8_t *)&uli_buf;
val.os.len = sess->gtp.user_location_information.len;
ret = fd_msg_avp_setvalue(avp, &val);
ogs_assert(ret == 0);
ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp);
ogs_assert(ret == 0);
}
}
/* 3GPP-User-Location-Info, 3GPP TS 29.061 16.4.7.2 22 */
smf_fd_msg_avp_add_3gpp_uli(sess, avpch1);
/* Set 3GPP-MS-Timezone */
if (sess->gtp.ue_timezone.presence &&

View File

@ -466,43 +466,8 @@ static void fill_service_information_ccr(smf_sess_t *sess,
ogs_assert(ret == 0);
}
/* 3GPP-User-Location-Info */
if (sess->gtp.user_location_information.presence) {
ogs_gtp2_uli_t uli;
int16_t uli_len;
uint8_t uli_buf[OGS_GTP2_MAX_ULI_LEN];
uli_len = ogs_gtp2_parse_uli(
&uli, &sess->gtp.user_location_information);
ogs_assert(sess->gtp.user_location_information.len == uli_len);
ogs_assert(sess->gtp.user_location_information.data);
ogs_assert(sess->gtp.user_location_information.len);
memcpy(&uli_buf, sess->gtp.user_location_information.data,
sess->gtp.user_location_information.len);
/* Update Gy ULI Type */
if (uli.flags.tai && uli.flags.e_cgi)
uli_buf[0] =
OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_TAI_AND_ECGI;
else if (uli.flags.tai)
uli_buf[0] = OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_TAI;
else if (uli.flags.e_cgi)
uli_buf[0] = OGS_DIAM_GY_3GPP_USER_LOCATION_INFO_TYPE_ECGI;
if (uli_buf[0]) {
ret = fd_msg_avp_new(
ogs_diam_gy_3gpp_user_location_info, 0, &avpch2);
ogs_assert(ret == 0);
val.os.data = (uint8_t *)&uli_buf;
val.os.len = sess->gtp.user_location_information.len;
ret = fd_msg_avp_setvalue(avpch2, &val);
ogs_assert(ret == 0);
ret = fd_msg_avp_add(avpch1, MSG_BRW_LAST_CHILD, avpch2);
ogs_assert(ret == 0);
}
}
/* 3GPP-User-Location-Info, 3GPP TS 29.061 16.4.7.2 22 */
smf_fd_msg_avp_add_3gpp_uli(sess, avpch1);
if (sess->smf_ue->imeisv_len > 0) {
/* User-Equipment-Info, 3GPP TS 32.299 7.1.17 */