diff --git a/configs/310014.yaml.in b/configs/310014.yaml.in index 475fc9fff..cbcf47791 100644 --- a/configs/310014.yaml.in +++ b/configs/310014.yaml.in @@ -246,3 +246,7 @@ udr: sbi: - addr: 127.0.0.20 port: 7777 + +time: + t3512: + value: 540 # 9 mintues * 60 = 540 seconds diff --git a/configs/csfb.yaml.in b/configs/csfb.yaml.in index 90fe516f7..b28f7af0d 100644 --- a/configs/csfb.yaml.in +++ b/configs/csfb.yaml.in @@ -275,3 +275,7 @@ udr: sbi: - addr: 127.0.0.20 port: 7777 + +time: + t3512: + value: 540 # 9 mintues * 60 = 540 seconds diff --git a/configs/non3gpp.yaml.in b/configs/non3gpp.yaml.in index 3408f8142..abe0757d0 100644 --- a/configs/non3gpp.yaml.in +++ b/configs/non3gpp.yaml.in @@ -244,3 +244,7 @@ udr: sbi: - addr: 127.0.0.20 port: 7777 + +time: + t3512: + value: 540 # 9 mintues * 60 = 540 seconds diff --git a/configs/open5gs/amf.yaml.in b/configs/open5gs/amf.yaml.in index e25e7e0d6..99c36c72f 100644 --- a/configs/open5gs/amf.yaml.in +++ b/configs/open5gs/amf.yaml.in @@ -541,4 +541,13 @@ usrsctp: # o Handover Wait Duration (500ms) # handover: # duration: 500 +# +# o Timers of 5GS mobility/session management +# t3502: +# value: 720 # 12 minutes * 60 = 720 seconds +# t3512: +# value: 3240 # 54 minutes * 60 = 3240 seconds +# time: + t3512: + value: 540 # 9 mintues * 60 = 540 seconds diff --git a/configs/open5gs/mme.yaml.in b/configs/open5gs/mme.yaml.in index 4dfdc09c0..409ee5c4e 100644 --- a/configs/open5gs/mme.yaml.in +++ b/configs/open5gs/mme.yaml.in @@ -429,4 +429,11 @@ usrsctp: # o Handover Wait Duration (500ms) # handover: # duration: 500 +# +# o Timers of EPS mobility/session management +# t3402: +# value: 720 # 12 minutes * 60 = 720 seconds +# t3412: +# value: 3240 # 54 minutes * 60 = 3240 seconds +# time: diff --git a/configs/sample.yaml.in b/configs/sample.yaml.in index 6b679b745..3661d77a1 100644 --- a/configs/sample.yaml.in +++ b/configs/sample.yaml.in @@ -279,3 +279,7 @@ udr: sbi: - addr: 127.0.0.20 port: 7777 + +time: + t3512: + value: 540 # 9 mintues * 60 = 540 seconds diff --git a/configs/slice.yaml.in b/configs/slice.yaml.in index bbb299902..c5b7e0991 100644 --- a/configs/slice.yaml.in +++ b/configs/slice.yaml.in @@ -255,3 +255,7 @@ udr: sbi: - addr: 127.0.0.20 port: 7777 + +time: + t3512: + value: 540 # 9 mintues * 60 = 540 seconds diff --git a/configs/srslte.yaml.in b/configs/srslte.yaml.in index d622da78b..1d6f1871b 100644 --- a/configs/srslte.yaml.in +++ b/configs/srslte.yaml.in @@ -241,3 +241,7 @@ udr: sbi: - addr: 127.0.0.20 port: 7777 + +time: + t3512: + value: 540 # 9 mintues * 60 = 540 seconds diff --git a/configs/volte.yaml.in b/configs/volte.yaml.in index 1fdaa3cc2..39009b7af 100644 --- a/configs/volte.yaml.in +++ b/configs/volte.yaml.in @@ -248,3 +248,7 @@ udr: sbi: - addr: 127.0.0.20 port: 7777 + +time: + t3512: + value: 540 # 9 mintues * 60 = 540 seconds diff --git a/configs/vonr.yaml.in b/configs/vonr.yaml.in index a40fbe18c..fdca4d62d 100644 --- a/configs/vonr.yaml.in +++ b/configs/vonr.yaml.in @@ -256,3 +256,7 @@ udr: sbi: - addr: 127.0.0.20 port: 7777 + +time: + t3512: + value: 540 # 9 mintues * 60 = 540 seconds diff --git a/lib/app/ogs-context.c b/lib/app/ogs-context.c index 884528075..a4338a51d 100644 --- a/lib/app/ogs-context.c +++ b/lib/app/ogs-context.c @@ -635,6 +635,16 @@ int ogs_app_context_parse_config(void) } else ogs_warn("unknown key `%s`", msg_key); } + } else if (!strcmp(time_key, "t3502")) { + /* handle config in amf */ + } else if (!strcmp(time_key, "t3512")) { + /* handle config in amf */ + } else if (!strcmp(time_key, "t3402")) { + /* handle config in mme */ + } else if (!strcmp(time_key, "t3412")) { + /* handle config in mme */ + } else if (!strcmp(time_key, "t3423")) { + /* handle config in mme */ } else ogs_warn("unknown key `%s`", time_key); } diff --git a/lib/nas/common/conv.c b/lib/nas/common/conv.c index 823df0081..5c1c3a5c4 100644 --- a/lib/nas/common/conv.c +++ b/lib/nas/common/conv.c @@ -72,3 +72,121 @@ void *ogs_nas_imeisv_bcd_to_buffer(const char *in, uint8_t *out, int *out_len) return ogs_bcd_to_buffer_reverse_order(in, out, out_len); } + +int ogs_nas_gprs_timer_from_sec( + ogs_nas_gprs_timer_t *gprs_timer, ogs_time_t sec) +{ + ogs_time_t timer_value = sec; + + ogs_assert(gprs_timer); + memset(gprs_timer, 0, sizeof(*gprs_timer)); + + if (timer_value <= 63) { + if (timer_value%2 != 0) { + ogs_error("Not multiples of 2 seconds"); + return OGS_ERROR; + } + gprs_timer->value = timer_value / 2; + } else { + if (timer_value%60 != 0) { + ogs_error("Not multiples of 1 minute"); + return OGS_ERROR; + } + timer_value /= 60; /* multiples of 1 minute */ + if (timer_value <= 31) { + gprs_timer->unit = OGS_NAS_GPRS_TIMER_UNIT_MULTIPLES_OF_1_MM; + gprs_timer->value = timer_value; + } else { + if (timer_value%10 != 0) { + ogs_error("Not multiples of decihours(= 10 minutes)"); + return OGS_ERROR; + } + timer_value /= 10; /* multiples of decihours = 10 minutes */ + if (timer_value <= 31) { + gprs_timer->unit = OGS_NAS_GPRS_TIMER_UNIT_MULTIPLES_OF_DECI_HH; + gprs_timer->value = timer_value; + } else { + ogs_error("Overflow!"); + return OGS_ERROR; + } + } + } + + return OGS_OK; +} + +int ogs_nas_gprs_timer_3_from_sec( + ogs_nas_gprs_timer_t *gprs_timer, ogs_time_t sec) +{ + ogs_time_t timer_value = sec; + + ogs_assert(gprs_timer); + memset(gprs_timer, 0, sizeof(*gprs_timer)); + + if (timer_value <= 63) { + if (timer_value%2 != 0) { + ogs_error("Not multiples of 2 seconds"); + return OGS_ERROR; + } + gprs_timer->unit = OGS_NAS_GPRS_TIMER_3_UNIT_MULTIPLES_OF_2_SS; + gprs_timer->value = timer_value / 2; + } else { + if (timer_value%60 != 0) { + ogs_error("Not multiples of 1 minute"); + return OGS_ERROR; + } + timer_value /= 60; /* multiples of 1 minute */ + if (timer_value <= 31) { + gprs_timer->unit = OGS_NAS_GPRS_TIMER_3_UNIT_MULTIPLES_OF_1_MM; + gprs_timer->value = timer_value; + } else { + if (timer_value%10 != 0) { + ogs_error("Not multiples of decihours(= 10 minutes)"); + return OGS_ERROR; + } + timer_value /= 10; /* multiples of decihours = 10 mintues */ + if (timer_value <= 31) { + gprs_timer->unit = OGS_NAS_GPRS_TIMER_3_UNIT_MULTIPLES_OF_10_MM; + gprs_timer->value = timer_value; + } else { + if (timer_value%6 != 0) { + ogs_error("Not multiples of 1 hour"); + return OGS_ERROR; + } + timer_value /= 6; /* multiples of 1 hour */ + if (timer_value <= 31) { + gprs_timer->unit = + OGS_NAS_GPRS_TIMER_3_UNIT_MULTIPLES_OF_1_HH; + gprs_timer->value = timer_value; + } else { + if (timer_value%10 != 0) { + ogs_error("Not multiples of 10 hours"); + return OGS_ERROR; + } + timer_value /= 10; /* multiples of 10 hours */ + if (timer_value <= 31) { + gprs_timer->unit = + OGS_NAS_GPRS_TIMER_3_UNIT_MULTIPLES_OF_10_HH; + gprs_timer->value = timer_value; + } else { + if (timer_value%32 != 0) { + ogs_error("Not multiples of 10 hours"); + return OGS_ERROR; + } + timer_value /= 32; /* multiples of 320 hours */ + if (timer_value <= 31) { + gprs_timer->unit = + OGS_NAS_GPRS_TIMER_3_UNIT_MULTIPLES_OF_320_HH; + gprs_timer->value = timer_value; + } else { + ogs_error("Overflow!"); + return OGS_ERROR; + } + } + } + } + } + } + + return OGS_OK; +} diff --git a/lib/nas/common/conv.h b/lib/nas/common/conv.h index a6c3ea68e..0a68d3b7c 100644 --- a/lib/nas/common/conv.h +++ b/lib/nas/common/conv.h @@ -34,6 +34,11 @@ void ogs_nas_imeisv_to_bcd( ogs_nas_mobile_identity_imeisv_t *imeisv, uint8_t imeisv_len, char *bcd); void *ogs_nas_imeisv_bcd_to_buffer(const char *in, uint8_t *out, int *out_len); +int ogs_nas_gprs_timer_from_sec( + ogs_nas_gprs_timer_t *gprs_timer, ogs_time_t sec); +int ogs_nas_gprs_timer_3_from_sec( + ogs_nas_gprs_timer_t *gprs_timer, ogs_time_t sec); + #ifdef __cplusplus } #endif diff --git a/lib/nas/common/types.h b/lib/nas/common/types.h index e0ba2044d..c4627bc84 100644 --- a/lib/nas/common/types.h +++ b/lib/nas/common/types.h @@ -239,10 +239,10 @@ ED2(uint8_t spare:6;, /* 9.9.3.16 GPRS timer * See subclause 10.5.7.3 in 3GPP TS 24.008 [13]. * M V 1 or O TV 2 */ -#define OGS_NAS_GRPS_TIMER_UNIT_MULTIPLES_OF_2_SS 0 -#define OGS_NAS_GRPS_TIMER_UNIT_MULTIPLES_OF_1_MM 1 -#define OGS_NAS_GRPS_TIMER_UNIT_MULTIPLES_OF_DECI_HH 2 -#define OGS_NAS_GRPS_TIMER_UNIT_DEACTIVATED 7 +#define OGS_NAS_GPRS_TIMER_UNIT_MULTIPLES_OF_2_SS 0 +#define OGS_NAS_GPRS_TIMER_UNIT_MULTIPLES_OF_1_MM 1 +#define OGS_NAS_GPRS_TIMER_UNIT_MULTIPLES_OF_DECI_HH 2 +#define OGS_NAS_GPRS_TIMER_UNIT_DEACTIVATED 7 typedef struct ogs_nas_gprs_timer_s { ED2(uint8_t unit:3;, uint8_t value:5;) @@ -253,26 +253,24 @@ ED2(uint8_t unit:3;, * O TLV 3 */ typedef struct ogs_nas_gprs_timer_2_s { uint8_t length; -ED2(uint8_t unit:3;, - uint8_t value:5;) + ogs_nas_gprs_timer_t t; } __attribute__ ((packed)) ogs_nas_gprs_timer_2_t; /* 9.9.3.16B GPRS timer 3 * See subclause 10.5.7.4a in 3GPP TS 24.008 [13]. * O TLV 3 */ -#define OGS_NAS_GRPS_TIMER_3_UNIT_MULTIPLES_OF_10_MM 0 -#define OGS_NAS_GRPS_TIMER_3_UNIT_MULTIPLES_OF_1_HH 1 -#define OGS_NAS_GRPS_TIMER_3_UNIT_MULTIPLES_OF_10_HH 2 -#define OGS_NAS_GRPS_TIMER_3_UNIT_MULTIPLES_OF_2_SS 3 -#define OGS_NAS_GRPS_TIMER_3_UNIT_MULTIPLES_OF_30_SS 4 -#define OGS_NAS_GRPS_TIMER_3_UNIT_MULTIPLES_OF_1_MM 5 -#define OGS_NAS_GRPS_TIMER_3_UNIT_MULTIPLES_OF_320_HH 6 -#define OGS_NAS_GRPS_TIMER_3_UNIT_DEACTIVATED 7 +#define OGS_NAS_GPRS_TIMER_3_UNIT_MULTIPLES_OF_10_MM 0 +#define OGS_NAS_GPRS_TIMER_3_UNIT_MULTIPLES_OF_1_HH 1 +#define OGS_NAS_GPRS_TIMER_3_UNIT_MULTIPLES_OF_10_HH 2 +#define OGS_NAS_GPRS_TIMER_3_UNIT_MULTIPLES_OF_2_SS 3 +#define OGS_NAS_GPRS_TIMER_3_UNIT_MULTIPLES_OF_30_SS 4 +#define OGS_NAS_GPRS_TIMER_3_UNIT_MULTIPLES_OF_1_MM 5 +#define OGS_NAS_GPRS_TIMER_3_UNIT_MULTIPLES_OF_320_HH 6 +#define OGS_NAS_GPRS_TIMER_3_UNIT_DEACTIVATED 7 typedef struct ogs_nas_gprs_timer_3_s { uint8_t length; -ED2(uint8_t unit:3;, - uint8_t value:5;) + ogs_nas_gprs_timer_t t; } __attribute__ ((packed)) ogs_nas_gprs_timer_3_t; /* 9.9.3.18 IMEISV request diff --git a/src/amf/context.c b/src/amf/context.c index e931dc955..01eaba0d6 100644 --- a/src/amf/context.c +++ b/src/amf/context.c @@ -123,6 +123,8 @@ static int amf_context_prepare(void) static int amf_context_validation(void) { + ogs_nas_gprs_timer_t gprs_timer; + if (ogs_list_first(&self.ngap_list) == NULL && ogs_list_first(&self.ngap_list6) == NULL) { ogs_error("No amf.ngap in '%s'", ogs_app()->file); @@ -171,6 +173,16 @@ static int amf_context_validation(void) ogs_app()->file); return OGS_ERROR; } + if (ogs_nas_gprs_timer_from_sec(&gprs_timer, self.time.t3502.value) != + OGS_OK) { + ogs_error("Not support GPRS Timer 2 [%d]", (int)self.time.t3502.value); + return OGS_ERROR; + } + if (ogs_nas_gprs_timer_3_from_sec(&gprs_timer, self.time.t3512.value) != + OGS_OK) { + ogs_error("Not support GPRS Timer 3 [%d]", (int)self.time.t3512.value); + return OGS_ERROR; + } return OGS_OK; } @@ -830,6 +842,55 @@ int amf_context_parse_config(void) } else ogs_warn("unknown key `%s`", amf_key); } + } else if (!strcmp(root_key, "time")) { + ogs_yaml_iter_t time_iter; + ogs_yaml_iter_recurse(&root_iter, &time_iter); + while (ogs_yaml_iter_next(&time_iter)) { + const char *time_key = ogs_yaml_iter_key(&time_iter); + ogs_assert(time_key); + if (!strcmp(time_key, "t3502")) { + ogs_yaml_iter_t t3502_iter; + ogs_yaml_iter_recurse(&time_iter, &t3502_iter); + + while (ogs_yaml_iter_next(&t3502_iter)) { + const char *t3502_key = + ogs_yaml_iter_key(&t3502_iter); + ogs_assert(t3502_key); + + if (!strcmp(t3502_key, "value")) { + const char *v = ogs_yaml_iter_value(&t3502_iter); + if (v) + self.time.t3502.value = atoll(v); + } else + ogs_warn("unknown key `%s`", t3502_key); + } + } else if (!strcmp(time_key, "t3512")) { + ogs_yaml_iter_t t3512_iter; + ogs_yaml_iter_recurse(&time_iter, &t3512_iter); + + while (ogs_yaml_iter_next(&t3512_iter)) { + const char *t3512_key = + ogs_yaml_iter_key(&t3512_iter); + ogs_assert(t3512_key); + + if (!strcmp(t3512_key, "value")) { + const char *v = ogs_yaml_iter_value(&t3512_iter); + if (v) + self.time.t3512.value = atoll(v); + } else + ogs_warn("unknown key `%s`", t3512_key); + } + } else if (!strcmp(time_key, "nf_instance")) { + /* handle config in app library */ + } else if (!strcmp(time_key, "subscription")) { + /* handle config in app library */ + } else if (!strcmp(time_key, "message")) { + /* handle config in app library */ + } else if (!strcmp(time_key, "handover")) { + /* handle config in app library */ + } else + ogs_warn("unknown key `%s`", time_key); + } } } diff --git a/src/amf/context.h b/src/amf/context.h index a87fed43e..2317e17fd 100644 --- a/src/amf/context.h +++ b/src/amf/context.h @@ -109,6 +109,12 @@ typedef struct amf_context_s { ogs_list_t ngap_list; /* AMF NGAP IPv4 Server List */ ogs_list_t ngap_list6; /* AMF NGAP IPv6 Server List */ + struct { + struct { + ogs_time_t value; /* Timer Value(Seconds) */ + } t3502, t3512; + } time; + } amf_context_t; typedef struct amf_gnb_s { diff --git a/src/amf/gmm-build.c b/src/amf/gmm-build.c index 987dc9082..f38bc71c4 100644 --- a/src/amf/gmm-build.c +++ b/src/amf/gmm-build.c @@ -29,7 +29,7 @@ static uint16_t get_pdu_session_reactivation_result(amf_ue_t *amf_ue); ogs_pkbuf_t *gmm_build_registration_accept(amf_ue_t *amf_ue) { - int served_tai_index = 0; + int rv, served_tai_index = 0; ogs_pkbuf_t *pkbuf = NULL; ogs_nas_5gs_message_t message; @@ -50,6 +50,7 @@ ogs_pkbuf_t *gmm_build_registration_accept(amf_ue_t *amf_ue) ogs_nas_pdu_session_reactivation_result_t *pdu_session_reactivation_result = ®istration_accept->pdu_session_reactivation_result; ogs_nas_gprs_timer_3_t *t3512_value = ®istration_accept->t3512_value; + ogs_nas_gprs_timer_2_t *t3502_value = ®istration_accept->t3502_value; ogs_assert(amf_ue); @@ -127,18 +128,24 @@ ogs_pkbuf_t *gmm_build_registration_accept(amf_ue_t *amf_ue) network_feature_support->ims_vops_3gpp = 1; /* Set T3512 */ - registration_accept->presencemask |= OGS_NAS_5GS_REGISTRATION_ACCEPT_T3512_VALUE_PRESENT; - t3512_value->length = 1; - t3512_value->unit = OGS_NAS_GRPS_TIMER_3_UNIT_MULTIPLES_OF_1_HH; - t3512_value->value = 9; + if (amf_self()->time.t3512.value) { + rv = ogs_nas_gprs_timer_3_from_sec( + &t3512_value->t, amf_self()->time.t3512.value); + ogs_assert(rv == OGS_OK); + registration_accept->presencemask |= + OGS_NAS_5GS_REGISTRATION_ACCEPT_T3512_VALUE_PRESENT; + t3512_value->length = 1; + } -#if 0 /* Set T3502 */ - registration_accept->presencemask |= OGS_NAS_5GS_REGISTRATION_ACCEPT_T3502_VALUE_PRESENT; - registration_accept->t3502_value.length = 1; - registration_accept->t3502_value.unit = OGS_NAS_GRPS_TIMER_UNIT_MULTIPLES_OF_1_MM; - registration_accept->t3502_value.value = 12; -#endif + if (amf_self()->time.t3502.value) { + rv = ogs_nas_gprs_timer_from_sec( + &t3502_value->t, amf_self()->time.t3502.value); + ogs_assert(rv == OGS_OK); + registration_accept->presencemask |= + OGS_NAS_5GS_REGISTRATION_ACCEPT_T3502_VALUE_PRESENT; + t3502_value->length = 1; + } if (amf_ue->nas.present.pdu_session_status) { registration_accept->presencemask |= @@ -650,9 +657,9 @@ ogs_pkbuf_t *gmm_build_dl_nas_transport(amf_sess_t *sess, dl_nas_transport->presencemask |= OGS_NAS_5GS_DL_NAS_TRANSPORT_BACK_OFF_TIMER_VALUE_PRESENT; back_off_timer_value->length = 1; - back_off_timer_value->unit = - OGS_NAS_GRPS_TIMER_3_UNIT_MULTIPLES_OF_2_SS; - back_off_timer_value->value = backoff_time / 2; + back_off_timer_value->t.unit = + OGS_NAS_GPRS_TIMER_3_UNIT_MULTIPLES_OF_2_SS; + back_off_timer_value->t.value = backoff_time / 2; } gmmbuf = nas_5gs_security_encode(amf_ue, &message); diff --git a/src/mme/emm-build.c b/src/mme/emm-build.c index 1b7db9a3b..69e9c3a11 100644 --- a/src/mme/emm-build.c +++ b/src/mme/emm-build.c @@ -33,7 +33,9 @@ ogs_pkbuf_t *emm_build_attach_accept( ogs_nas_eps_attach_result_t *eps_attach_result = &attach_accept->eps_attach_result; ogs_nas_gprs_timer_t *t3412_value = &attach_accept->t3412_value; - int served_tai_index = 0; + ogs_nas_gprs_timer_t *t3402_value = &attach_accept->t3402_value; + ogs_nas_gprs_timer_t *t3423_value = &attach_accept->t3423_value; + int rv, served_tai_index = 0; ogs_nas_eps_mobile_identity_t *nas_guti = &attach_accept->guti; ogs_nas_eps_network_feature_support_t *eps_network_feature_support = &attach_accept->eps_network_feature_support; @@ -137,9 +139,15 @@ ogs_pkbuf_t *emm_build_attach_accept( } /* Set T3412 */ - t3412_value->unit = OGS_NAS_GRPS_TIMER_UNIT_MULTIPLES_OF_DECI_HH; + t3412_value->unit = OGS_NAS_GPRS_TIMER_UNIT_MULTIPLES_OF_DECI_HH; t3412_value->value = 9; + if (mme_self()->time.t3412.value) { + rv = ogs_nas_gprs_timer_from_sec( + t3412_value, mme_self()->time.t3412.value); + ogs_assert(rv == OGS_OK); + } + ogs_debug(" TAI[PLMN_ID:%06x,TAC:%d]", ogs_plmn_id_hexdump(&mme_ue->tai.plmn_id), mme_ue->tai.tac); @@ -174,19 +182,23 @@ ogs_pkbuf_t *emm_build_attach_accept( nas_guti->guti.m_tmsi = mme_ue->next.guti.m_tmsi; } -#if 0 /* Need not to include T3402 */ /* Set T3402 */ - attach_accept->presencemask |= OGS_NAS_EPS_ATTACH_ACCEPT_T3402_VALUE_PRESENT; - attach_accept->t3402_value.unit = OGS_NAS_GRPS_TIMER_UNIT_MULTIPLES_OF_1_MM; - attach_accept->t3402_value.value = 12; -#endif + if (mme_self()->time.t3402.value) { + rv = ogs_nas_gprs_timer_from_sec( + t3402_value, mme_self()->time.t3402.value); + ogs_assert(rv == OGS_OK); + attach_accept->presencemask |= + OGS_NAS_EPS_ATTACH_ACCEPT_T3402_VALUE_PRESENT; + } /* Set T3423 */ - attach_accept->presencemask |= - OGS_NAS_EPS_ATTACH_ACCEPT_T3423_VALUE_PRESENT; - attach_accept->t3423_value.unit = - OGS_NAS_GRPS_TIMER_UNIT_MULTIPLES_OF_DECI_HH; - attach_accept->t3423_value.value = 9; + if (mme_self()->time.t3423.value) { + rv = ogs_nas_gprs_timer_from_sec( + t3423_value, mme_self()->time.t3423.value); + ogs_assert(rv == OGS_OK); + attach_accept->presencemask |= + OGS_NAS_EPS_ATTACH_ACCEPT_T3423_VALUE_PRESENT; + } attach_accept->presencemask |= OGS_NAS_EPS_ATTACH_ACCEPT_EPS_NETWORK_FEATURE_SUPPORT_PRESENT; @@ -480,7 +492,10 @@ ogs_pkbuf_t *emm_build_tau_accept(mme_ue_t *mme_ue) ogs_nas_eps_tracking_area_update_accept_t *tau_accept = &message.emm.tracking_area_update_accept; ogs_nas_eps_mobile_identity_t *nas_guti = &tau_accept->guti; - int served_tai_index = 0; + ogs_nas_gprs_timer_t *t3412_value = &tau_accept->t3412_value; + ogs_nas_gprs_timer_t *t3402_value = &tau_accept->t3402_value; + ogs_nas_gprs_timer_t *t3423_value = &tau_accept->t3423_value; + int rv, served_tai_index = 0; mme_sess_t *sess = NULL; @@ -505,11 +520,13 @@ ogs_pkbuf_t *emm_build_tau_accept(mme_ue_t *mme_ue) OGS_NAS_EPS_UPDATE_RESULT_TA_UPDATED; } - /* Set T3412 */ - tau_accept->presencemask |= - OGS_NAS_EPS_TRACKING_AREA_UPDATE_ACCEPT_T3412_VALUE_PRESENT ; - tau_accept->t3412_value.unit = OGS_NAS_GRPS_TIMER_UNIT_MULTIPLES_OF_DECI_HH; - tau_accept->t3412_value.value = 9; + if (mme_self()->time.t3412.value) { + rv = ogs_nas_gprs_timer_from_sec( + t3412_value, mme_self()->time.t3412.value); + ogs_assert(rv == OGS_OK); + tau_accept->presencemask |= + OGS_NAS_EPS_TRACKING_AREA_UPDATE_ACCEPT_T3412_VALUE_PRESENT ; + } if (mme_ue->next.m_tmsi) { tau_accept->presencemask |= @@ -575,19 +592,23 @@ ogs_pkbuf_t *emm_build_tau_accept(mme_ue_t *mme_ue) sess = mme_sess_next(sess); } -#if 0 /* Need not to include T3402 */ /* Set T3402 */ - tau_accept->presencemask |= - OGS_NAS_EPS_TRACKING_AREA_UPDATE_ACCEPT_T3402_VALUE_PRESENT; - tau_accept->t3402_value.unit = OGS_NAS_GRPS_TIMER_UNIT_MULTIPLES_OF_1_MM; - tau_accept->t3402_value.value = 12; -#endif + if (mme_self()->time.t3402.value) { + rv = ogs_nas_gprs_timer_from_sec( + t3402_value, mme_self()->time.t3402.value); + ogs_assert(rv == OGS_OK); + tau_accept->presencemask |= + OGS_NAS_EPS_TRACKING_AREA_UPDATE_ACCEPT_T3402_VALUE_PRESENT; + } /* Set T3423 */ - tau_accept->presencemask |= - OGS_NAS_EPS_TRACKING_AREA_UPDATE_ACCEPT_T3423_VALUE_PRESENT; - tau_accept->t3423_value.unit = OGS_NAS_GRPS_TIMER_UNIT_MULTIPLES_OF_DECI_HH; - tau_accept->t3423_value.value = 9; + if (mme_self()->time.t3423.value) { + rv = ogs_nas_gprs_timer_from_sec( + t3423_value, mme_self()->time.t3423.value); + ogs_assert(rv == OGS_OK); + tau_accept->presencemask |= + OGS_NAS_EPS_TRACKING_AREA_UPDATE_ACCEPT_T3423_VALUE_PRESENT; + } /* Set EPS network feature support */ tau_accept->presencemask |= diff --git a/src/mme/mme-context.c b/src/mme/mme-context.c index 638170923..090d5bcda 100644 --- a/src/mme/mme-context.c +++ b/src/mme/mme-context.c @@ -178,6 +178,8 @@ static int mme_context_prepare(void) static int mme_context_validation(void) { + ogs_nas_gprs_timer_t gprs_timer; + if (self.diam_conf_path == NULL && (self.diam_config->cnf_diamid == NULL || self.diam_config->cnf_diamrlm == NULL || @@ -249,6 +251,21 @@ static int mme_context_validation(void) ogs_app()->file); return OGS_ERROR; } + if (ogs_nas_gprs_timer_from_sec(&gprs_timer, self.time.t3402.value) != + OGS_OK) { + ogs_error("Not support GPRS Timer [%d]", (int)self.time.t3402.value); + return OGS_ERROR; + } + if (ogs_nas_gprs_timer_from_sec(&gprs_timer, self.time.t3412.value) != + OGS_OK) { + ogs_error("Not support GPRS Timer [%d]", (int)self.time.t3412.value); + return OGS_ERROR; + } + if (ogs_nas_gprs_timer_from_sec(&gprs_timer, self.time.t3423.value) != + OGS_OK) { + ogs_error("Not support GPRS Timer [%d]", (int)self.time.t3423.value); + return OGS_ERROR; + } return OGS_OK; } @@ -1544,6 +1561,73 @@ int mme_context_parse_config() YAML_SEQUENCE_NODE); } } + } else if (!strcmp(root_key, "time")) { + ogs_yaml_iter_t time_iter; + ogs_yaml_iter_recurse(&root_iter, &time_iter); + while (ogs_yaml_iter_next(&time_iter)) { + const char *time_key = ogs_yaml_iter_key(&time_iter); + ogs_assert(time_key); + if (!strcmp(time_key, "t3402")) { + ogs_yaml_iter_t t3402_iter; + ogs_yaml_iter_recurse(&time_iter, &t3402_iter); + + while (ogs_yaml_iter_next(&t3402_iter)) { + const char *t3402_key = + ogs_yaml_iter_key(&t3402_iter); + ogs_assert(t3402_key); + + if (!strcmp(t3402_key, "value")) { + const char *v = ogs_yaml_iter_value(&t3402_iter); + if (v) + self.time.t3402.value = atoll(v); + } else + ogs_warn("unknown key `%s`", t3402_key); + } + } else if (!strcmp(time_key, "t3412")) { + ogs_yaml_iter_t t3412_iter; + ogs_yaml_iter_recurse(&time_iter, &t3412_iter); + + while (ogs_yaml_iter_next(&t3412_iter)) { + const char *t3412_key = + ogs_yaml_iter_key(&t3412_iter); + ogs_assert(t3412_key); + + if (!strcmp(t3412_key, "value")) { + const char *v = ogs_yaml_iter_value(&t3412_iter); + if (v) + self.time.t3412.value = atoll(v); + } else + ogs_warn("unknown key `%s`", t3412_key); + } + } else if (!strcmp(time_key, "t3423")) { + ogs_yaml_iter_t t3423_iter; + ogs_yaml_iter_recurse(&time_iter, &t3423_iter); + + while (ogs_yaml_iter_next(&t3423_iter)) { + const char *t3423_key = + ogs_yaml_iter_key(&t3423_iter); + ogs_assert(t3423_key); + + if (!strcmp(t3423_key, "value")) { + const char *v = ogs_yaml_iter_value(&t3423_iter); + if (v) + self.time.t3423.value = atoll(v); + } else + ogs_warn("unknown key `%s`", t3423_key); + } + } else if (!strcmp(time_key, "t3512")) { + /* handle config in amf */ + } else if (!strcmp(time_key, "nf_instance")) { + /* handle config in app library */ + } else if (!strcmp(time_key, "subscription")) { + /* handle config in app library */ + } else if (!strcmp(time_key, "message")) { + /* handle config in app library */ + } else if (!strcmp(time_key, "handover")) { + /* handle config in app library */ + } else + ogs_warn("unknown key `%s`", time_key); + } } } diff --git a/src/mme/mme-context.h b/src/mme/mme-context.h index 58f1cdfd7..55205e34b 100644 --- a/src/mme/mme-context.h +++ b/src/mme/mme-context.h @@ -146,6 +146,11 @@ typedef struct mme_context_s { ogs_hash_t *imsi_ue_hash; /* hash table (IMSI : MME_UE) */ ogs_hash_t *guti_ue_hash; /* hash table (GUTI : MME_UE) */ + struct { + struct { + ogs_time_t value; /* Timer Value(Seconds) */ + } t3402, t3412, t3423; + } time; } mme_context_t; typedef struct mme_sgw_s { diff --git a/tests/unit/nas-message-test.c b/tests/unit/nas-message-test.c index 38fc48897..ac992b119 100644 --- a/tests/unit/nas-message-test.c +++ b/tests/unit/nas-message-test.c @@ -81,7 +81,7 @@ static void ogs_nas_eps_message_test2(abts_case *tc, void *data) attach_accept->eps_attach_result.result = OGS_NAS_ATTACH_RESULT_COMBINED_EPS_IMSI_ATTACH; attach_accept->t3412_value.unit = - OGS_NAS_GRPS_TIMER_UNIT_MULTIPLES_OF_1_MM; + OGS_NAS_GPRS_TIMER_UNIT_MULTIPLES_OF_1_MM; attach_accept->t3412_value.value = 3; memset(&tai0_list, 0, sizeof(ogs_eps_tai0_list_t)); @@ -327,6 +327,158 @@ static void ogs_nas_eps_message_test8(abts_case *tc, void *data) ogs_pkbuf_free(pkbuf); } +static void ogs_nas_eps_message_test9(abts_case *tc, void *data) +{ + ogs_nas_gprs_timer_t gprs_timer; + int rv; + + ogs_log_install_domain(&__ogs_nas_domain, "nas", OGS_LOG_FATAL); + + rv = ogs_nas_gprs_timer_from_sec(&gprs_timer, 1); + ABTS_INT_EQUAL(tc, OGS_ERROR, rv); + rv = ogs_nas_gprs_timer_from_sec(&gprs_timer, 2); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + ABTS_INT_EQUAL(tc, OGS_NAS_GPRS_TIMER_UNIT_MULTIPLES_OF_2_SS, + gprs_timer.unit); + ABTS_INT_EQUAL(tc, 1, gprs_timer.value); + rv = ogs_nas_gprs_timer_from_sec(&gprs_timer, 3); + ABTS_INT_EQUAL(tc, OGS_ERROR, rv); + rv = ogs_nas_gprs_timer_from_sec(&gprs_timer, 4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + ABTS_INT_EQUAL(tc, OGS_NAS_GPRS_TIMER_UNIT_MULTIPLES_OF_2_SS, + gprs_timer.unit); + ABTS_INT_EQUAL(tc, 2, gprs_timer.value); + rv = ogs_nas_gprs_timer_from_sec(&gprs_timer, 63); + ABTS_INT_EQUAL(tc, OGS_ERROR, rv); + rv = ogs_nas_gprs_timer_from_sec(&gprs_timer, 64); + ABTS_INT_EQUAL(tc, OGS_ERROR, rv); + rv = ogs_nas_gprs_timer_from_sec(&gprs_timer, 60*2-1); + ABTS_INT_EQUAL(tc, OGS_ERROR, rv); + rv = ogs_nas_gprs_timer_from_sec(&gprs_timer, 60*2); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + ABTS_INT_EQUAL(tc, OGS_NAS_GPRS_TIMER_UNIT_MULTIPLES_OF_1_MM, + gprs_timer.unit); + ABTS_INT_EQUAL(tc, 2, gprs_timer.value); + rv = ogs_nas_gprs_timer_from_sec(&gprs_timer, 60*2+1); + ABTS_INT_EQUAL(tc, OGS_ERROR, rv); + rv = ogs_nas_gprs_timer_from_sec(&gprs_timer, 60*30); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + ABTS_INT_EQUAL(tc, OGS_NAS_GPRS_TIMER_UNIT_MULTIPLES_OF_1_MM, + gprs_timer.unit); + ABTS_INT_EQUAL(tc, 30, gprs_timer.value); + rv = ogs_nas_gprs_timer_from_sec(&gprs_timer, 60*31); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + ABTS_INT_EQUAL(tc, OGS_NAS_GPRS_TIMER_UNIT_MULTIPLES_OF_1_MM, + gprs_timer.unit); + ABTS_INT_EQUAL(tc, 31, gprs_timer.value); + rv = ogs_nas_gprs_timer_from_sec(&gprs_timer, 60*32); + ABTS_INT_EQUAL(tc, OGS_ERROR, rv); + rv = ogs_nas_gprs_timer_from_sec(&gprs_timer, 60*10*4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + ABTS_INT_EQUAL(tc, OGS_NAS_GPRS_TIMER_UNIT_MULTIPLES_OF_DECI_HH, + gprs_timer.unit); + ABTS_INT_EQUAL(tc, 4, gprs_timer.value); + rv = ogs_nas_gprs_timer_from_sec(&gprs_timer, 60*10*4+1); + ABTS_INT_EQUAL(tc, OGS_ERROR, rv); + rv = ogs_nas_gprs_timer_from_sec(&gprs_timer, 60*10*31); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + ABTS_INT_EQUAL(tc, OGS_NAS_GPRS_TIMER_UNIT_MULTIPLES_OF_DECI_HH, + gprs_timer.unit); + ABTS_INT_EQUAL(tc, 31, gprs_timer.value); + rv = ogs_nas_gprs_timer_from_sec(&gprs_timer, 60*10*32); + ABTS_INT_EQUAL(tc, OGS_ERROR, rv); + + rv = ogs_nas_gprs_timer_3_from_sec(&gprs_timer, 1); + ABTS_INT_EQUAL(tc, OGS_ERROR, rv); + rv = ogs_nas_gprs_timer_3_from_sec(&gprs_timer, 2); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + ABTS_INT_EQUAL(tc, OGS_NAS_GPRS_TIMER_3_UNIT_MULTIPLES_OF_2_SS, + gprs_timer.unit); + ABTS_INT_EQUAL(tc, 1, gprs_timer.value); + rv = ogs_nas_gprs_timer_3_from_sec(&gprs_timer, 3); + ABTS_INT_EQUAL(tc, OGS_ERROR, rv); + rv = ogs_nas_gprs_timer_3_from_sec(&gprs_timer, 4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + ABTS_INT_EQUAL(tc, OGS_NAS_GPRS_TIMER_3_UNIT_MULTIPLES_OF_2_SS, + gprs_timer.unit); + ABTS_INT_EQUAL(tc, 2, gprs_timer.value); + rv = ogs_nas_gprs_timer_3_from_sec(&gprs_timer, 63); + ABTS_INT_EQUAL(tc, OGS_ERROR, rv); + rv = ogs_nas_gprs_timer_3_from_sec(&gprs_timer, 64); + ABTS_INT_EQUAL(tc, OGS_ERROR, rv); + rv = ogs_nas_gprs_timer_3_from_sec(&gprs_timer, 60*2-1); + ABTS_INT_EQUAL(tc, OGS_ERROR, rv); + rv = ogs_nas_gprs_timer_3_from_sec(&gprs_timer, 60*2); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + ABTS_INT_EQUAL(tc, OGS_NAS_GPRS_TIMER_3_UNIT_MULTIPLES_OF_1_MM, + gprs_timer.unit); + ABTS_INT_EQUAL(tc, 2, gprs_timer.value); + rv = ogs_nas_gprs_timer_3_from_sec(&gprs_timer, 60*2+1); + ABTS_INT_EQUAL(tc, OGS_ERROR, rv); + rv = ogs_nas_gprs_timer_3_from_sec(&gprs_timer, 60*30); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + ABTS_INT_EQUAL(tc, OGS_NAS_GPRS_TIMER_3_UNIT_MULTIPLES_OF_1_MM, + gprs_timer.unit); + ABTS_INT_EQUAL(tc, 30, gprs_timer.value); + rv = ogs_nas_gprs_timer_3_from_sec(&gprs_timer, 60*31); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + ABTS_INT_EQUAL(tc, OGS_NAS_GPRS_TIMER_3_UNIT_MULTIPLES_OF_1_MM, + gprs_timer.unit); + ABTS_INT_EQUAL(tc, 31, gprs_timer.value); + rv = ogs_nas_gprs_timer_3_from_sec(&gprs_timer, 60*32); + ABTS_INT_EQUAL(tc, OGS_ERROR, rv); + rv = ogs_nas_gprs_timer_3_from_sec(&gprs_timer, 60*10*4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + ABTS_INT_EQUAL(tc, OGS_NAS_GPRS_TIMER_3_UNIT_MULTIPLES_OF_10_MM, + gprs_timer.unit); + ABTS_INT_EQUAL(tc, 4, gprs_timer.value); + rv = ogs_nas_gprs_timer_3_from_sec(&gprs_timer, 60*10*4+1); + ABTS_INT_EQUAL(tc, OGS_ERROR, rv); + rv = ogs_nas_gprs_timer_3_from_sec(&gprs_timer, 60*10*31); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + ABTS_INT_EQUAL(tc, OGS_NAS_GPRS_TIMER_3_UNIT_MULTIPLES_OF_10_MM, + gprs_timer.unit); + ABTS_INT_EQUAL(tc, 31, gprs_timer.value); + rv = ogs_nas_gprs_timer_3_from_sec(&gprs_timer, 60*10*32); + ABTS_INT_EQUAL(tc, OGS_ERROR, rv); + rv = ogs_nas_gprs_timer_3_from_sec(&gprs_timer, 60*10*36); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + ABTS_INT_EQUAL(tc, OGS_NAS_GPRS_TIMER_3_UNIT_MULTIPLES_OF_1_HH, + gprs_timer.unit); + ABTS_INT_EQUAL(tc, 6, gprs_timer.value); + rv = ogs_nas_gprs_timer_3_from_sec(&gprs_timer, 60*60*31); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + ABTS_INT_EQUAL(tc, OGS_NAS_GPRS_TIMER_3_UNIT_MULTIPLES_OF_1_HH, + gprs_timer.unit); + ABTS_INT_EQUAL(tc, 31, gprs_timer.value); + rv = ogs_nas_gprs_timer_3_from_sec(&gprs_timer, 60*60*32); + ABTS_INT_EQUAL(tc, OGS_ERROR, rv); + rv = ogs_nas_gprs_timer_3_from_sec(&gprs_timer, 60*60*40); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + ABTS_INT_EQUAL(tc, OGS_NAS_GPRS_TIMER_3_UNIT_MULTIPLES_OF_10_HH, + gprs_timer.unit); + ABTS_INT_EQUAL(tc, 4, gprs_timer.value); + rv = ogs_nas_gprs_timer_3_from_sec(&gprs_timer, 60*60*10*31); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + ABTS_INT_EQUAL(tc, OGS_NAS_GPRS_TIMER_3_UNIT_MULTIPLES_OF_10_HH, + gprs_timer.unit); + ABTS_INT_EQUAL(tc, 31, gprs_timer.value); + rv = ogs_nas_gprs_timer_3_from_sec(&gprs_timer, 60*60*10*32); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + ABTS_INT_EQUAL(tc, OGS_NAS_GPRS_TIMER_3_UNIT_MULTIPLES_OF_320_HH, + gprs_timer.unit); + ABTS_INT_EQUAL(tc, 1, gprs_timer.value); + rv = ogs_nas_gprs_timer_3_from_sec(&gprs_timer, 60*60*10*32*31); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + ABTS_INT_EQUAL(tc, OGS_NAS_GPRS_TIMER_3_UNIT_MULTIPLES_OF_320_HH, + gprs_timer.unit); + ABTS_INT_EQUAL(tc, 31, gprs_timer.value); + rv = ogs_nas_gprs_timer_3_from_sec(&gprs_timer, 60*60*10*32*32); + ABTS_INT_EQUAL(tc, OGS_ERROR, rv); + + ogs_log_install_domain(&__ogs_nas_domain, "nas", OGS_LOG_ERROR); +} + abts_suite *test_nas_message(abts_suite *suite) { suite = ADD_SUITE(suite) @@ -343,6 +495,7 @@ abts_suite *test_nas_message(abts_suite *suite) abts_run_test(suite, ogs_nas_eps_message_test6, NULL); abts_run_test(suite, ogs_nas_eps_message_test7, NULL); abts_run_test(suite, ogs_nas_eps_message_test8, NULL); + abts_run_test(suite, ogs_nas_eps_message_test9, NULL); return suite; }