From 0fb8279e3665d722d750b8e154fe34ad19905f76 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Sun, 14 Nov 2021 21:07:56 +0900 Subject: [PATCH] VoNR added but not tested! --- configs/meson.build | 1 - docs/_pages/about.md | 4 +- lib/core/ogs-3gpp-types.c | 276 ++ lib/core/ogs-3gpp-types.h | 26 + lib/dbi/session.c | 2 +- lib/gtp/types.c | 6 +- lib/nas/5gs/types.c | 311 +- lib/nas/5gs/types.h | 6 + lib/nas/common/types.c | 61 + lib/nas/common/types.h | 1 + lib/pfcp/xact.h | 32 +- lib/sbi/conv.c | 158 + lib/sbi/conv.h | 6 + lib/sbi/message.c | 82 +- lib/sbi/message.h | 8 +- lib/sbi/ogs-sbi.h | 2 + .../openapi/model/acceptable_service_info.c | 13 +- lib/sbi/openapi/model/am_policy_data.c | 13 +- .../model/app_session_context_req_data.c | 13 +- .../model/app_session_context_update_data.c | 13 +- lib/sbi/openapi/model/area_scope.c | 13 +- lib/sbi/openapi/model/cag_data.c | 13 +- lib/sbi/openapi/model/cag_data_1.c | 13 +- lib/sbi/openapi/model/eap_session.c | 13 +- lib/sbi/openapi/model/ee_subscription.c | 13 +- lib/sbi/openapi/model/eps_interworking_info.c | 13 +- lib/sbi/openapi/model/inline_response_200.c | 13 +- lib/sbi/openapi/model/iptv_config_data.c | 13 +- .../openapi/model/iptv_config_data_patch.c | 13 +- lib/sbi/openapi/model/media_component.c | 13 +- lib/sbi/openapi/model/media_component_rm.c | 13 +- lib/sbi/openapi/model/nf_profile.c | 169 +- lib/sbi/openapi/model/nrf_info.c | 208 +- lib/sbi/openapi/model/nssai.c | 13 +- lib/sbi/openapi/model/nssai_1.c | 13 +- lib/sbi/openapi/model/policy_association.c | 13 +- .../model/policy_association_update_request.c | 13 +- .../model/policy_data_change_notification.c | 13 +- lib/sbi/openapi/model/policy_update.c | 13 +- .../session_management_subscription_data.c | 39 +- .../session_management_subscription_data_1.c | 39 +- lib/sbi/openapi/model/shared_data.c | 39 +- lib/sbi/openapi/model/sm_policy_data.c | 39 +- lib/sbi/openapi/model/sm_policy_data_patch.c | 26 +- lib/sbi/openapi/model/sm_policy_decision.c | 130 +- lib/sbi/openapi/model/sm_policy_dnn_data.c | 26 +- lib/sbi/openapi/model/sm_policy_snssai_data.c | 13 +- .../model/sm_policy_snssai_data_patch.c | 13 +- .../model/sm_policy_update_context_data.c | 13 +- lib/sbi/openapi/model/smf_selection_data.c | 13 +- .../model/smf_selection_subscription_data.c | 13 +- .../model/smf_selection_subscription_data_1.c | 13 +- lib/sbi/openapi/model/spatial_validity.c | 13 +- lib/sbi/openapi/model/spatial_validity_rm.c | 13 +- .../openapi/model/ue_context_in_smf_data.c | 13 +- .../openapi/model/ue_context_in_smf_data_1.c | 13 +- lib/sbi/openapi/model/ue_policy_set.c | 39 +- lib/sbi/openapi/model/ue_policy_set_patch.c | 13 +- lib/sbi/openapi/model/usage_mon_data.c | 13 +- lib/sbi/openapi/model/usage_mon_data_limit.c | 13 +- .../templates/model-body.mustache | 13 +- lib/sbi/support/20210629/openapitools.json | 7 + src/amf/context.c | 31 + src/amf/context.h | 78 +- src/amf/gmm-handler.c | 41 +- src/amf/gmm-handler.h | 8 - src/amf/gmm-sm.c | 8 +- src/amf/namf-handler.c | 69 +- src/amf/nas-path.c | 31 + src/amf/nas-path.h | 3 + src/amf/ngap-handler.c | 66 +- src/amf/nsmf-handler.c | 37 + src/pcf/context.c | 87 +- src/pcf/context.h | 27 +- src/pcf/event.h | 2 + src/pcf/meson.build | 1 + src/pcf/naf-build.c | 42 + src/pcf/naf-build.h | 36 + src/pcf/nbsf-handler.c | 130 +- src/pcf/npcf-handler.c | 793 +++- src/pcf/npcf-handler.h | 10 +- src/pcf/nsmf-build.c | 63 +- src/pcf/nsmf-build.h | 4 +- src/pcf/pcf-sm.c | 6 +- src/pcf/sbi-path.c | 64 +- src/pcf/sbi-path.h | 10 +- src/pcf/sm-sm.c | 53 +- src/pcrf/pcrf-gx-path.c | 316 +- src/pcrf/pcrf-rx-path.c | 19 +- src/smf/binding.c | 301 +- src/smf/binding.h | 2 +- src/smf/context.c | 86 +- src/smf/context.h | 22 +- src/smf/gsm-build.c | 237 +- src/smf/gsm-build.h | 5 +- src/smf/gsm-handler.c | 453 +++ src/smf/gsm-handler.h | 5 + src/smf/gsm-sm.c | 36 +- src/smf/gx-handler.c | 8 +- src/smf/n4-build.c | 15 +- src/smf/n4-handler.c | 164 +- src/smf/namf-build.c | 1 + src/smf/namf-build.h | 5 +- src/smf/namf-handler.c | 17 +- src/smf/namf-handler.h | 4 +- src/smf/ngap-build.c | 48 +- src/smf/ngap-build.h | 5 +- src/smf/ngap-handler.c | 9 + src/smf/npcf-handler.c | 488 ++- src/smf/npcf-handler.h | 4 + src/smf/pfcp-path.c | 1 - src/smf/s5c-build.c | 4 +- src/smf/s5c-build.h | 2 +- src/smf/s5c-handler.c | 57 +- src/smf/sbi-path.c | 11 +- src/smf/smf-sm.c | 50 +- tests/af/af-sm.c | 102 +- tests/af/context.c | 9 +- tests/af/npcf-build.c | 830 +++- tests/af/npcf-build.h | 13 + tests/af/npcf-handler.c | 36 + tests/af/npcf-handler.h | 2 + tests/common/gsm-build.c | 184 + tests/common/gsm-build.h | 3 + tests/common/ngap-build.c | 115 +- tests/common/ngap-build.h | 4 +- tests/handover/5gc-n2-test.c | 10 +- tests/handover/5gc-xn-test.c | 2 +- tests/registration/paging-test.c | 4 +- tests/vonr/abts-main.c | 2 + tests/vonr/af-test.c | 3611 ++++++++++++++++- tests/vonr/meson.build | 1 + tests/vonr/qos-flow-test.c | 2 +- tests/vonr/session-test.c | 8 +- tests/vonr/video-test.c | 561 +++ 135 files changed, 10220 insertions(+), 1552 deletions(-) create mode 100644 lib/sbi/support/20210629/openapitools.json create mode 100644 src/pcf/naf-build.c create mode 100644 src/pcf/naf-build.h create mode 100644 tests/vonr/video-test.c diff --git a/configs/meson.build b/configs/meson.build index f0cb05a93..26c73959b 100644 --- a/configs/meson.build +++ b/configs/meson.build @@ -41,7 +41,6 @@ example_conf = ''' vonr.yaml slice.yaml srslte.yaml - sample.yaml non3gpp.yaml '''.split() diff --git a/docs/_pages/about.md b/docs/_pages/about.md index 918a33899..c72d26e55 100644 --- a/docs/_pages/about.md +++ b/docs/_pages/about.md @@ -16,13 +16,13 @@ Open5GS is a C-language Open Source implementation of 5GC and EPC, i.e. the core - Multiple PDU session - Handover(5GC Xn/N2 and EPC S1/X2) - CSFB(Circuit Switched Fall Back) and SMSoS(SMS Over SGs) -- VoLTE(Voice over LTE) with HSS-Cx interface - Support ePDG Interface(SWx, S6b, S2b) +- VoLTE(Voice over LTE) with HSS-Cx interface +- VoNR(Voice over NR) #### Known Limitations --- -- No VoNR(Voice over NR) - No Interworking with EPC - No NB-IoT - No OCS/OFCS diff --git a/lib/core/ogs-3gpp-types.c b/lib/core/ogs-3gpp-types.c index b5da4a5c0..e143cb078 100644 --- a/lib/core/ogs-3gpp-types.c +++ b/lib/core/ogs-3gpp-types.c @@ -726,3 +726,279 @@ void ogs_ims_data_free(ogs_ims_data_t *ims_data) } } } + +static int flow_rx_to_gx(ogs_flow_t *rx_flow, ogs_flow_t *gx_flow) +{ + int len; + char *from_str, *to_str; + + ogs_assert(rx_flow); + ogs_assert(gx_flow); + + if (!strncmp(rx_flow->description, + "permit out", strlen("permit out"))) { + gx_flow->direction = OGS_FLOW_DOWNLINK_ONLY; + gx_flow->description = ogs_strdup(rx_flow->description); + ogs_assert(gx_flow->description); + + } else if (!strncmp(rx_flow->description, + "permit in", strlen("permit in"))) { + gx_flow->direction = OGS_FLOW_UPLINK_ONLY; + + /* 'permit in' should be changed + * 'permit out' in Gx Diameter */ + len = strlen(rx_flow->description)+2; + gx_flow->description = ogs_malloc(len); + ogs_assert(gx_flow->description); + strcpy(gx_flow->description, "permit out"); + from_str = strstr(&rx_flow->description[strlen("permit in")], "from"); + ogs_assert(from_str); + to_str = strstr(&rx_flow->description[strlen("permit in")], "to"); + ogs_assert(to_str); + strncat(gx_flow->description, + &rx_flow->description[strlen("permit in")], + strlen(rx_flow->description) - + strlen("permit in") - strlen(from_str)); + strcat(gx_flow->description, "from"); + strcat(gx_flow->description, &to_str[strlen("to")]); + strcat(gx_flow->description, " to"); + strncat(gx_flow->description, &from_str[strlen("from")], + strlen(from_str) - strlen(to_str) - strlen("from") - 1); + ogs_assert(len == strlen(gx_flow->description)+1); + } else { + ogs_error("Invalid Flow Descripton : [%s]", rx_flow->description); + return OGS_ERROR; + } + + return OGS_OK; +} + +int ogs_pcc_rule_num_of_flow_equal_to_media( + ogs_pcc_rule_t *pcc_rule, ogs_media_component_t *media_component) +{ + int rv; + int i, j, k; + int matched = 0; + int new = 0; + + ogs_assert(pcc_rule); + ogs_assert(media_component); + + for (i = 0; i < media_component->num_of_sub; i++) { + ogs_media_sub_component_t *sub = &media_component->sub[i]; + + for (j = 0; j < sub->num_of_flow; j++) { + new++; + } + } + + if (new == 0) { + /* No new flow in Media-Component */ + return pcc_rule->num_of_flow; + } + + for (i = 0; i < media_component->num_of_sub; i++) { + ogs_media_sub_component_t *sub = &media_component->sub[i]; + + for (j = 0; j < sub->num_of_flow && + j < OGS_MAX_NUM_OF_FLOW_IN_MEDIA_SUB_COMPONENT; j++) { + ogs_flow_t gx_flow; + ogs_flow_t *rx_flow = &sub->flow[j]; + + rv = flow_rx_to_gx(rx_flow, &gx_flow); + if (rv != OGS_OK) { + ogs_error("flow reformatting error"); + return OGS_ERROR; + } + + for (k = 0; k < pcc_rule->num_of_flow; k++) { + if (gx_flow.direction == pcc_rule->flow[k].direction && + !strcmp(gx_flow.description, + pcc_rule->flow[k].description)) { + matched++; + break; + } + } + + OGS_FLOW_FREE(&gx_flow); + } + } + + return matched; +} + +int ogs_pcc_rule_install_flow_from_media( + ogs_pcc_rule_t *pcc_rule, ogs_media_component_t *media_component) +{ + int rv; + int i, j; + + ogs_assert(pcc_rule); + ogs_assert(media_component); + + /* Remove Flow from PCC Rule */ + for (i = 0; i < pcc_rule->num_of_flow; i++) { + OGS_FLOW_FREE(&pcc_rule->flow[i]); + } + pcc_rule->num_of_flow = 0; + + for (i = 0; i < media_component->num_of_sub; i++) { + ogs_media_sub_component_t *sub = &media_component->sub[i]; + + /* Copy Flow to PCC Rule */ + for (j = 0; j < sub->num_of_flow && + j < OGS_MAX_NUM_OF_FLOW_IN_MEDIA_SUB_COMPONENT; j++) { + ogs_flow_t *rx_flow = NULL; + ogs_flow_t *gx_flow = NULL; + + if (pcc_rule->num_of_flow < OGS_MAX_NUM_OF_FLOW_IN_PCC_RULE) { + rx_flow = &sub->flow[j]; + gx_flow = &pcc_rule->flow[pcc_rule->num_of_flow]; + + rv = flow_rx_to_gx(rx_flow, gx_flow); + if (rv != OGS_OK) { + ogs_error("flow reformatting error"); + return OGS_ERROR; + } + + pcc_rule->num_of_flow++; + } else { + ogs_error("Overflow: Number of Flow"); + return OGS_ERROR; + } + } + } + + return OGS_OK; +} + +int ogs_pcc_rule_update_qos_from_media( + ogs_pcc_rule_t *pcc_rule, ogs_media_component_t *media_component) +{ + int rv; + int i, j; + + ogs_assert(pcc_rule); + ogs_assert(media_component); + + pcc_rule->qos.mbr.downlink = 0; + pcc_rule->qos.mbr.uplink = 0; + pcc_rule->qos.gbr.downlink = 0; + pcc_rule->qos.gbr.uplink = 0; + + for (i = 0; i < media_component->num_of_sub; i++) { + ogs_media_sub_component_t *sub = &media_component->sub[i]; + + for (j = 0; j < sub->num_of_flow && + j < OGS_MAX_NUM_OF_FLOW_IN_MEDIA_SUB_COMPONENT; j++) { + ogs_flow_t gx_flow; + ogs_flow_t *rx_flow = &sub->flow[j]; + + rv = flow_rx_to_gx(rx_flow, &gx_flow); + if (rv != OGS_OK) { + ogs_error("flow reformatting error"); + return OGS_ERROR; + } + + if (gx_flow.direction == OGS_FLOW_DOWNLINK_ONLY) { + if (sub->flow_usage == OGS_FLOW_USAGE_RTCP) { + if (media_component->rr_bandwidth && + media_component->rs_bandwidth) { + pcc_rule->qos.mbr.downlink += + (media_component->rr_bandwidth + + media_component->rs_bandwidth); + } else if (media_component->max_requested_bandwidth_dl) { + if (media_component->rr_bandwidth && + !media_component->rs_bandwidth) { + pcc_rule->qos.mbr.downlink += + ogs_max(0.05 * + media_component->max_requested_bandwidth_dl, + media_component->rr_bandwidth); + } + if (!media_component->rr_bandwidth && + media_component->rs_bandwidth) { + pcc_rule->qos.mbr.downlink += + ogs_max(0.05 * + media_component->max_requested_bandwidth_dl, + media_component->rs_bandwidth); + } + if (!media_component->rr_bandwidth && + !media_component->rs_bandwidth) { + pcc_rule->qos.mbr.downlink += + 0.05 * + media_component->max_requested_bandwidth_dl; + } + } + } else { + if (gx_flow.description) { + pcc_rule->qos.mbr.downlink += + media_component->max_requested_bandwidth_dl; + pcc_rule->qos.gbr.downlink += + media_component->min_requested_bandwidth_dl; + } + } + } else if (gx_flow.direction == OGS_FLOW_UPLINK_ONLY) { + if (sub->flow_usage == OGS_FLOW_USAGE_RTCP) { + if (media_component->rr_bandwidth && + media_component->rs_bandwidth) { + pcc_rule->qos.mbr.uplink += + (media_component->rr_bandwidth + + media_component->rs_bandwidth); + } else if (media_component->max_requested_bandwidth_ul) { + if (media_component->rr_bandwidth && + !media_component->rs_bandwidth) { + pcc_rule->qos.mbr.uplink += + ogs_max(0.05 * + media_component->max_requested_bandwidth_ul, + media_component->rr_bandwidth); + } + if (!media_component->rr_bandwidth && + media_component->rs_bandwidth) { + pcc_rule->qos.mbr.uplink += + ogs_max(0.05 * + media_component->max_requested_bandwidth_ul, + media_component->rs_bandwidth); + } + if (!media_component->rr_bandwidth && + !media_component->rs_bandwidth) { + pcc_rule->qos.mbr.uplink += + 0.05 * + media_component->max_requested_bandwidth_ul; + } + } + } else { + if (gx_flow.description) { + pcc_rule->qos.mbr.uplink += + media_component->max_requested_bandwidth_ul; + pcc_rule->qos.gbr.uplink += + media_component->min_requested_bandwidth_ul; + } + } + } else + ogs_assert_if_reached(); + + OGS_FLOW_FREE(&gx_flow); + } + } + + if (pcc_rule->qos.mbr.downlink == 0) { + pcc_rule->qos.mbr.downlink += + media_component->max_requested_bandwidth_dl; + pcc_rule->qos.mbr.downlink += + (media_component->rr_bandwidth + media_component->rs_bandwidth); + } + + if (pcc_rule->qos.mbr.uplink == 0) { + pcc_rule->qos.mbr.uplink += + media_component->max_requested_bandwidth_ul; + pcc_rule->qos.mbr.uplink += + (media_component->rr_bandwidth + media_component->rs_bandwidth); + } + + if (pcc_rule->qos.gbr.downlink == 0) + pcc_rule->qos.gbr.downlink = pcc_rule->qos.mbr.downlink; + if (pcc_rule->qos.gbr.uplink == 0) + pcc_rule->qos.gbr.uplink = pcc_rule->qos.mbr.uplink; + + return OGS_OK; +} diff --git a/lib/core/ogs-3gpp-types.h b/lib/core/ogs-3gpp-types.h index 8463d4ad3..5f0ea4032 100644 --- a/lib/core/ogs-3gpp-types.h +++ b/lib/core/ogs-3gpp-types.h @@ -652,6 +652,25 @@ void ogs_session_data_free(ogs_session_data_t *session_data); typedef struct ogs_media_sub_component_s { uint32_t flow_number; +/* + * TS29.214 + * 5.3.12 Flow-Usage AVP + * NO_INFORMATION(0) + * RTCP(1) + * AF_SIGNALLING(2) + * + * TS29.514 + * 5.6.3.14 Enumeration: FlowUsage + * NO_INFO : 1 + * RTCP : 2 + * AF_SIGNALLING : 3 + * + * EPC and 5GC have different values for FlowUsage + * At this point, we will use the 5GC value. + */ +#define OGS_FLOW_USAGE_NO_INFO 1 +#define OGS_FLOW_USAGE_RTCP 2 +#define OGS_FLOW_USAGE_AF_SIGNALLING 3 uint32_t flow_usage; ogs_flow_t flow[OGS_MAX_NUM_OF_FLOW_IN_MEDIA_SUB_COMPONENT]; int num_of_flow; @@ -690,6 +709,13 @@ typedef struct ogs_ims_data_s { void ogs_ims_data_free(ogs_ims_data_t *ims_data); +int ogs_pcc_rule_num_of_flow_equal_to_media( + ogs_pcc_rule_t *pcc_rule, ogs_media_component_t *media_component); +int ogs_pcc_rule_install_flow_from_media( + ogs_pcc_rule_t *pcc_rule, ogs_media_component_t *media_component); +int ogs_pcc_rule_update_qos_from_media( + ogs_pcc_rule_t *pcc_rule, ogs_media_component_t *media_component); + #ifdef __cplusplus } #endif diff --git a/lib/dbi/session.c b/lib/dbi/session.c index 609ecd434..9b58c5b1a 100644 --- a/lib/dbi/session.c +++ b/lib/dbi/session.c @@ -477,7 +477,7 @@ done: ogs_error("PCC Rule Id has already been defined"); ogs_free(pcc_rule->id); } - pcc_rule->id = ogs_msprintf("%d", pcc_rule_index+1); + pcc_rule->id = ogs_msprintf("%s-n%d", dnn, pcc_rule_index+1); ogs_assert(pcc_rule->id); pcc_rule->precedence = pcc_rule_index+1; diff --git a/lib/gtp/types.c b/lib/gtp/types.c index 38e46abe8..b8300931f 100644 --- a/lib/gtp/types.c +++ b/lib/gtp/types.c @@ -403,7 +403,7 @@ int16_t ogs_gtp_parse_tft(ogs_gtp_tft_t *tft, ogs_tlv_octet_t *octet) (unsigned char *)octet->data+size+len, sizeof(tft->pf[i].content.component[j].port.low)); tft->pf[i].content.component[j].port.low = - htobe16(tft->pf[i].content.component[j].port.low); + be16toh(tft->pf[i].content.component[j].port.low); len += sizeof(tft->pf[i].content.component[j].port.low); break; case OGS_PACKET_FILTER_LOCAL_PORT_RANGE_TYPE: @@ -415,7 +415,7 @@ int16_t ogs_gtp_parse_tft(ogs_gtp_tft_t *tft, ogs_tlv_octet_t *octet) (unsigned char *)octet->data+size+len, sizeof(tft->pf[i].content.component[j].port.low)); tft->pf[i].content.component[j].port.low = - htobe16(tft->pf[i].content.component[j].port.low); + be16toh(tft->pf[i].content.component[j].port.low); len += sizeof(tft->pf[i].content.component[j].port.low); ogs_assert(size+len+ @@ -425,7 +425,7 @@ int16_t ogs_gtp_parse_tft(ogs_gtp_tft_t *tft, ogs_tlv_octet_t *octet) (unsigned char *)octet->data+size+len, sizeof(tft->pf[i].content.component[j].port.high)); tft->pf[i].content.component[j].port.high = - htobe16(tft->pf[i].content.component[j].port.high); + be16toh(tft->pf[i].content.component[j].port.high); len += sizeof(tft->pf[i].content.component[j].port.high); break; default: diff --git a/lib/nas/5gs/types.c b/lib/nas/5gs/types.c index c00d10c6f..36185e4c2 100644 --- a/lib/nas/5gs/types.c +++ b/lib/nas/5gs/types.c @@ -444,6 +444,77 @@ int ogs_nas_build_qos_flow_descriptions( return OGS_OK; } +int ogs_nas_parse_qos_flow_descriptions( + ogs_nas_qos_flow_description_t *description, + ogs_nas_qos_flow_descriptions_t *descriptions) +{ + ogs_nas_qos_flow_description_t *first = description; + + char *buffer; + uint16_t length, size = 0; + int i; + + ogs_assert(description); + ogs_assert(descriptions); + ogs_assert(descriptions->length); + length = descriptions->length; + ogs_assert(descriptions->buffer); + buffer = descriptions->buffer; + + size = 0; + while (size < length) { + memset(description, 0, sizeof(*description)); + + ogs_assert(size+3 <= length); + memcpy(description, buffer+size, 3); + size += 3; + + for (i = 0; i < description->num_of_parameter && + i < OGS_NAS_MAX_NUM_OF_QOS_FLOW_PARAMETER; i++) { + ogs_assert(size+sizeof(description->param[i].identifier) <= length); + memcpy(&description->param[i].identifier, buffer+size, + sizeof(description->param[i].identifier)); + size += sizeof(description->param[i].identifier); + + ogs_assert(size+sizeof(description->param[i].len) <= length); + memcpy(&description->param[i].len, buffer+size, + sizeof(description->param[i].len)); + size += sizeof(description->param[i].len); + + switch(description->param[i].identifier) { + case OGS_NAX_QOS_FLOW_PARAMETER_ID_5QI: + ogs_assert(description->param[i].len == 1); + ogs_assert(size+description->param[i].len <= length); + memcpy(&description->param[i].qos_index, + buffer+size, description->param[i].len); + size += description->param[i].len; + break; + + case OGS_NAX_QOS_FLOW_PARAMETER_ID_GFBR_UPLINK: + case OGS_NAX_QOS_FLOW_PARAMETER_ID_GFBR_DOWNLINK: + case OGS_NAX_QOS_FLOW_PARAMETER_ID_MFBR_UPLINK: + case OGS_NAX_QOS_FLOW_PARAMETER_ID_MFBR_DOWNLINK: + ogs_assert(description->param[i].len == 3); + ogs_assert(size+description->param[i].len <= length); + memcpy(&description->param[i].br, + buffer+size, description->param[i].len); + description->param[i].br.value = + be16toh(description->param[i].br.value); + size += description->param[i].len; + break; + default: + ogs_fatal("Unknown qos_flow parameter identifier [%d]", + description->param[i].identifier); + ogs_assert_if_reached(); + } + } + + description++; + } + + return (int)(description-first); +} + int ogs_nas_build_qos_rules(ogs_nas_qos_rules_t *rules, ogs_nas_qos_rule_t *rule, int num_of_rule) { @@ -471,7 +542,6 @@ int ogs_nas_build_qos_rules(ogs_nas_qos_rules_t *rules, memcpy(buffer + length, &target.identifier, sizeof(target.identifier)); length += sizeof(target.identifier); - ogs_assert(length + sizeof(target.length) <= OGS_NAS_MAX_QOS_RULES_LEN); @@ -484,6 +554,16 @@ int ogs_nas_build_qos_rules(ogs_nas_qos_rules_t *rules, memcpy(buffer + length, &target.flags, sizeof(target.flags)); length += sizeof(target.flags); + if (rule->code == OGS_NAS_QOS_CODE_DELETE_EXISTING_QOS_RULE || + rule->code == OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_WITHOUT_MODIFYING_PACKET_FILTERS) { + if (target.num_of_packet_filter != 0) { + ogs_fatal("Invalue QoS rule code[%d] " + "and number of packet filter[%d]", + rule->code, target.num_of_packet_filter); + ogs_assert_if_reached(); + } + } + for (j = 0; j < target.num_of_packet_filter && j < OGS_MAX_NUM_OF_FLOW_IN_NAS; j++) { ogs_assert(length + sizeof(target.pf[j].flags) <= @@ -492,6 +572,10 @@ int ogs_nas_build_qos_rules(ogs_nas_qos_rules_t *rules, sizeof(target.pf[j].flags)); length += sizeof(target.pf[j].flags); + if (rule->code == + OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_DELETE_PACKET_FILTERS) + continue; + ogs_assert(length + sizeof(target.pf[j].content.length) <= OGS_NAS_MAX_QOS_RULES_LEN); memcpy(buffer + length, &target.pf[j].content.length, @@ -625,14 +709,20 @@ int ogs_nas_build_qos_rules(ogs_nas_qos_rules_t *rules, } } - ogs_assert(length + sizeof(target.precedence) <= - OGS_NAS_MAX_QOS_RULES_LEN); - memcpy(buffer + length, &target.precedence, sizeof(target.precedence)); - length += sizeof(target.precedence); - ogs_assert(length + sizeof(target.flow.flags) <= - OGS_NAS_MAX_QOS_RULES_LEN); - memcpy(buffer + length, &target.flow.flags, sizeof(target.precedence)); - length += sizeof(target.flow.flags); + if (rule->code != OGS_NAS_QOS_CODE_DELETE_EXISTING_QOS_RULE && + rule->code != OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_DELETE_PACKET_FILTERS && + rule->code != OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_WITHOUT_MODIFYING_PACKET_FILTERS) { + ogs_assert(length + sizeof(target.precedence) <= + OGS_NAS_MAX_QOS_RULES_LEN); + memcpy(buffer + length, &target.precedence, + sizeof(target.precedence)); + length += sizeof(target.precedence); + ogs_assert(length + sizeof(target.flow.flags) <= + OGS_NAS_MAX_QOS_RULES_LEN); + memcpy(buffer + length, &target.flow.flags, + sizeof(target.flow.flags)); + length += sizeof(target.flow.flags); + } /* Update QoS Rule Length */ target.length = htobe16( @@ -645,3 +735,206 @@ int ogs_nas_build_qos_rules(ogs_nas_qos_rules_t *rules, return OGS_OK; } + +int ogs_nas_parse_qos_rules( + ogs_nas_qos_rule_t *rule, ogs_nas_qos_rules_t *rules) +{ + ogs_nas_qos_rule_t *first = rule; + + char *buffer; + uint16_t length, size = 0; + int i, j, len = 0; + + ogs_assert(rule); + ogs_assert(rules); + ogs_assert(rules->length); + length = rules->length; + ogs_assert(rules->buffer); + buffer = rules->buffer; + + size = 0; + while (size < length) { + memset(rule, 0, sizeof(*rule)); + + ogs_assert(size+sizeof(rule->identifier) <= length); + memcpy(&rule->identifier, buffer+size, sizeof(rule->identifier)); + size += sizeof(rule->identifier); + + ogs_assert(size+sizeof(rule->length) <= length); + memcpy(&rule->length, buffer+size, sizeof(rule->length)); + rule->length = be16toh(rule->length); + size += sizeof(rule->length); + + ogs_assert(size+sizeof(rule->flags) <= length); + memcpy(&rule->flags, buffer+size, sizeof(rule->flags)); + size += sizeof(rule->flags); + + if (rule->code == OGS_NAS_QOS_CODE_DELETE_EXISTING_QOS_RULE || + rule->code == OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_WITHOUT_MODIFYING_PACKET_FILTERS) { + if (rule->num_of_packet_filter != 0) { + ogs_error("Invalue QoS rule code[%d] " + "and number of packet filter[%d]", + rule->code, rule->num_of_packet_filter); + rule->num_of_packet_filter = 0; + } + } + + for (i = 0; i < rule->num_of_packet_filter && + i < OGS_MAX_NUM_OF_FLOW_IN_GTP; i++) { + ogs_assert(size+sizeof(rule->pf[i].flags) <= length); + memcpy(&rule->pf[i].flags, buffer+size, sizeof(rule->pf[i].flags)); + size += sizeof(rule->pf[i].flags); + + if (rule->code == + OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_DELETE_PACKET_FILTERS) + continue; + + ogs_assert(size+sizeof(rule->pf[i].content.length) <= length); + memcpy(&rule->pf[i].content.length, buffer+size, + sizeof(rule->pf[i].content.length)); + size += sizeof(rule->pf[i].content.length); + + j = 0; len = 0; + while(len < rule->pf[i].content.length) { + ogs_assert(size+len+ + sizeof(rule->pf[i].content.component[j].type) <= length); + memcpy(&rule->pf[i].content.component[j].type, + buffer+size+len, + sizeof(rule->pf[i].content.component[j].type)); + len += sizeof(rule->pf[i].content.component[j].type); + switch(rule->pf[i].content.component[j].type) { + case OGS_PACKET_FILTER_PROTOCOL_IDENTIFIER_NEXT_HEADER_TYPE: + ogs_assert(size+len+ + sizeof(rule->pf[i].content.component[j].proto) <= + length); + memcpy(&rule->pf[i].content.component[j].proto, + buffer+size+len, + sizeof(rule->pf[i].content.component[j].proto)); + len += sizeof(rule->pf[i].content.component[j].proto); + break; + case OGS_PACKET_FILTER_IPV4_REMOTE_ADDRESS_TYPE: + case OGS_PACKET_FILTER_IPV4_LOCAL_ADDRESS_TYPE: + ogs_assert(size+len+ + sizeof(rule->pf[i].content.component[j].ipv4.addr) <= + length); + memcpy(&rule->pf[i].content.component[j].ipv4.addr, + buffer+size+len, + sizeof(rule->pf[i].content.component[j].ipv4.addr)); + len += sizeof(rule->pf[i].content.component[j].ipv4.addr); + + ogs_assert(size+len+ + sizeof(rule->pf[i].content.component[j].ipv4.mask) <= + length); + memcpy(&rule->pf[i].content.component[j].ipv4.mask, + buffer+size+len, + sizeof(rule->pf[i].content.component[j].ipv4.mask)); + len += sizeof(rule->pf[i].content.component[j].ipv4.mask); + break; + case OGS_PACKET_FILTER_IPV6_LOCAL_ADDRESS_PREFIX_LENGTH_TYPE: + case OGS_PACKET_FILTER_IPV6_REMOTE_ADDRESS_PREFIX_LENGTH_TYPE: + ogs_assert(size+len+ + sizeof(rule->pf[i].content.component[j].ipv6.addr) <= + length); + memcpy(&rule->pf[i].content.component[j].ipv6.addr, + buffer+size+len, + sizeof(rule->pf[i].content.component[j].ipv6.addr)); + len += sizeof(rule->pf[i].content.component[j].ipv6.addr); + + ogs_assert(size+len+ + sizeof( + rule->pf[i].content.component[j].ipv6.prefixlen) <= + length); + memcpy(&rule->pf[i].content.component[j].ipv6.prefixlen, + buffer+size+len, + sizeof( + rule->pf[i].content.component[j].ipv6.prefixlen)); + len += sizeof( + rule->pf[i].content.component[j].ipv6.prefixlen); + break; + case OGS_PACKET_FILTER_IPV6_LOCAL_ADDRESS_TYPE: + case OGS_PACKET_FILTER_IPV6_REMOTE_ADDRESS_TYPE: + ogs_assert(size+len+ + sizeof( + rule->pf[i].content.component[j].ipv6_mask.addr) <= + length); + memcpy(&rule->pf[i].content.component[j].ipv6_mask.addr, + buffer+size+len, + sizeof( + rule->pf[i].content.component[j].ipv6_mask.addr)); + len += sizeof( + rule->pf[i].content.component[j].ipv6_mask.addr); + + ogs_assert(size+len+ + sizeof( + rule->pf[i].content.component[j].ipv6_mask.mask) <= + length); + memcpy(&rule->pf[i].content.component[j].ipv6_mask.mask, + buffer+size+len, + sizeof( + rule->pf[i].content.component[j].ipv6_mask.mask)); + len += sizeof( + rule->pf[i].content.component[j].ipv6_mask.mask); + break; + case OGS_PACKET_FILTER_SINGLE_LOCAL_PORT_TYPE: + case OGS_PACKET_FILTER_SINGLE_REMOTE_PORT_TYPE: + ogs_assert(size+len+ + sizeof(rule->pf[i].content.component[j].port.low) <= + length); + memcpy(&rule->pf[i].content.component[j].port.low, + buffer+size+len, + sizeof(rule->pf[i].content.component[j].port.low)); + rule->pf[i].content.component[j].port.low = + be16toh(rule->pf[i].content.component[j].port.low); + len += sizeof(rule->pf[i].content.component[j].port.low); + break; + case OGS_PACKET_FILTER_LOCAL_PORT_RANGE_TYPE: + case OGS_PACKET_FILTER_REMOTE_PORT_RANGE_TYPE: + ogs_assert(size+len+ + sizeof(rule->pf[i].content.component[j].port.low) <= + length); + memcpy(&rule->pf[i].content.component[j].port.low, + buffer+size+len, + sizeof(rule->pf[i].content.component[j].port.low)); + rule->pf[i].content.component[j].port.low = + be16toh(rule->pf[i].content.component[j].port.low); + len += sizeof(rule->pf[i].content.component[j].port.low); + + ogs_assert(size+len+ + sizeof(rule->pf[i].content.component[j].port.high) <= + length); + memcpy(&rule->pf[i].content.component[j].port.high, + buffer+size+len, + sizeof(rule->pf[i].content.component[j].port.high)); + rule->pf[i].content.component[j].port.high = + be16toh(rule->pf[i].content.component[j].port.high); + len += sizeof(rule->pf[i].content.component[j].port.high); + break; + default: + ogs_error("Unknown Packet Filter Type(%d)", + rule->pf[i].content.component[j].type); + return -1; + } + j++; + } + rule->pf[i].content.num_of_component = j; + size += len; + } + + if (rule->code != OGS_NAS_QOS_CODE_DELETE_EXISTING_QOS_RULE && + rule->code != OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_DELETE_PACKET_FILTERS && + rule->code != OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_WITHOUT_MODIFYING_PACKET_FILTERS) { + + ogs_assert(size+sizeof(rule->precedence) <= length); + memcpy(&rule->precedence, buffer+size, sizeof(rule->precedence)); + size += sizeof(rule->precedence); + + ogs_assert(size+sizeof(rule->flow.flags) <= length); + memcpy(&rule->flow.flags, buffer+size, sizeof(rule->flow.flags)); + size += sizeof(rule->flow.flags); + } + + rule++; + } + + return (int)(rule-first); +} diff --git a/lib/nas/5gs/types.h b/lib/nas/5gs/types.h index e03155b17..865aae5b1 100644 --- a/lib/nas/5gs/types.h +++ b/lib/nas/5gs/types.h @@ -803,6 +803,10 @@ int ogs_nas_build_qos_flow_descriptions( ogs_nas_qos_flow_description_t *flow_description, int num_of_flow_description); +int ogs_nas_parse_qos_flow_descriptions( + ogs_nas_qos_flow_description_t *description, + ogs_nas_qos_flow_descriptions_t *descriptions); + /* 9.11.4.13 QoS rules * M LV-E 6-65535 */ #define OGS_NAS_MAX_NUM_OF_QOS_RULE 8 @@ -858,6 +862,8 @@ typedef struct ogs_nas_qos_rules_s { int ogs_nas_build_qos_rules(ogs_nas_qos_rules_t *rules, ogs_nas_qos_rule_t *rule, int num_of_rule); +int ogs_nas_parse_qos_rules( + ogs_nas_qos_rule_t *rule, ogs_nas_qos_rules_t *rules); /* 9.11.4.15 SM PDU DN request container * O TLV 3-255 */ diff --git a/lib/nas/common/types.c b/lib/nas/common/types.c index fe5c0495b..f0da24b84 100644 --- a/lib/nas/common/types.c +++ b/lib/nas/common/types.c @@ -443,3 +443,64 @@ void ogs_nas_bitrate_from_uint64(ogs_nas_bitrate_t *nas, uint64_t bitrate) } nas->value = bitrate; } + +uint64_t ogs_nas_bitrate_to_uint64(ogs_nas_bitrate_t *nas_bitrate) +{ + ogs_assert(nas_bitrate); + + if (nas_bitrate->unit == OGS_NAS_BR_UNIT_1K) + return nas_bitrate->value * 1024; + if (nas_bitrate->unit == OGS_NAS_BR_UNIT_4K) + return nas_bitrate->value * 4 * 1024; + if (nas_bitrate->unit == OGS_NAS_BR_UNIT_16K) + return nas_bitrate->value * 16 * 1024; + if (nas_bitrate->unit == OGS_NAS_BR_UNIT_64K) + return nas_bitrate->value * 64 * 1024; + if (nas_bitrate->unit == OGS_NAS_BR_UNIT_256K) + return nas_bitrate->value * 256 * 1024; + if (nas_bitrate->unit == OGS_NAS_BR_UNIT_1M) + return nas_bitrate->value * 1024 * 1024; + if (nas_bitrate->unit == OGS_NAS_BR_UNIT_4M) + return nas_bitrate->value * 4 * 1024 * 1024; + if (nas_bitrate->unit == OGS_NAS_BR_UNIT_16M) + return nas_bitrate->value * 16 * 1024 * 1024; + if (nas_bitrate->unit == OGS_NAS_BR_UNIT_64M) + return nas_bitrate->value * 64 * 1024 * 1024; + if (nas_bitrate->unit == OGS_NAS_BR_UNIT_256M) + return nas_bitrate->value * 256 * 1024 * 1024; + if (nas_bitrate->unit == OGS_NAS_BR_UNIT_1G) + return nas_bitrate->value * 1024 * 1024 * 1024; + if (nas_bitrate->unit == OGS_NAS_BR_UNIT_4G) + return nas_bitrate->value * 4 * 1024 * 1024 * 1024; + if (nas_bitrate->unit == OGS_NAS_BR_UNIT_16G) + return nas_bitrate->value * 16 * 1024 * 1024 * 1024; + if (nas_bitrate->unit == OGS_NAS_BR_UNIT_64G) + return nas_bitrate->value * 64 * 1024 * 1024 * 1024; + if (nas_bitrate->unit == OGS_NAS_BR_UNIT_256G) + return nas_bitrate->value * 256 * 1024 * 1024 * 1024; + if (nas_bitrate->unit == OGS_NAS_BR_UNIT_1T) + return nas_bitrate->value * 1024 * 1024 * 1024 * 1024; + if (nas_bitrate->unit == OGS_NAS_BR_UNIT_4T) + return nas_bitrate->value * 4 * 1024 * 1024 * 1024 * 1024; + if (nas_bitrate->unit == OGS_NAS_BR_UNIT_16T) + return nas_bitrate->value * 16 * 1024 * 1024 * 1024 * 1024; + if (nas_bitrate->unit == OGS_NAS_BR_UNIT_64T) + return nas_bitrate->value * 64 * 1024 * 1024 * 1024 * 1024; + if (nas_bitrate->unit == OGS_NAS_BR_UNIT_256T) + return nas_bitrate->value * 256 * 1024 * 1024 * 1024 * 1024; + if (nas_bitrate->unit == OGS_NAS_BR_UNIT_1P) + return nas_bitrate->value * 1024 * 1024 * 1024 * 1024 * 1024; + if (nas_bitrate->unit == OGS_NAS_BR_UNIT_4P) + return nas_bitrate->value * 4 * 1024 * 1024 * 1024 * 1024 * 1024; + if (nas_bitrate->unit == OGS_NAS_BR_UNIT_16P) + return nas_bitrate->value * 16 * 1024 * 1024 * 1024 * 1024 * 1024; + if (nas_bitrate->unit == OGS_NAS_BR_UNIT_64P) + return nas_bitrate->value * 64 * 1024 * 1024 * 1024 * 1024 * 1024; + if (nas_bitrate->unit == OGS_NAS_BR_UNIT_256P) + return nas_bitrate->value * 256 * 1024 * 1024 * 1024 * 1024 * 1024; + + ogs_fatal("Unknown unit [%d]", nas_bitrate->unit); + ogs_assert_if_reached(); + + return 0; +} diff --git a/lib/nas/common/types.h b/lib/nas/common/types.h index 7ffb01ea4..537a1a27a 100644 --- a/lib/nas/common/types.h +++ b/lib/nas/common/types.h @@ -941,6 +941,7 @@ typedef struct ogs_nas_bitrate_s { void ogs_nas_bitrate_from_uint64( ogs_nas_bitrate_t *nas_bitrate, uint64_t bitrate); +uint64_t ogs_nas_bitrate_to_uint64(ogs_nas_bitrate_t *nas_bitrate); typedef struct ogs_nas_session_ambr_s { uint8_t length; diff --git a/lib/pfcp/xact.h b/lib/pfcp/xact.h index 481947952..9df2f8d4b 100644 --- a/lib/pfcp/xact.h +++ b/lib/pfcp/xact.h @@ -74,17 +74,27 @@ typedef struct ogs_pfcp_xact_s { #define OGS_PFCP_MODIFY_DL_ONLY ((uint64_t)1<<1) #define OGS_PFCP_MODIFY_UL_ONLY ((uint64_t)1<<2) #define OGS_PFCP_MODIFY_INDIRECT ((uint64_t)1<<3) -#define OGS_PFCP_MODIFY_CREATE ((uint64_t)1<<4) -#define OGS_PFCP_MODIFY_REMOVE ((uint64_t)1<<5) -#define OGS_PFCP_MODIFY_TFT_UPDATE ((uint64_t)1<<6) -#define OGS_PFCP_MODIFY_QOS_UPDATE ((uint64_t)1<<7) -#define OGS_PFCP_MODIFY_ACTIVATE ((uint64_t)1<<8) -#define OGS_PFCP_MODIFY_DEACTIVATE ((uint64_t)1<<9) -#define OGS_PFCP_MODIFY_END_MARKER ((uint64_t)1<<10) -#define OGS_PFCP_MODIFY_ERROR_INDICATION ((uint64_t)1<<11) -#define OGS_PFCP_MODIFY_XN_HANDOVER ((uint64_t)1<<12) -#define OGS_PFCP_MODIFY_N2_HANDOVER ((uint64_t)1<<13) -#define OGS_PFCP_MODIFY_HANDOVER_CANCEL ((uint64_t)1<<14) +#define OGS_PFCP_MODIFY_UE_REQUESTED ((uint64_t)1<<4) +#define OGS_PFCP_MODIFY_NETWORK_REQUESTED ((uint64_t)1<<5) +#define OGS_PFCP_MODIFY_CREATE ((uint64_t)1<<6) +#define OGS_PFCP_MODIFY_REMOVE ((uint64_t)1<<7) +#define OGS_PFCP_MODIFY_EPC_TFT_UPDATE ((uint64_t)1<<8) +#define OGS_PFCP_MODIFY_EPC_QOS_UPDATE ((uint64_t)1<<9) +#define OGS_PFCP_MODIFY_TFT_NEW ((uint64_t)1<<10) +#define OGS_PFCP_MODIFY_TFT_ADD ((uint64_t)1<<11) +#define OGS_PFCP_MODIFY_TFT_REPLACE ((uint64_t)1<<12) +#define OGS_PFCP_MODIFY_TFT_DELETE ((uint64_t)1<<13) +#define OGS_PFCP_MODIFY_QOS_CREATE ((uint64_t)1<<14) +#define OGS_PFCP_MODIFY_QOS_MODIFY ((uint64_t)1<<15) +#define OGS_PFCP_MODIFY_QOS_DELETE ((uint64_t)1<<16) +#define OGS_PFCP_MODIFY_ACTIVATE ((uint64_t)1<<17) +#define OGS_PFCP_MODIFY_DEACTIVATE ((uint64_t)1<<18) +#define OGS_PFCP_MODIFY_END_MARKER ((uint64_t)1<<19) +#define OGS_PFCP_MODIFY_ERROR_INDICATION ((uint64_t)1<<20) +#define OGS_PFCP_MODIFY_XN_HANDOVER ((uint64_t)1<<21) +#define OGS_PFCP_MODIFY_N2_HANDOVER ((uint64_t)1<<22) +#define OGS_PFCP_MODIFY_HANDOVER_CANCEL ((uint64_t)1<<23) + uint64_t modify_flags; #define OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED 1 diff --git a/lib/sbi/conv.c b/lib/sbi/conv.c index 36bd4e64b..c034e7655 100644 --- a/lib/sbi/conv.c +++ b/lib/sbi/conv.c @@ -663,3 +663,161 @@ void ogs_sbi_free_nr_location(OpenAPI_nr_location_t *NrLocation) ogs_free(NrLocation); } + +OpenAPI_pcc_rule_t *ogs_sbi_build_pcc_rule( + ogs_pcc_rule_t *pcc_rule, int flow_presence) +{ + OpenAPI_pcc_rule_t *PccRule = NULL; + OpenAPI_list_t *FlowInformationList = NULL; + OpenAPI_flow_information_t *FlowInformation = NULL; + + int i; + + ogs_assert(pcc_rule); + + PccRule = ogs_calloc(1, sizeof(*PccRule)); + ogs_assert(PccRule); + + /* + * At this point, only 1 QosData is used for PccRule. + * Therefore, QoS ID uses the same value as PCC Rule ID. + */ + PccRule->pcc_rule_id = pcc_rule->id; + + PccRule->ref_qos_data = OpenAPI_list_create(); + ogs_assert(PccRule->ref_qos_data); + + OpenAPI_list_add(PccRule->ref_qos_data, PccRule->pcc_rule_id); + + PccRule->is_precedence = true; + PccRule->precedence = pcc_rule->precedence; + + if (flow_presence == 1) { + FlowInformationList = OpenAPI_list_create(); + ogs_assert(FlowInformationList); + + for (i = 0; i < pcc_rule->num_of_flow; i++) { + ogs_flow_t *flow = &pcc_rule->flow[i]; + ogs_assert(flow); + + FlowInformation = ogs_calloc(1, sizeof(*FlowInformation)); + ogs_assert(FlowInformation); + + if (flow->direction == OGS_FLOW_UPLINK_ONLY) + FlowInformation->flow_direction = + OpenAPI_flow_direction_UPLINK; + else if (flow->direction == OGS_FLOW_DOWNLINK_ONLY) + FlowInformation->flow_direction = + OpenAPI_flow_direction_DOWNLINK; + else { + ogs_fatal("Unsupported direction [%d]", flow->direction); + ogs_assert_if_reached(); + } + + ogs_assert(flow->description); + FlowInformation->flow_description = flow->description; + + OpenAPI_list_add(FlowInformationList, FlowInformation); + } + + if (FlowInformationList->count) + PccRule->flow_infos = FlowInformationList; + else + OpenAPI_list_free(FlowInformationList); + } + + return PccRule; +} + +void ogs_sbi_free_pcc_rule(OpenAPI_pcc_rule_t *PccRule) +{ + OpenAPI_flow_information_t *FlowInformation = NULL; + OpenAPI_lnode_t *node = NULL; + + ogs_assert(PccRule); + + if (PccRule->ref_qos_data) + OpenAPI_list_free(PccRule->ref_qos_data); + if (PccRule->flow_infos) { + OpenAPI_list_for_each(PccRule->flow_infos, node) { + FlowInformation = node->data; + if (FlowInformation) ogs_free(FlowInformation); + } + OpenAPI_list_free(PccRule->flow_infos); + } + ogs_free(PccRule); +} + +OpenAPI_qos_data_t *ogs_sbi_build_qos_data(ogs_pcc_rule_t *pcc_rule) +{ + OpenAPI_qos_data_t *QosData = NULL; + + ogs_assert(pcc_rule); + + QosData = ogs_calloc(1, sizeof(*QosData)); + ogs_assert(QosData); + + /* + * At this point, only 1 QosData is used for PccRule. + * Therefore, QoS ID uses the same value as PCC Rule ID. + */ + QosData->qos_id = pcc_rule->id; + + QosData->is__5qi = true; + QosData->_5qi = pcc_rule->qos.index; + QosData->is_priority_level = true; + QosData->priority_level = pcc_rule->qos.arp.priority_level; + + QosData->arp = ogs_calloc(1, sizeof(OpenAPI_arp_t)); + ogs_assert(QosData->arp); + + if (pcc_rule->qos.arp.pre_emption_capability == + OGS_5GC_PRE_EMPTION_ENABLED) + QosData->arp->preempt_cap = + OpenAPI_preemption_capability_MAY_PREEMPT; + else if (pcc_rule->qos.arp.pre_emption_capability == + OGS_5GC_PRE_EMPTION_DISABLED) + QosData->arp->preempt_cap = + OpenAPI_preemption_capability_NOT_PREEMPT; + ogs_assert(pcc_rule->qos.arp.pre_emption_capability); + + if (pcc_rule->qos.arp.pre_emption_vulnerability == + OGS_5GC_PRE_EMPTION_ENABLED) + QosData->arp->preempt_vuln = + OpenAPI_preemption_vulnerability_PREEMPTABLE; + else if (pcc_rule->qos.arp.pre_emption_vulnerability == + OGS_5GC_PRE_EMPTION_DISABLED) + QosData->arp->preempt_vuln = + OpenAPI_preemption_vulnerability_NOT_PREEMPTABLE; + ogs_assert(pcc_rule->qos.arp.pre_emption_vulnerability); + QosData->arp->priority_level = pcc_rule->qos.arp.priority_level; + + if (pcc_rule->qos.mbr.uplink) + QosData->maxbr_ul = ogs_sbi_bitrate_to_string( + pcc_rule->qos.mbr.uplink, OGS_SBI_BITRATE_BPS); + if (pcc_rule->qos.mbr.downlink) + QosData->maxbr_dl = ogs_sbi_bitrate_to_string( + pcc_rule->qos.mbr.downlink, OGS_SBI_BITRATE_BPS); + + if (pcc_rule->qos.gbr.uplink) + QosData->gbr_ul = ogs_sbi_bitrate_to_string( + pcc_rule->qos.gbr.uplink, OGS_SBI_BITRATE_BPS); + if (pcc_rule->qos.gbr.downlink) + QosData->gbr_dl = ogs_sbi_bitrate_to_string( + pcc_rule->qos.gbr.downlink, OGS_SBI_BITRATE_BPS); + + return QosData; +} + +void ogs_sbi_free_qos_data(OpenAPI_qos_data_t *QosData) +{ + ogs_assert(QosData); + + if (QosData->arp) ogs_free(QosData->arp); + if (QosData->maxbr_ul) ogs_free(QosData->maxbr_ul); + if (QosData->maxbr_dl) ogs_free(QosData->maxbr_dl); + if (QosData->gbr_ul) ogs_free(QosData->gbr_ul); + if (QosData->gbr_dl) ogs_free(QosData->gbr_dl); + + ogs_free(QosData); +} diff --git a/lib/sbi/conv.h b/lib/sbi/conv.h index b083dc5b0..ab3ee14ef 100644 --- a/lib/sbi/conv.h +++ b/lib/sbi/conv.h @@ -76,6 +76,12 @@ bool ogs_sbi_parse_nr_location(ogs_5gs_tai_t *tai, ogs_nr_cgi_t *nr_cgi, OpenAPI_nr_location_t *NrLocation); void ogs_sbi_free_nr_location(OpenAPI_nr_location_t *NrLocation); +OpenAPI_pcc_rule_t *ogs_sbi_build_pcc_rule( + ogs_pcc_rule_t *pcc_rule, int flow_presence); +void ogs_sbi_free_pcc_rule(OpenAPI_pcc_rule_t *PccRule); +OpenAPI_qos_data_t *ogs_sbi_build_qos_data(ogs_pcc_rule_t *pcc_rule); +void ogs_sbi_free_qos_data(OpenAPI_qos_data_t *QosData); + #ifdef __cplusplus } #endif diff --git a/lib/sbi/message.c b/lib/sbi/message.c index 06a021448..ba714a45d 100644 --- a/lib/sbi/message.c +++ b/lib/sbi/message.c @@ -161,6 +161,12 @@ void ogs_sbi_message_free(ogs_sbi_message_t *message) OpenAPI_pcf_binding_free(message->PcfBinding); if (message->AppSessionContext) OpenAPI_app_session_context_free(message->AppSessionContext); + if (message->AppSessionContextUpdateDataPatch) + OpenAPI_app_session_context_update_data_patch_free(message->AppSessionContextUpdateDataPatch); + if (message->SmPolicyNotification) + OpenAPI_sm_policy_notification_free(message->SmPolicyNotification); + if (message->TerminationNotification) + OpenAPI_termination_notification_free(message->TerminationNotification); for (i = 0; i < message->num_of_part; i++) { if (message->part[i].pkbuf) @@ -875,6 +881,18 @@ static char *build_json(ogs_sbi_message_t *message) item = OpenAPI_app_session_context_convertToJSON( message->AppSessionContext); ogs_assert(item); + } else if (message->AppSessionContextUpdateDataPatch) { + item = OpenAPI_app_session_context_update_data_patch_convertToJSON( + message->AppSessionContextUpdateDataPatch); + ogs_assert(item); + } else if (message->SmPolicyNotification) { + item = OpenAPI_sm_policy_notification_convertToJSON( + message->SmPolicyNotification); + ogs_assert(item); + } else if (message->TerminationNotification) { + item = OpenAPI_termination_notification_convertToJSON( + message->TerminationNotification); + ogs_assert(item); } if (item) { @@ -1608,14 +1626,30 @@ static int parse_json(ogs_sbi_message_t *message, SWITCH(message->h.resource.component[0]) CASE(OGS_SBI_RESOURCE_NAME_APP_SESSIONS) if (message->h.resource.component[1]) { - SWITCH(message->h.method) - CASE(OGS_SBI_HTTP_METHOD_DELETE) - break; - DEFAULT - rv = OGS_ERROR; - ogs_error("Unknown method [%s]", message->h.method); - END - break; + if (message->h.resource.component[2]) { + SWITCH(message->h.resource.component[2]) + CASE(OGS_SBI_RESOURCE_NAME_DELETE) + /* Nothing */ + break; + DEFAULT + rv = OGS_ERROR; + ogs_error("JSON parse error"); + END + } else { + SWITCH(message->h.method) + CASE(OGS_SBI_HTTP_METHOD_PATCH) + message->AppSessionContextUpdateDataPatch = + OpenAPI_app_session_context_update_data_patch_parseFromJSON(item); + if (!message->AppSessionContextUpdateDataPatch) { + rv = OGS_ERROR; + ogs_error("JSON parse error"); + } + break; + DEFAULT + rv = OGS_ERROR; + ogs_error("JSON parse error"); + END + } } else { SWITCH(message->h.method) CASE(OGS_SBI_HTTP_METHOD_POST) @@ -1630,14 +1664,12 @@ static int parse_json(ogs_sbi_message_t *message, } } break; - DEFAULT rv = OGS_ERROR; ogs_error("Unknown method [%s]", message->h.method); END - break; } - + break; DEFAULT rv = OGS_ERROR; ogs_error("Unknown resource name [%s]", @@ -1675,10 +1707,36 @@ static int parse_json(ogs_sbi_message_t *message, } break; + CASE(OGS_SBI_RESOURCE_NAME_SM_POLICY_NOTIFY) + SWITCH(message->h.resource.component[2]) + CASE(OGS_SBI_RESOURCE_NAME_UPDATE) + message->SmPolicyNotification = + OpenAPI_sm_policy_notification_parseFromJSON(item); + if (!message->SmPolicyNotification) { + rv = OGS_ERROR; + ogs_error("JSON parse error"); + } + break; + CASE(OGS_SBI_RESOURCE_NAME_TERMINATE) + message->TerminationNotification = + OpenAPI_termination_notification_parseFromJSON(item); + if (!message->TerminationNotification) { + rv = OGS_ERROR; + ogs_error("JSON parse error"); + } + break; + + DEFAULT + rv = OGS_ERROR; + ogs_error("Unknown resource name [%s]", + message->h.resource.component[2]); + END + break; + DEFAULT rv = OGS_ERROR; ogs_error("Unknown resource name [%s]", - message->h.resource.component[1]); + message->h.resource.component[0]); END break; diff --git a/lib/sbi/message.h b/lib/sbi/message.h index 67eea10f2..ce86784e8 100644 --- a/lib/sbi/message.h +++ b/lib/sbi/message.h @@ -148,6 +148,9 @@ extern "C" { "npcf-policyauthorization" #define OGS_SBI_RESOURCE_NAME_APP_SESSIONS "app-sessions" #define OGS_SBI_RESOURCE_NAME_NOTIFY "notify" +#define OGS_SBI_SERVICE_NAME_NPCF_CALLBACK "npcf-callback" +#define OGS_SBI_RESOURCE_NAME_UPDATE "update" +#define OGS_SBI_RESOURCE_NAME_TERMINATE "terminate" #define OGS_SBI_SERVICE_NAME_NNSSF_NSSELECTION "nnssf-nsselection" #define OGS_SBI_RESOURCE_NAME_NETWORK_SLICE_INFORMATION \ @@ -397,10 +400,13 @@ typedef struct ogs_sbi_message_s { OpenAPI_sm_policy_decision_t *SmPolicyDecision; OpenAPI_sm_policy_data_t *SmPolicyData; OpenAPI_sm_policy_delete_data_t *SmPolicyDeleteData; - OpenAPI_sm_policy_notification_t *SmPolicyNotification; OpenAPI_authorized_network_slice_info_t *AuthorizedNetworkSliceInfo; OpenAPI_pcf_binding_t *PcfBinding; OpenAPI_app_session_context_t *AppSessionContext; + OpenAPI_app_session_context_update_data_patch_t + *AppSessionContextUpdateDataPatch; + OpenAPI_sm_policy_notification_t *SmPolicyNotification; + OpenAPI_termination_notification_t *TerminationNotification; ogs_sbi_links_t *links; diff --git a/lib/sbi/ogs-sbi.h b/lib/sbi/ogs-sbi.h index 8e77ad9ba..454df7d16 100644 --- a/lib/sbi/ogs-sbi.h +++ b/lib/sbi/ogs-sbi.h @@ -68,8 +68,10 @@ #include "model/authorized_network_slice_info.h" #include "model/pcf_binding.h" #include "model/app_session_context.h" +#include "model/app_session_context_update_data_patch.h" #include "model/policy_update.h" #include "model/sm_policy_notification.h" +#include "model/termination_notification.h" #include "custom/links.h" #include "custom/ue_authentication_ctx.h" diff --git a/lib/sbi/openapi/model/acceptable_service_info.c b/lib/sbi/openapi/model/acceptable_service_info.c index 7f826392e..a1beafcab 100644 --- a/lib/sbi/openapi/model/acceptable_service_info.c +++ b/lib/sbi/openapi/model/acceptable_service_info.c @@ -59,7 +59,9 @@ cJSON *OpenAPI_acceptable_service_info_convertToJSON(OpenAPI_acceptable_service_ if (acceptable_service_info->acc_bw_med_comps) { OpenAPI_list_for_each(acceptable_service_info->acc_bw_med_comps, acc_bw_med_comps_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)acc_bw_med_comps_node->data; - cJSON *itemLocal = OpenAPI_media_component_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_media_component_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_acceptable_service_info_convertToJSON() failed [acc_bw_med_comps]"); goto end; @@ -103,12 +105,15 @@ OpenAPI_acceptable_service_info_t *OpenAPI_acceptable_service_info_parseFromJSON OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(acc_bw_med_comps_local_map, acc_bw_med_comps) { cJSON *localMapObject = acc_bw_med_comps_local_map; - if (!cJSON_IsObject(acc_bw_med_comps_local_map)) { + if (cJSON_IsObject(acc_bw_med_comps_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_media_component_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(acc_bw_med_comps_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_acceptable_service_info_parseFromJSON() failed [acc_bw_med_comps]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_media_component_parseFromJSON(localMapObject)); OpenAPI_list_add(acc_bw_med_compsList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/am_policy_data.c b/lib/sbi/openapi/model/am_policy_data.c index 83161adfa..8643a3b35 100644 --- a/lib/sbi/openapi/model/am_policy_data.c +++ b/lib/sbi/openapi/model/am_policy_data.c @@ -59,7 +59,9 @@ cJSON *OpenAPI_am_policy_data_convertToJSON(OpenAPI_am_policy_data_t *am_policy_ if (am_policy_data->pra_infos) { OpenAPI_list_for_each(am_policy_data->pra_infos, pra_infos_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)pra_infos_node->data; - cJSON *itemLocal = OpenAPI_presence_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_presence_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_am_policy_data_convertToJSON() failed [pra_infos]"); goto end; @@ -105,12 +107,15 @@ OpenAPI_am_policy_data_t *OpenAPI_am_policy_data_parseFromJSON(cJSON *am_policy_ OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(pra_infos_local_map, pra_infos) { cJSON *localMapObject = pra_infos_local_map; - if (!cJSON_IsObject(pra_infos_local_map)) { + if (cJSON_IsObject(pra_infos_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_presence_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(pra_infos_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_am_policy_data_parseFromJSON() failed [pra_infos]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_presence_info_parseFromJSON(localMapObject)); OpenAPI_list_add(pra_infosList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/app_session_context_req_data.c b/lib/sbi/openapi/model/app_session_context_req_data.c index 059088c90..5580429b2 100644 --- a/lib/sbi/openapi/model/app_session_context_req_data.c +++ b/lib/sbi/openapi/model/app_session_context_req_data.c @@ -223,7 +223,9 @@ cJSON *OpenAPI_app_session_context_req_data_convertToJSON(OpenAPI_app_session_co if (app_session_context_req_data->med_components) { OpenAPI_list_for_each(app_session_context_req_data->med_components, med_components_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)med_components_node->data; - cJSON *itemLocal = OpenAPI_media_component_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_media_component_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_app_session_context_req_data_convertToJSON() failed [med_components]"); goto end; @@ -508,12 +510,15 @@ OpenAPI_app_session_context_req_data_t *OpenAPI_app_session_context_req_data_par OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(med_components_local_map, med_components) { cJSON *localMapObject = med_components_local_map; - if (!cJSON_IsObject(med_components_local_map)) { + if (cJSON_IsObject(med_components_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_media_component_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(med_components_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_app_session_context_req_data_parseFromJSON() failed [med_components]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_media_component_parseFromJSON(localMapObject)); OpenAPI_list_add(med_componentsList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/app_session_context_update_data.c b/lib/sbi/openapi/model/app_session_context_update_data.c index a9ad6cdcc..1ae815d10 100644 --- a/lib/sbi/openapi/model/app_session_context_update_data.c +++ b/lib/sbi/openapi/model/app_session_context_update_data.c @@ -167,7 +167,9 @@ cJSON *OpenAPI_app_session_context_update_data_convertToJSON(OpenAPI_app_session if (app_session_context_update_data->med_components) { OpenAPI_list_for_each(app_session_context_update_data->med_components, med_components_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)med_components_node->data; - cJSON *itemLocal = OpenAPI_media_component_rm_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_media_component_rm_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_app_session_context_update_data_convertToJSON() failed [med_components]"); goto end; @@ -364,12 +366,15 @@ OpenAPI_app_session_context_update_data_t *OpenAPI_app_session_context_update_da OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(med_components_local_map, med_components) { cJSON *localMapObject = med_components_local_map; - if (!cJSON_IsObject(med_components_local_map)) { + if (cJSON_IsObject(med_components_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_media_component_rm_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(med_components_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_app_session_context_update_data_parseFromJSON() failed [med_components]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_media_component_rm_parseFromJSON(localMapObject)); OpenAPI_list_add(med_componentsList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/area_scope.c b/lib/sbi/openapi/model/area_scope.c index 8bc3e84db..1c0f199b2 100644 --- a/lib/sbi/openapi/model/area_scope.c +++ b/lib/sbi/openapi/model/area_scope.c @@ -119,7 +119,9 @@ cJSON *OpenAPI_area_scope_convertToJSON(OpenAPI_area_scope_t *area_scope) if (area_scope->tac_info_per_plmn) { OpenAPI_list_for_each(area_scope->tac_info_per_plmn, tac_info_per_plmn_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)tac_info_per_plmn_node->data; - cJSON *itemLocal = OpenAPI_tac_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_tac_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_area_scope_convertToJSON() failed [tac_info_per_plmn]"); goto end; @@ -209,12 +211,15 @@ OpenAPI_area_scope_t *OpenAPI_area_scope_parseFromJSON(cJSON *area_scopeJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(tac_info_per_plmn_local_map, tac_info_per_plmn) { cJSON *localMapObject = tac_info_per_plmn_local_map; - if (!cJSON_IsObject(tac_info_per_plmn_local_map)) { + if (cJSON_IsObject(tac_info_per_plmn_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_tac_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(tac_info_per_plmn_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_area_scope_parseFromJSON() failed [tac_info_per_plmn]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_tac_info_parseFromJSON(localMapObject)); OpenAPI_list_add(tac_info_per_plmnList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/cag_data.c b/lib/sbi/openapi/model/cag_data.c index cc815b779..021e2bb56 100644 --- a/lib/sbi/openapi/model/cag_data.c +++ b/lib/sbi/openapi/model/cag_data.c @@ -55,7 +55,9 @@ cJSON *OpenAPI_cag_data_convertToJSON(OpenAPI_cag_data_t *cag_data) if (cag_data->cag_infos) { OpenAPI_list_for_each(cag_data->cag_infos, cag_infos_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)cag_infos_node->data; - cJSON *itemLocal = OpenAPI_cag_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_cag_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_cag_data_convertToJSON() failed [cag_infos]"); goto end; @@ -94,12 +96,15 @@ OpenAPI_cag_data_t *OpenAPI_cag_data_parseFromJSON(cJSON *cag_dataJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(cag_infos_local_map, cag_infos) { cJSON *localMapObject = cag_infos_local_map; - if (!cJSON_IsObject(cag_infos_local_map)) { + if (cJSON_IsObject(cag_infos_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_cag_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(cag_infos_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_cag_data_parseFromJSON() failed [cag_infos]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_cag_info_parseFromJSON(localMapObject)); OpenAPI_list_add(cag_infosList , localMapKeyPair); } diff --git a/lib/sbi/openapi/model/cag_data_1.c b/lib/sbi/openapi/model/cag_data_1.c index fb03069de..3d73967b8 100644 --- a/lib/sbi/openapi/model/cag_data_1.c +++ b/lib/sbi/openapi/model/cag_data_1.c @@ -55,7 +55,9 @@ cJSON *OpenAPI_cag_data_1_convertToJSON(OpenAPI_cag_data_1_t *cag_data_1) if (cag_data_1->cag_infos) { OpenAPI_list_for_each(cag_data_1->cag_infos, cag_infos_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)cag_infos_node->data; - cJSON *itemLocal = OpenAPI_cag_info_1_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_cag_info_1_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_cag_data_1_convertToJSON() failed [cag_infos]"); goto end; @@ -94,12 +96,15 @@ OpenAPI_cag_data_1_t *OpenAPI_cag_data_1_parseFromJSON(cJSON *cag_data_1JSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(cag_infos_local_map, cag_infos) { cJSON *localMapObject = cag_infos_local_map; - if (!cJSON_IsObject(cag_infos_local_map)) { + if (cJSON_IsObject(cag_infos_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_cag_info_1_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(cag_infos_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_cag_data_1_parseFromJSON() failed [cag_infos]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_cag_info_1_parseFromJSON(localMapObject)); OpenAPI_list_add(cag_infosList , localMapKeyPair); } diff --git a/lib/sbi/openapi/model/eap_session.c b/lib/sbi/openapi/model/eap_session.c index dfd7885fc..a42c61351 100644 --- a/lib/sbi/openapi/model/eap_session.c +++ b/lib/sbi/openapi/model/eap_session.c @@ -79,7 +79,9 @@ cJSON *OpenAPI_eap_session_convertToJSON(OpenAPI_eap_session_t *eap_session) if (eap_session->_links) { OpenAPI_list_for_each(eap_session->_links, _links_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)_links_node->data; - cJSON *itemLocal = OpenAPI_links_value_schema_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_links_value_schema_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_eap_session_convertToJSON() failed [_links]"); goto end; @@ -150,12 +152,15 @@ OpenAPI_eap_session_t *OpenAPI_eap_session_parseFromJSON(cJSON *eap_sessionJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(_links_local_map, _links) { cJSON *localMapObject = _links_local_map; - if (!cJSON_IsObject(_links_local_map)) { + if (cJSON_IsObject(_links_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_links_value_schema_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(_links_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_eap_session_parseFromJSON() failed [_links]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_links_value_schema_parseFromJSON(localMapObject)); OpenAPI_list_add(_linksList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/ee_subscription.c b/lib/sbi/openapi/model/ee_subscription.c index aba0d8b45..4025886c8 100644 --- a/lib/sbi/openapi/model/ee_subscription.c +++ b/lib/sbi/openapi/model/ee_subscription.c @@ -85,7 +85,9 @@ cJSON *OpenAPI_ee_subscription_convertToJSON(OpenAPI_ee_subscription_t *ee_subsc if (ee_subscription->monitoring_configurations) { OpenAPI_list_for_each(ee_subscription->monitoring_configurations, monitoring_configurations_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)monitoring_configurations_node->data; - cJSON *itemLocal = OpenAPI_monitoring_configuration_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_monitoring_configuration_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_ee_subscription_convertToJSON() failed [monitoring_configurations]"); goto end; @@ -196,12 +198,15 @@ OpenAPI_ee_subscription_t *OpenAPI_ee_subscription_parseFromJSON(cJSON *ee_subsc OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(monitoring_configurations_local_map, monitoring_configurations) { cJSON *localMapObject = monitoring_configurations_local_map; - if (!cJSON_IsObject(monitoring_configurations_local_map)) { + if (cJSON_IsObject(monitoring_configurations_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_monitoring_configuration_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(monitoring_configurations_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_ee_subscription_parseFromJSON() failed [monitoring_configurations]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_monitoring_configuration_parseFromJSON(localMapObject)); OpenAPI_list_add(monitoring_configurationsList , localMapKeyPair); } diff --git a/lib/sbi/openapi/model/eps_interworking_info.c b/lib/sbi/openapi/model/eps_interworking_info.c index 195997ab3..3e2803e7f 100644 --- a/lib/sbi/openapi/model/eps_interworking_info.c +++ b/lib/sbi/openapi/model/eps_interworking_info.c @@ -53,7 +53,9 @@ cJSON *OpenAPI_eps_interworking_info_convertToJSON(OpenAPI_eps_interworking_info if (eps_interworking_info->eps_iwk_pgws) { OpenAPI_list_for_each(eps_interworking_info->eps_iwk_pgws, eps_iwk_pgws_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)eps_iwk_pgws_node->data; - cJSON *itemLocal = OpenAPI_eps_iwk_pgw_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_eps_iwk_pgw_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_eps_interworking_info_convertToJSON() failed [eps_iwk_pgws]"); goto end; @@ -83,12 +85,15 @@ OpenAPI_eps_interworking_info_t *OpenAPI_eps_interworking_info_parseFromJSON(cJS OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(eps_iwk_pgws_local_map, eps_iwk_pgws) { cJSON *localMapObject = eps_iwk_pgws_local_map; - if (!cJSON_IsObject(eps_iwk_pgws_local_map)) { + if (cJSON_IsObject(eps_iwk_pgws_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_eps_iwk_pgw_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(eps_iwk_pgws_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_eps_interworking_info_parseFromJSON() failed [eps_iwk_pgws]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_eps_iwk_pgw_parseFromJSON(localMapObject)); OpenAPI_list_add(eps_iwk_pgwsList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/inline_response_200.c b/lib/sbi/openapi/model/inline_response_200.c index 7b43a013b..3395b0b0a 100644 --- a/lib/sbi/openapi/model/inline_response_200.c +++ b/lib/sbi/openapi/model/inline_response_200.c @@ -53,7 +53,9 @@ cJSON *OpenAPI_inline_response_200_convertToJSON(OpenAPI_inline_response_200_t * if (inline_response_200->_links) { OpenAPI_list_for_each(inline_response_200->_links, _links_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)_links_node->data; - cJSON *itemLocal = OpenAPI_links_value_schema_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_links_value_schema_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_inline_response_200_convertToJSON() failed [_links]"); goto end; @@ -83,12 +85,15 @@ OpenAPI_inline_response_200_t *OpenAPI_inline_response_200_parseFromJSON(cJSON * OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(_links_local_map, _links) { cJSON *localMapObject = _links_local_map; - if (!cJSON_IsObject(_links_local_map)) { + if (cJSON_IsObject(_links_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_links_value_schema_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(_links_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_inline_response_200_parseFromJSON() failed [_links]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_links_value_schema_parseFromJSON(localMapObject)); OpenAPI_list_add(_linksList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/iptv_config_data.c b/lib/sbi/openapi/model/iptv_config_data.c index 852a95dd9..2a3b34842 100644 --- a/lib/sbi/openapi/model/iptv_config_data.c +++ b/lib/sbi/openapi/model/iptv_config_data.c @@ -112,7 +112,9 @@ cJSON *OpenAPI_iptv_config_data_convertToJSON(OpenAPI_iptv_config_data_t *iptv_c if (iptv_config_data->multi_acc_ctrls) { OpenAPI_list_for_each(iptv_config_data->multi_acc_ctrls, multi_acc_ctrls_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)multi_acc_ctrls_node->data; - cJSON *itemLocal = OpenAPI_multicast_access_control_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_multicast_access_control_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_iptv_config_data_convertToJSON() failed [multi_acc_ctrls]"); goto end; @@ -203,12 +205,15 @@ OpenAPI_iptv_config_data_t *OpenAPI_iptv_config_data_parseFromJSON(cJSON *iptv_c OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(multi_acc_ctrls_local_map, multi_acc_ctrls) { cJSON *localMapObject = multi_acc_ctrls_local_map; - if (!cJSON_IsObject(multi_acc_ctrls_local_map)) { + if (cJSON_IsObject(multi_acc_ctrls_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_multicast_access_control_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(multi_acc_ctrls_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_iptv_config_data_parseFromJSON() failed [multi_acc_ctrls]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_multicast_access_control_parseFromJSON(localMapObject)); OpenAPI_list_add(multi_acc_ctrlsList , localMapKeyPair); } diff --git a/lib/sbi/openapi/model/iptv_config_data_patch.c b/lib/sbi/openapi/model/iptv_config_data_patch.c index 0348e244f..11f4b0975 100644 --- a/lib/sbi/openapi/model/iptv_config_data_patch.c +++ b/lib/sbi/openapi/model/iptv_config_data_patch.c @@ -53,7 +53,9 @@ cJSON *OpenAPI_iptv_config_data_patch_convertToJSON(OpenAPI_iptv_config_data_pat if (iptv_config_data_patch->multi_acc_ctrls) { OpenAPI_list_for_each(iptv_config_data_patch->multi_acc_ctrls, multi_acc_ctrls_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)multi_acc_ctrls_node->data; - cJSON *itemLocal = OpenAPI_multicast_access_control_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_multicast_access_control_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_iptv_config_data_patch_convertToJSON() failed [multi_acc_ctrls]"); goto end; @@ -83,12 +85,15 @@ OpenAPI_iptv_config_data_patch_t *OpenAPI_iptv_config_data_patch_parseFromJSON(c OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(multi_acc_ctrls_local_map, multi_acc_ctrls) { cJSON *localMapObject = multi_acc_ctrls_local_map; - if (!cJSON_IsObject(multi_acc_ctrls_local_map)) { + if (cJSON_IsObject(multi_acc_ctrls_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_multicast_access_control_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(multi_acc_ctrls_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_iptv_config_data_patch_parseFromJSON() failed [multi_acc_ctrls]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_multicast_access_control_parseFromJSON(localMapObject)); OpenAPI_list_add(multi_acc_ctrlsList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/media_component.c b/lib/sbi/openapi/model/media_component.c index adbd6cfed..c92bf12dd 100644 --- a/lib/sbi/openapi/model/media_component.c +++ b/lib/sbi/openapi/model/media_component.c @@ -310,7 +310,9 @@ cJSON *OpenAPI_media_component_convertToJSON(OpenAPI_media_component_t *media_co if (media_component->med_sub_comps) { OpenAPI_list_for_each(media_component->med_sub_comps, med_sub_comps_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)med_sub_comps_node->data; - cJSON *itemLocal = OpenAPI_media_sub_component_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_media_sub_component_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_media_component_convertToJSON() failed [med_sub_comps]"); goto end; @@ -656,12 +658,15 @@ OpenAPI_media_component_t *OpenAPI_media_component_parseFromJSON(cJSON *media_co OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(med_sub_comps_local_map, med_sub_comps) { cJSON *localMapObject = med_sub_comps_local_map; - if (!cJSON_IsObject(med_sub_comps_local_map)) { + if (cJSON_IsObject(med_sub_comps_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_media_sub_component_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(med_sub_comps_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_media_component_parseFromJSON() failed [med_sub_comps]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_media_sub_component_parseFromJSON(localMapObject)); OpenAPI_list_add(med_sub_compsList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/media_component_rm.c b/lib/sbi/openapi/model/media_component_rm.c index c44a0d6e3..d4578221a 100644 --- a/lib/sbi/openapi/model/media_component_rm.c +++ b/lib/sbi/openapi/model/media_component_rm.c @@ -312,7 +312,9 @@ cJSON *OpenAPI_media_component_rm_convertToJSON(OpenAPI_media_component_rm_t *me if (media_component_rm->med_sub_comps) { OpenAPI_list_for_each(media_component_rm->med_sub_comps, med_sub_comps_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)med_sub_comps_node->data; - cJSON *itemLocal = OpenAPI_media_sub_component_rm_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_media_sub_component_rm_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_media_component_rm_convertToJSON() failed [med_sub_comps]"); goto end; @@ -670,12 +672,15 @@ OpenAPI_media_component_rm_t *OpenAPI_media_component_rm_parseFromJSON(cJSON *me OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(med_sub_comps_local_map, med_sub_comps) { cJSON *localMapObject = med_sub_comps_local_map; - if (!cJSON_IsObject(med_sub_comps_local_map)) { + if (cJSON_IsObject(med_sub_comps_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_media_sub_component_rm_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(med_sub_comps_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_media_component_rm_parseFromJSON() failed [med_sub_comps]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_media_sub_component_rm_parseFromJSON(localMapObject)); OpenAPI_list_add(med_sub_compsList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/nf_profile.c b/lib/sbi/openapi/model/nf_profile.c index 015051305..34aa722ec 100644 --- a/lib/sbi/openapi/model/nf_profile.c +++ b/lib/sbi/openapi/model/nf_profile.c @@ -686,7 +686,9 @@ cJSON *OpenAPI_nf_profile_convertToJSON(OpenAPI_nf_profile_t *nf_profile) if (nf_profile->udr_info_list) { OpenAPI_list_for_each(nf_profile->udr_info_list, udr_info_list_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)udr_info_list_node->data; - cJSON *itemLocal = OpenAPI_udr_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_udr_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nf_profile_convertToJSON() failed [udr_info_list]"); goto end; @@ -720,7 +722,9 @@ cJSON *OpenAPI_nf_profile_convertToJSON(OpenAPI_nf_profile_t *nf_profile) if (nf_profile->udm_info_list) { OpenAPI_list_for_each(nf_profile->udm_info_list, udm_info_list_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)udm_info_list_node->data; - cJSON *itemLocal = OpenAPI_udm_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_udm_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nf_profile_convertToJSON() failed [udm_info_list]"); goto end; @@ -754,7 +758,9 @@ cJSON *OpenAPI_nf_profile_convertToJSON(OpenAPI_nf_profile_t *nf_profile) if (nf_profile->ausf_info_list) { OpenAPI_list_for_each(nf_profile->ausf_info_list, ausf_info_list_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)ausf_info_list_node->data; - cJSON *itemLocal = OpenAPI_ausf_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_ausf_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nf_profile_convertToJSON() failed [ausf_info_list]"); goto end; @@ -788,7 +794,9 @@ cJSON *OpenAPI_nf_profile_convertToJSON(OpenAPI_nf_profile_t *nf_profile) if (nf_profile->amf_info_list) { OpenAPI_list_for_each(nf_profile->amf_info_list, amf_info_list_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)amf_info_list_node->data; - cJSON *itemLocal = OpenAPI_amf_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_amf_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nf_profile_convertToJSON() failed [amf_info_list]"); goto end; @@ -822,7 +830,9 @@ cJSON *OpenAPI_nf_profile_convertToJSON(OpenAPI_nf_profile_t *nf_profile) if (nf_profile->smf_info_list) { OpenAPI_list_for_each(nf_profile->smf_info_list, smf_info_list_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)smf_info_list_node->data; - cJSON *itemLocal = OpenAPI_smf_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_smf_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nf_profile_convertToJSON() failed [smf_info_list]"); goto end; @@ -856,7 +866,9 @@ cJSON *OpenAPI_nf_profile_convertToJSON(OpenAPI_nf_profile_t *nf_profile) if (nf_profile->upf_info_list) { OpenAPI_list_for_each(nf_profile->upf_info_list, upf_info_list_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)upf_info_list_node->data; - cJSON *itemLocal = OpenAPI_upf_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_upf_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nf_profile_convertToJSON() failed [upf_info_list]"); goto end; @@ -890,7 +902,9 @@ cJSON *OpenAPI_nf_profile_convertToJSON(OpenAPI_nf_profile_t *nf_profile) if (nf_profile->pcf_info_list) { OpenAPI_list_for_each(nf_profile->pcf_info_list, pcf_info_list_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)pcf_info_list_node->data; - cJSON *itemLocal = OpenAPI_pcf_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_pcf_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nf_profile_convertToJSON() failed [pcf_info_list]"); goto end; @@ -924,7 +938,9 @@ cJSON *OpenAPI_nf_profile_convertToJSON(OpenAPI_nf_profile_t *nf_profile) if (nf_profile->bsf_info_list) { OpenAPI_list_for_each(nf_profile->bsf_info_list, bsf_info_list_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)bsf_info_list_node->data; - cJSON *itemLocal = OpenAPI_bsf_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_bsf_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nf_profile_convertToJSON() failed [bsf_info_list]"); goto end; @@ -958,7 +974,9 @@ cJSON *OpenAPI_nf_profile_convertToJSON(OpenAPI_nf_profile_t *nf_profile) if (nf_profile->chf_info_list) { OpenAPI_list_for_each(nf_profile->chf_info_list, chf_info_list_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)chf_info_list_node->data; - cJSON *itemLocal = OpenAPI_chf_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_chf_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nf_profile_convertToJSON() failed [chf_info_list]"); goto end; @@ -1018,7 +1036,9 @@ cJSON *OpenAPI_nf_profile_convertToJSON(OpenAPI_nf_profile_t *nf_profile) if (nf_profile->udsf_info_list) { OpenAPI_list_for_each(nf_profile->udsf_info_list, udsf_info_list_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)udsf_info_list_node->data; - cJSON *itemLocal = OpenAPI_udsf_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_udsf_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nf_profile_convertToJSON() failed [udsf_info_list]"); goto end; @@ -1052,7 +1072,9 @@ cJSON *OpenAPI_nf_profile_convertToJSON(OpenAPI_nf_profile_t *nf_profile) if (nf_profile->pcscf_info_list) { OpenAPI_list_for_each(nf_profile->pcscf_info_list, pcscf_info_list_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)pcscf_info_list_node->data; - cJSON *itemLocal = OpenAPI_pcscf_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_pcscf_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nf_profile_convertToJSON() failed [pcscf_info_list]"); goto end; @@ -1073,7 +1095,9 @@ cJSON *OpenAPI_nf_profile_convertToJSON(OpenAPI_nf_profile_t *nf_profile) if (nf_profile->hss_info_list) { OpenAPI_list_for_each(nf_profile->hss_info_list, hss_info_list_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)hss_info_list_node->data; - cJSON *itemLocal = OpenAPI_hss_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_hss_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nf_profile_convertToJSON() failed [hss_info_list]"); goto end; @@ -1141,7 +1165,9 @@ cJSON *OpenAPI_nf_profile_convertToJSON(OpenAPI_nf_profile_t *nf_profile) if (nf_profile->nf_service_list) { OpenAPI_list_for_each(nf_profile->nf_service_list, nf_service_list_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)nf_service_list_node->data; - cJSON *itemLocal = OpenAPI_nf_service_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_nf_service_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nf_profile_convertToJSON() failed [nf_service_list]"); goto end; @@ -1724,12 +1750,15 @@ OpenAPI_nf_profile_t *OpenAPI_nf_profile_parseFromJSON(cJSON *nf_profileJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(udr_info_list_local_map, udr_info_list) { cJSON *localMapObject = udr_info_list_local_map; - if (!cJSON_IsObject(udr_info_list_local_map)) { + if (cJSON_IsObject(udr_info_list_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_udr_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(udr_info_list_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nf_profile_parseFromJSON() failed [udr_info_list]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_udr_info_parseFromJSON(localMapObject)); OpenAPI_list_add(udr_info_listList , localMapKeyPair); } } @@ -1754,12 +1783,15 @@ OpenAPI_nf_profile_t *OpenAPI_nf_profile_parseFromJSON(cJSON *nf_profileJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(udm_info_list_local_map, udm_info_list) { cJSON *localMapObject = udm_info_list_local_map; - if (!cJSON_IsObject(udm_info_list_local_map)) { + if (cJSON_IsObject(udm_info_list_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_udm_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(udm_info_list_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nf_profile_parseFromJSON() failed [udm_info_list]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_udm_info_parseFromJSON(localMapObject)); OpenAPI_list_add(udm_info_listList , localMapKeyPair); } } @@ -1784,12 +1816,15 @@ OpenAPI_nf_profile_t *OpenAPI_nf_profile_parseFromJSON(cJSON *nf_profileJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(ausf_info_list_local_map, ausf_info_list) { cJSON *localMapObject = ausf_info_list_local_map; - if (!cJSON_IsObject(ausf_info_list_local_map)) { + if (cJSON_IsObject(ausf_info_list_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_ausf_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(ausf_info_list_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nf_profile_parseFromJSON() failed [ausf_info_list]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_ausf_info_parseFromJSON(localMapObject)); OpenAPI_list_add(ausf_info_listList , localMapKeyPair); } } @@ -1814,12 +1849,15 @@ OpenAPI_nf_profile_t *OpenAPI_nf_profile_parseFromJSON(cJSON *nf_profileJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(amf_info_list_local_map, amf_info_list) { cJSON *localMapObject = amf_info_list_local_map; - if (!cJSON_IsObject(amf_info_list_local_map)) { + if (cJSON_IsObject(amf_info_list_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_amf_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(amf_info_list_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nf_profile_parseFromJSON() failed [amf_info_list]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_amf_info_parseFromJSON(localMapObject)); OpenAPI_list_add(amf_info_listList , localMapKeyPair); } } @@ -1844,12 +1882,15 @@ OpenAPI_nf_profile_t *OpenAPI_nf_profile_parseFromJSON(cJSON *nf_profileJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(smf_info_list_local_map, smf_info_list) { cJSON *localMapObject = smf_info_list_local_map; - if (!cJSON_IsObject(smf_info_list_local_map)) { + if (cJSON_IsObject(smf_info_list_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_smf_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(smf_info_list_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nf_profile_parseFromJSON() failed [smf_info_list]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_smf_info_parseFromJSON(localMapObject)); OpenAPI_list_add(smf_info_listList , localMapKeyPair); } } @@ -1874,12 +1915,15 @@ OpenAPI_nf_profile_t *OpenAPI_nf_profile_parseFromJSON(cJSON *nf_profileJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(upf_info_list_local_map, upf_info_list) { cJSON *localMapObject = upf_info_list_local_map; - if (!cJSON_IsObject(upf_info_list_local_map)) { + if (cJSON_IsObject(upf_info_list_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_upf_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(upf_info_list_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nf_profile_parseFromJSON() failed [upf_info_list]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_upf_info_parseFromJSON(localMapObject)); OpenAPI_list_add(upf_info_listList , localMapKeyPair); } } @@ -1904,12 +1948,15 @@ OpenAPI_nf_profile_t *OpenAPI_nf_profile_parseFromJSON(cJSON *nf_profileJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(pcf_info_list_local_map, pcf_info_list) { cJSON *localMapObject = pcf_info_list_local_map; - if (!cJSON_IsObject(pcf_info_list_local_map)) { + if (cJSON_IsObject(pcf_info_list_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_pcf_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(pcf_info_list_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nf_profile_parseFromJSON() failed [pcf_info_list]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_pcf_info_parseFromJSON(localMapObject)); OpenAPI_list_add(pcf_info_listList , localMapKeyPair); } } @@ -1934,12 +1981,15 @@ OpenAPI_nf_profile_t *OpenAPI_nf_profile_parseFromJSON(cJSON *nf_profileJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(bsf_info_list_local_map, bsf_info_list) { cJSON *localMapObject = bsf_info_list_local_map; - if (!cJSON_IsObject(bsf_info_list_local_map)) { + if (cJSON_IsObject(bsf_info_list_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_bsf_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(bsf_info_list_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nf_profile_parseFromJSON() failed [bsf_info_list]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_bsf_info_parseFromJSON(localMapObject)); OpenAPI_list_add(bsf_info_listList , localMapKeyPair); } } @@ -1964,12 +2014,15 @@ OpenAPI_nf_profile_t *OpenAPI_nf_profile_parseFromJSON(cJSON *nf_profileJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(chf_info_list_local_map, chf_info_list) { cJSON *localMapObject = chf_info_list_local_map; - if (!cJSON_IsObject(chf_info_list_local_map)) { + if (cJSON_IsObject(chf_info_list_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_chf_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(chf_info_list_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nf_profile_parseFromJSON() failed [chf_info_list]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_chf_info_parseFromJSON(localMapObject)); OpenAPI_list_add(chf_info_listList , localMapKeyPair); } } @@ -2008,12 +2061,15 @@ OpenAPI_nf_profile_t *OpenAPI_nf_profile_parseFromJSON(cJSON *nf_profileJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(udsf_info_list_local_map, udsf_info_list) { cJSON *localMapObject = udsf_info_list_local_map; - if (!cJSON_IsObject(udsf_info_list_local_map)) { + if (cJSON_IsObject(udsf_info_list_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_udsf_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(udsf_info_list_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nf_profile_parseFromJSON() failed [udsf_info_list]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_udsf_info_parseFromJSON(localMapObject)); OpenAPI_list_add(udsf_info_listList , localMapKeyPair); } } @@ -2038,12 +2094,15 @@ OpenAPI_nf_profile_t *OpenAPI_nf_profile_parseFromJSON(cJSON *nf_profileJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(pcscf_info_list_local_map, pcscf_info_list) { cJSON *localMapObject = pcscf_info_list_local_map; - if (!cJSON_IsObject(pcscf_info_list_local_map)) { + if (cJSON_IsObject(pcscf_info_list_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_pcscf_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(pcscf_info_list_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nf_profile_parseFromJSON() failed [pcscf_info_list]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_pcscf_info_parseFromJSON(localMapObject)); OpenAPI_list_add(pcscf_info_listList , localMapKeyPair); } } @@ -2061,12 +2120,15 @@ OpenAPI_nf_profile_t *OpenAPI_nf_profile_parseFromJSON(cJSON *nf_profileJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(hss_info_list_local_map, hss_info_list) { cJSON *localMapObject = hss_info_list_local_map; - if (!cJSON_IsObject(hss_info_list_local_map)) { + if (cJSON_IsObject(hss_info_list_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_hss_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(hss_info_list_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nf_profile_parseFromJSON() failed [hss_info_list]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_hss_info_parseFromJSON(localMapObject)); OpenAPI_list_add(hss_info_listList , localMapKeyPair); } } @@ -2132,12 +2194,15 @@ OpenAPI_nf_profile_t *OpenAPI_nf_profile_parseFromJSON(cJSON *nf_profileJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(nf_service_list_local_map, nf_service_list) { cJSON *localMapObject = nf_service_list_local_map; - if (!cJSON_IsObject(nf_service_list_local_map)) { + if (cJSON_IsObject(nf_service_list_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_nf_service_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(nf_service_list_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nf_profile_parseFromJSON() failed [nf_service_list]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_nf_service_parseFromJSON(localMapObject)); OpenAPI_list_add(nf_service_listList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/nrf_info.c b/lib/sbi/openapi/model/nrf_info.c index 3445804e4..fe37da8e6 100644 --- a/lib/sbi/openapi/model/nrf_info.c +++ b/lib/sbi/openapi/model/nrf_info.c @@ -269,7 +269,9 @@ cJSON *OpenAPI_nrf_info_convertToJSON(OpenAPI_nrf_info_t *nrf_info) if (nrf_info->served_udr_info) { OpenAPI_list_for_each(nrf_info->served_udr_info, served_udr_info_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)served_udr_info_node->data; - cJSON *itemLocal = OpenAPI_udr_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_udr_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nrf_info_convertToJSON() failed [served_udr_info]"); goto end; @@ -305,7 +307,9 @@ cJSON *OpenAPI_nrf_info_convertToJSON(OpenAPI_nrf_info_t *nrf_info) if (nrf_info->served_udm_info) { OpenAPI_list_for_each(nrf_info->served_udm_info, served_udm_info_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)served_udm_info_node->data; - cJSON *itemLocal = OpenAPI_udm_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_udm_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nrf_info_convertToJSON() failed [served_udm_info]"); goto end; @@ -341,7 +345,9 @@ cJSON *OpenAPI_nrf_info_convertToJSON(OpenAPI_nrf_info_t *nrf_info) if (nrf_info->served_ausf_info) { OpenAPI_list_for_each(nrf_info->served_ausf_info, served_ausf_info_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)served_ausf_info_node->data; - cJSON *itemLocal = OpenAPI_ausf_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_ausf_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nrf_info_convertToJSON() failed [served_ausf_info]"); goto end; @@ -377,7 +383,9 @@ cJSON *OpenAPI_nrf_info_convertToJSON(OpenAPI_nrf_info_t *nrf_info) if (nrf_info->served_amf_info) { OpenAPI_list_for_each(nrf_info->served_amf_info, served_amf_info_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)served_amf_info_node->data; - cJSON *itemLocal = OpenAPI_amf_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_amf_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nrf_info_convertToJSON() failed [served_amf_info]"); goto end; @@ -413,7 +421,9 @@ cJSON *OpenAPI_nrf_info_convertToJSON(OpenAPI_nrf_info_t *nrf_info) if (nrf_info->served_smf_info) { OpenAPI_list_for_each(nrf_info->served_smf_info, served_smf_info_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)served_smf_info_node->data; - cJSON *itemLocal = OpenAPI_smf_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_smf_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nrf_info_convertToJSON() failed [served_smf_info]"); goto end; @@ -449,7 +459,9 @@ cJSON *OpenAPI_nrf_info_convertToJSON(OpenAPI_nrf_info_t *nrf_info) if (nrf_info->served_upf_info) { OpenAPI_list_for_each(nrf_info->served_upf_info, served_upf_info_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)served_upf_info_node->data; - cJSON *itemLocal = OpenAPI_upf_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_upf_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nrf_info_convertToJSON() failed [served_upf_info]"); goto end; @@ -485,7 +497,9 @@ cJSON *OpenAPI_nrf_info_convertToJSON(OpenAPI_nrf_info_t *nrf_info) if (nrf_info->served_pcf_info) { OpenAPI_list_for_each(nrf_info->served_pcf_info, served_pcf_info_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)served_pcf_info_node->data; - cJSON *itemLocal = OpenAPI_pcf_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_pcf_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nrf_info_convertToJSON() failed [served_pcf_info]"); goto end; @@ -521,7 +535,9 @@ cJSON *OpenAPI_nrf_info_convertToJSON(OpenAPI_nrf_info_t *nrf_info) if (nrf_info->served_bsf_info) { OpenAPI_list_for_each(nrf_info->served_bsf_info, served_bsf_info_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)served_bsf_info_node->data; - cJSON *itemLocal = OpenAPI_bsf_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_bsf_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nrf_info_convertToJSON() failed [served_bsf_info]"); goto end; @@ -557,7 +573,9 @@ cJSON *OpenAPI_nrf_info_convertToJSON(OpenAPI_nrf_info_t *nrf_info) if (nrf_info->served_chf_info) { OpenAPI_list_for_each(nrf_info->served_chf_info, served_chf_info_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)served_chf_info_node->data; - cJSON *itemLocal = OpenAPI_chf_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_chf_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nrf_info_convertToJSON() failed [served_chf_info]"); goto end; @@ -593,7 +611,9 @@ cJSON *OpenAPI_nrf_info_convertToJSON(OpenAPI_nrf_info_t *nrf_info) if (nrf_info->served_nef_info) { OpenAPI_list_for_each(nrf_info->served_nef_info, served_nef_info_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)served_nef_info_node->data; - cJSON *itemLocal = OpenAPI_nef_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_nef_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nrf_info_convertToJSON() failed [served_nef_info]"); goto end; @@ -614,7 +634,9 @@ cJSON *OpenAPI_nrf_info_convertToJSON(OpenAPI_nrf_info_t *nrf_info) if (nrf_info->served_nwdaf_info) { OpenAPI_list_for_each(nrf_info->served_nwdaf_info, served_nwdaf_info_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)served_nwdaf_info_node->data; - cJSON *itemLocal = OpenAPI_nwdaf_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_nwdaf_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nrf_info_convertToJSON() failed [served_nwdaf_info]"); goto end; @@ -650,7 +672,9 @@ cJSON *OpenAPI_nrf_info_convertToJSON(OpenAPI_nrf_info_t *nrf_info) if (nrf_info->served_gmlc_info) { OpenAPI_list_for_each(nrf_info->served_gmlc_info, served_gmlc_info_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)served_gmlc_info_node->data; - cJSON *itemLocal = OpenAPI_gmlc_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_gmlc_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nrf_info_convertToJSON() failed [served_gmlc_info]"); goto end; @@ -671,7 +695,9 @@ cJSON *OpenAPI_nrf_info_convertToJSON(OpenAPI_nrf_info_t *nrf_info) if (nrf_info->served_lmf_info) { OpenAPI_list_for_each(nrf_info->served_lmf_info, served_lmf_info_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)served_lmf_info_node->data; - cJSON *itemLocal = OpenAPI_lmf_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_lmf_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nrf_info_convertToJSON() failed [served_lmf_info]"); goto end; @@ -692,7 +718,9 @@ cJSON *OpenAPI_nrf_info_convertToJSON(OpenAPI_nrf_info_t *nrf_info) if (nrf_info->served_nf_info) { OpenAPI_list_for_each(nrf_info->served_nf_info, served_nf_info_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)served_nf_info_node->data; - cJSON *itemLocal = OpenAPI_nf_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_nf_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nrf_info_convertToJSON() failed [served_nf_info]"); goto end; @@ -728,7 +756,9 @@ cJSON *OpenAPI_nrf_info_convertToJSON(OpenAPI_nrf_info_t *nrf_info) if (nrf_info->served_udsf_info) { OpenAPI_list_for_each(nrf_info->served_udsf_info, served_udsf_info_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)served_udsf_info_node->data; - cJSON *itemLocal = OpenAPI_udsf_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_udsf_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nrf_info_convertToJSON() failed [served_udsf_info]"); goto end; @@ -764,7 +794,9 @@ cJSON *OpenAPI_nrf_info_convertToJSON(OpenAPI_nrf_info_t *nrf_info) if (nrf_info->served_scp_info_list) { OpenAPI_list_for_each(nrf_info->served_scp_info_list, served_scp_info_list_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)served_scp_info_list_node->data; - cJSON *itemLocal = OpenAPI_scp_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_scp_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nrf_info_convertToJSON() failed [served_scp_info_list]"); goto end; @@ -794,12 +826,15 @@ OpenAPI_nrf_info_t *OpenAPI_nrf_info_parseFromJSON(cJSON *nrf_infoJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(served_udr_info_local_map, served_udr_info) { cJSON *localMapObject = served_udr_info_local_map; - if (!cJSON_IsObject(served_udr_info_local_map)) { + if (cJSON_IsObject(served_udr_info_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_udr_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(served_udr_info_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nrf_info_parseFromJSON() failed [served_udr_info]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_udr_info_parseFromJSON(localMapObject)); OpenAPI_list_add(served_udr_infoList , localMapKeyPair); } } @@ -834,12 +869,15 @@ OpenAPI_nrf_info_t *OpenAPI_nrf_info_parseFromJSON(cJSON *nrf_infoJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(served_udm_info_local_map, served_udm_info) { cJSON *localMapObject = served_udm_info_local_map; - if (!cJSON_IsObject(served_udm_info_local_map)) { + if (cJSON_IsObject(served_udm_info_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_udm_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(served_udm_info_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nrf_info_parseFromJSON() failed [served_udm_info]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_udm_info_parseFromJSON(localMapObject)); OpenAPI_list_add(served_udm_infoList , localMapKeyPair); } } @@ -874,12 +912,15 @@ OpenAPI_nrf_info_t *OpenAPI_nrf_info_parseFromJSON(cJSON *nrf_infoJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(served_ausf_info_local_map, served_ausf_info) { cJSON *localMapObject = served_ausf_info_local_map; - if (!cJSON_IsObject(served_ausf_info_local_map)) { + if (cJSON_IsObject(served_ausf_info_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_ausf_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(served_ausf_info_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nrf_info_parseFromJSON() failed [served_ausf_info]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_ausf_info_parseFromJSON(localMapObject)); OpenAPI_list_add(served_ausf_infoList , localMapKeyPair); } } @@ -914,12 +955,15 @@ OpenAPI_nrf_info_t *OpenAPI_nrf_info_parseFromJSON(cJSON *nrf_infoJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(served_amf_info_local_map, served_amf_info) { cJSON *localMapObject = served_amf_info_local_map; - if (!cJSON_IsObject(served_amf_info_local_map)) { + if (cJSON_IsObject(served_amf_info_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_amf_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(served_amf_info_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nrf_info_parseFromJSON() failed [served_amf_info]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_amf_info_parseFromJSON(localMapObject)); OpenAPI_list_add(served_amf_infoList , localMapKeyPair); } } @@ -954,12 +998,15 @@ OpenAPI_nrf_info_t *OpenAPI_nrf_info_parseFromJSON(cJSON *nrf_infoJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(served_smf_info_local_map, served_smf_info) { cJSON *localMapObject = served_smf_info_local_map; - if (!cJSON_IsObject(served_smf_info_local_map)) { + if (cJSON_IsObject(served_smf_info_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_smf_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(served_smf_info_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nrf_info_parseFromJSON() failed [served_smf_info]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_smf_info_parseFromJSON(localMapObject)); OpenAPI_list_add(served_smf_infoList , localMapKeyPair); } } @@ -994,12 +1041,15 @@ OpenAPI_nrf_info_t *OpenAPI_nrf_info_parseFromJSON(cJSON *nrf_infoJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(served_upf_info_local_map, served_upf_info) { cJSON *localMapObject = served_upf_info_local_map; - if (!cJSON_IsObject(served_upf_info_local_map)) { + if (cJSON_IsObject(served_upf_info_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_upf_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(served_upf_info_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nrf_info_parseFromJSON() failed [served_upf_info]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_upf_info_parseFromJSON(localMapObject)); OpenAPI_list_add(served_upf_infoList , localMapKeyPair); } } @@ -1034,12 +1084,15 @@ OpenAPI_nrf_info_t *OpenAPI_nrf_info_parseFromJSON(cJSON *nrf_infoJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(served_pcf_info_local_map, served_pcf_info) { cJSON *localMapObject = served_pcf_info_local_map; - if (!cJSON_IsObject(served_pcf_info_local_map)) { + if (cJSON_IsObject(served_pcf_info_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_pcf_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(served_pcf_info_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nrf_info_parseFromJSON() failed [served_pcf_info]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_pcf_info_parseFromJSON(localMapObject)); OpenAPI_list_add(served_pcf_infoList , localMapKeyPair); } } @@ -1074,12 +1127,15 @@ OpenAPI_nrf_info_t *OpenAPI_nrf_info_parseFromJSON(cJSON *nrf_infoJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(served_bsf_info_local_map, served_bsf_info) { cJSON *localMapObject = served_bsf_info_local_map; - if (!cJSON_IsObject(served_bsf_info_local_map)) { + if (cJSON_IsObject(served_bsf_info_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_bsf_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(served_bsf_info_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nrf_info_parseFromJSON() failed [served_bsf_info]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_bsf_info_parseFromJSON(localMapObject)); OpenAPI_list_add(served_bsf_infoList , localMapKeyPair); } } @@ -1114,12 +1170,15 @@ OpenAPI_nrf_info_t *OpenAPI_nrf_info_parseFromJSON(cJSON *nrf_infoJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(served_chf_info_local_map, served_chf_info) { cJSON *localMapObject = served_chf_info_local_map; - if (!cJSON_IsObject(served_chf_info_local_map)) { + if (cJSON_IsObject(served_chf_info_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_chf_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(served_chf_info_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nrf_info_parseFromJSON() failed [served_chf_info]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_chf_info_parseFromJSON(localMapObject)); OpenAPI_list_add(served_chf_infoList , localMapKeyPair); } } @@ -1154,12 +1213,15 @@ OpenAPI_nrf_info_t *OpenAPI_nrf_info_parseFromJSON(cJSON *nrf_infoJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(served_nef_info_local_map, served_nef_info) { cJSON *localMapObject = served_nef_info_local_map; - if (!cJSON_IsObject(served_nef_info_local_map)) { + if (cJSON_IsObject(served_nef_info_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_nef_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(served_nef_info_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nrf_info_parseFromJSON() failed [served_nef_info]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_nef_info_parseFromJSON(localMapObject)); OpenAPI_list_add(served_nef_infoList , localMapKeyPair); } } @@ -1177,12 +1239,15 @@ OpenAPI_nrf_info_t *OpenAPI_nrf_info_parseFromJSON(cJSON *nrf_infoJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(served_nwdaf_info_local_map, served_nwdaf_info) { cJSON *localMapObject = served_nwdaf_info_local_map; - if (!cJSON_IsObject(served_nwdaf_info_local_map)) { + if (cJSON_IsObject(served_nwdaf_info_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_nwdaf_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(served_nwdaf_info_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nrf_info_parseFromJSON() failed [served_nwdaf_info]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_nwdaf_info_parseFromJSON(localMapObject)); OpenAPI_list_add(served_nwdaf_infoList , localMapKeyPair); } } @@ -1217,12 +1282,15 @@ OpenAPI_nrf_info_t *OpenAPI_nrf_info_parseFromJSON(cJSON *nrf_infoJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(served_gmlc_info_local_map, served_gmlc_info) { cJSON *localMapObject = served_gmlc_info_local_map; - if (!cJSON_IsObject(served_gmlc_info_local_map)) { + if (cJSON_IsObject(served_gmlc_info_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_gmlc_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(served_gmlc_info_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nrf_info_parseFromJSON() failed [served_gmlc_info]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_gmlc_info_parseFromJSON(localMapObject)); OpenAPI_list_add(served_gmlc_infoList , localMapKeyPair); } } @@ -1240,12 +1308,15 @@ OpenAPI_nrf_info_t *OpenAPI_nrf_info_parseFromJSON(cJSON *nrf_infoJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(served_lmf_info_local_map, served_lmf_info) { cJSON *localMapObject = served_lmf_info_local_map; - if (!cJSON_IsObject(served_lmf_info_local_map)) { + if (cJSON_IsObject(served_lmf_info_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_lmf_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(served_lmf_info_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nrf_info_parseFromJSON() failed [served_lmf_info]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_lmf_info_parseFromJSON(localMapObject)); OpenAPI_list_add(served_lmf_infoList , localMapKeyPair); } } @@ -1263,12 +1334,15 @@ OpenAPI_nrf_info_t *OpenAPI_nrf_info_parseFromJSON(cJSON *nrf_infoJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(served_nf_info_local_map, served_nf_info) { cJSON *localMapObject = served_nf_info_local_map; - if (!cJSON_IsObject(served_nf_info_local_map)) { + if (cJSON_IsObject(served_nf_info_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_nf_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(served_nf_info_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nrf_info_parseFromJSON() failed [served_nf_info]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_nf_info_parseFromJSON(localMapObject)); OpenAPI_list_add(served_nf_infoList , localMapKeyPair); } } @@ -1303,12 +1377,15 @@ OpenAPI_nrf_info_t *OpenAPI_nrf_info_parseFromJSON(cJSON *nrf_infoJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(served_udsf_info_local_map, served_udsf_info) { cJSON *localMapObject = served_udsf_info_local_map; - if (!cJSON_IsObject(served_udsf_info_local_map)) { + if (cJSON_IsObject(served_udsf_info_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_udsf_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(served_udsf_info_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nrf_info_parseFromJSON() failed [served_udsf_info]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_udsf_info_parseFromJSON(localMapObject)); OpenAPI_list_add(served_udsf_infoList , localMapKeyPair); } } @@ -1343,12 +1420,15 @@ OpenAPI_nrf_info_t *OpenAPI_nrf_info_parseFromJSON(cJSON *nrf_infoJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(served_scp_info_list_local_map, served_scp_info_list) { cJSON *localMapObject = served_scp_info_list_local_map; - if (!cJSON_IsObject(served_scp_info_list_local_map)) { + if (cJSON_IsObject(served_scp_info_list_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_scp_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(served_scp_info_list_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nrf_info_parseFromJSON() failed [served_scp_info_list]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_scp_info_parseFromJSON(localMapObject)); OpenAPI_list_add(served_scp_info_listList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/nssai.c b/lib/sbi/openapi/model/nssai.c index 6c4fe8c22..7bd0454b8 100644 --- a/lib/sbi/openapi/model/nssai.c +++ b/lib/sbi/openapi/model/nssai.c @@ -123,7 +123,9 @@ cJSON *OpenAPI_nssai_convertToJSON(OpenAPI_nssai_t *nssai) if (nssai->additional_snssai_data) { OpenAPI_list_for_each(nssai->additional_snssai_data, additional_snssai_data_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)additional_snssai_data_node->data; - cJSON *itemLocal = OpenAPI_additional_snssai_data_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_additional_snssai_data_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nssai_convertToJSON() failed [additional_snssai_data]"); goto end; @@ -219,12 +221,15 @@ OpenAPI_nssai_t *OpenAPI_nssai_parseFromJSON(cJSON *nssaiJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(additional_snssai_data_local_map, additional_snssai_data) { cJSON *localMapObject = additional_snssai_data_local_map; - if (!cJSON_IsObject(additional_snssai_data_local_map)) { + if (cJSON_IsObject(additional_snssai_data_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_additional_snssai_data_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(additional_snssai_data_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nssai_parseFromJSON() failed [additional_snssai_data]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_additional_snssai_data_parseFromJSON(localMapObject)); OpenAPI_list_add(additional_snssai_dataList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/nssai_1.c b/lib/sbi/openapi/model/nssai_1.c index 4fa6f4ea1..b83f361d0 100644 --- a/lib/sbi/openapi/model/nssai_1.c +++ b/lib/sbi/openapi/model/nssai_1.c @@ -123,7 +123,9 @@ cJSON *OpenAPI_nssai_1_convertToJSON(OpenAPI_nssai_1_t *nssai_1) if (nssai_1->additional_snssai_data) { OpenAPI_list_for_each(nssai_1->additional_snssai_data, additional_snssai_data_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)additional_snssai_data_node->data; - cJSON *itemLocal = OpenAPI_additional_snssai_data_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_additional_snssai_data_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_nssai_1_convertToJSON() failed [additional_snssai_data]"); goto end; @@ -219,12 +221,15 @@ OpenAPI_nssai_1_t *OpenAPI_nssai_1_parseFromJSON(cJSON *nssai_1JSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(additional_snssai_data_local_map, additional_snssai_data) { cJSON *localMapObject = additional_snssai_data_local_map; - if (!cJSON_IsObject(additional_snssai_data_local_map)) { + if (cJSON_IsObject(additional_snssai_data_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_additional_snssai_data_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(additional_snssai_data_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_nssai_1_parseFromJSON() failed [additional_snssai_data]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_additional_snssai_data_parseFromJSON(localMapObject)); OpenAPI_list_add(additional_snssai_dataList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/policy_association.c b/lib/sbi/openapi/model/policy_association.c index e09cfdb76..87468335f 100644 --- a/lib/sbi/openapi/model/policy_association.c +++ b/lib/sbi/openapi/model/policy_association.c @@ -165,7 +165,9 @@ cJSON *OpenAPI_policy_association_convertToJSON(OpenAPI_policy_association_t *po if (policy_association->pras) { OpenAPI_list_for_each(policy_association->pras, pras_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)pras_node->data; - cJSON *itemLocal = OpenAPI_presence_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_presence_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_policy_association_convertToJSON() failed [pras]"); goto end; @@ -266,12 +268,15 @@ OpenAPI_policy_association_t *OpenAPI_policy_association_parseFromJSON(cJSON *po OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(pras_local_map, pras) { cJSON *localMapObject = pras_local_map; - if (!cJSON_IsObject(pras_local_map)) { + if (cJSON_IsObject(pras_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_presence_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(pras_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_policy_association_parseFromJSON() failed [pras]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_presence_info_parseFromJSON(localMapObject)); OpenAPI_list_add(prasList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/policy_association_update_request.c b/lib/sbi/openapi/model/policy_association_update_request.c index 6ea262743..d73a670eb 100644 --- a/lib/sbi/openapi/model/policy_association_update_request.c +++ b/lib/sbi/openapi/model/policy_association_update_request.c @@ -255,7 +255,9 @@ cJSON *OpenAPI_policy_association_update_request_convertToJSON(OpenAPI_policy_as if (policy_association_update_request->pra_statuses) { OpenAPI_list_for_each(policy_association_update_request->pra_statuses, pra_statuses_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)pra_statuses_node->data; - cJSON *itemLocal = OpenAPI_presence_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_presence_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_policy_association_update_request_convertToJSON() failed [pra_statuses]"); goto end; @@ -542,12 +544,15 @@ OpenAPI_policy_association_update_request_t *OpenAPI_policy_association_update_r OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(pra_statuses_local_map, pra_statuses) { cJSON *localMapObject = pra_statuses_local_map; - if (!cJSON_IsObject(pra_statuses_local_map)) { + if (cJSON_IsObject(pra_statuses_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_presence_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(pra_statuses_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_policy_association_update_request_parseFromJSON() failed [pra_statuses]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_presence_info_parseFromJSON(localMapObject)); OpenAPI_list_add(pra_statusesList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/policy_data_change_notification.c b/lib/sbi/openapi/model/policy_data_change_notification.c index f4bf00f3d..7237076e0 100644 --- a/lib/sbi/openapi/model/policy_data_change_notification.c +++ b/lib/sbi/openapi/model/policy_data_change_notification.c @@ -211,7 +211,9 @@ cJSON *OpenAPI_policy_data_change_notification_convertToJSON(OpenAPI_policy_data if (policy_data_change_notification->op_spec_data_map) { OpenAPI_list_for_each(policy_data_change_notification->op_spec_data_map, op_spec_data_map_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)op_spec_data_map_node->data; - cJSON *itemLocal = OpenAPI_operator_specific_data_container_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_operator_specific_data_container_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_policy_data_change_notification_convertToJSON() failed [op_spec_data_map]"); goto end; @@ -381,12 +383,15 @@ OpenAPI_policy_data_change_notification_t *OpenAPI_policy_data_change_notificati OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(op_spec_data_map_local_map, op_spec_data_map) { cJSON *localMapObject = op_spec_data_map_local_map; - if (!cJSON_IsObject(op_spec_data_map_local_map)) { + if (cJSON_IsObject(op_spec_data_map_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_operator_specific_data_container_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(op_spec_data_map_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_policy_data_change_notification_parseFromJSON() failed [op_spec_data_map]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_operator_specific_data_container_parseFromJSON(localMapObject)); OpenAPI_list_add(op_spec_data_mapList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/policy_update.c b/lib/sbi/openapi/model/policy_update.c index c30b5f311..2e8734aaf 100644 --- a/lib/sbi/openapi/model/policy_update.c +++ b/lib/sbi/openapi/model/policy_update.c @@ -154,7 +154,9 @@ cJSON *OpenAPI_policy_update_convertToJSON(OpenAPI_policy_update_t *policy_updat if (policy_update->pras) { OpenAPI_list_for_each(policy_update->pras, pras_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)pras_node->data; - cJSON *itemLocal = OpenAPI_presence_info_rm_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_presence_info_rm_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_policy_update_convertToJSON() failed [pras]"); goto end; @@ -254,12 +256,15 @@ OpenAPI_policy_update_t *OpenAPI_policy_update_parseFromJSON(cJSON *policy_updat OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(pras_local_map, pras) { cJSON *localMapObject = pras_local_map; - if (!cJSON_IsObject(pras_local_map)) { + if (cJSON_IsObject(pras_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_presence_info_rm_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(pras_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_policy_update_parseFromJSON() failed [pras]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_presence_info_rm_parseFromJSON(localMapObject)); OpenAPI_list_add(prasList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/session_management_subscription_data.c b/lib/sbi/openapi/model/session_management_subscription_data.c index 0efc92299..4b7dc1a20 100644 --- a/lib/sbi/openapi/model/session_management_subscription_data.c +++ b/lib/sbi/openapi/model/session_management_subscription_data.c @@ -111,7 +111,9 @@ cJSON *OpenAPI_session_management_subscription_data_convertToJSON(OpenAPI_sessio if (session_management_subscription_data->dnn_configurations) { OpenAPI_list_for_each(session_management_subscription_data->dnn_configurations, dnn_configurations_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)dnn_configurations_node->data; - cJSON *itemLocal = OpenAPI_dnn_configuration_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_dnn_configuration_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_session_management_subscription_data_convertToJSON() failed [dnn_configurations]"); goto end; @@ -197,7 +199,9 @@ cJSON *OpenAPI_session_management_subscription_data_convertToJSON(OpenAPI_sessio if (session_management_subscription_data->expected_ue_behaviours_list) { OpenAPI_list_for_each(session_management_subscription_data->expected_ue_behaviours_list, expected_ue_behaviours_list_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)expected_ue_behaviours_list_node->data; - cJSON *itemLocal = OpenAPI_expected_ue_behaviour_data_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_expected_ue_behaviour_data_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_session_management_subscription_data_convertToJSON() failed [expected_ue_behaviours_list]"); goto end; @@ -218,7 +222,9 @@ cJSON *OpenAPI_session_management_subscription_data_convertToJSON(OpenAPI_sessio if (session_management_subscription_data->suggested_packet_num_dl_list) { OpenAPI_list_for_each(session_management_subscription_data->suggested_packet_num_dl_list, suggested_packet_num_dl_list_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)suggested_packet_num_dl_list_node->data; - cJSON *itemLocal = OpenAPI_suggested_packet_num_dl_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_suggested_packet_num_dl_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_session_management_subscription_data_convertToJSON() failed [suggested_packet_num_dl_list]"); goto end; @@ -264,12 +270,15 @@ OpenAPI_session_management_subscription_data_t *OpenAPI_session_management_subsc OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(dnn_configurations_local_map, dnn_configurations) { cJSON *localMapObject = dnn_configurations_local_map; - if (!cJSON_IsObject(dnn_configurations_local_map)) { + if (cJSON_IsObject(dnn_configurations_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_dnn_configuration_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(dnn_configurations_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_session_management_subscription_data_parseFromJSON() failed [dnn_configurations]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_dnn_configuration_parseFromJSON(localMapObject)); OpenAPI_list_add(dnn_configurationsList , localMapKeyPair); } } @@ -360,12 +369,15 @@ OpenAPI_session_management_subscription_data_t *OpenAPI_session_management_subsc OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(expected_ue_behaviours_list_local_map, expected_ue_behaviours_list) { cJSON *localMapObject = expected_ue_behaviours_list_local_map; - if (!cJSON_IsObject(expected_ue_behaviours_list_local_map)) { + if (cJSON_IsObject(expected_ue_behaviours_list_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_expected_ue_behaviour_data_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(expected_ue_behaviours_list_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_session_management_subscription_data_parseFromJSON() failed [expected_ue_behaviours_list]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_expected_ue_behaviour_data_parseFromJSON(localMapObject)); OpenAPI_list_add(expected_ue_behaviours_listList , localMapKeyPair); } } @@ -383,12 +395,15 @@ OpenAPI_session_management_subscription_data_t *OpenAPI_session_management_subsc OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(suggested_packet_num_dl_list_local_map, suggested_packet_num_dl_list) { cJSON *localMapObject = suggested_packet_num_dl_list_local_map; - if (!cJSON_IsObject(suggested_packet_num_dl_list_local_map)) { + if (cJSON_IsObject(suggested_packet_num_dl_list_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_suggested_packet_num_dl_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(suggested_packet_num_dl_list_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_session_management_subscription_data_parseFromJSON() failed [suggested_packet_num_dl_list]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_suggested_packet_num_dl_parseFromJSON(localMapObject)); OpenAPI_list_add(suggested_packet_num_dl_listList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/session_management_subscription_data_1.c b/lib/sbi/openapi/model/session_management_subscription_data_1.c index 41ea1a84e..2da277125 100644 --- a/lib/sbi/openapi/model/session_management_subscription_data_1.c +++ b/lib/sbi/openapi/model/session_management_subscription_data_1.c @@ -111,7 +111,9 @@ cJSON *OpenAPI_session_management_subscription_data_1_convertToJSON(OpenAPI_sess if (session_management_subscription_data_1->dnn_configurations) { OpenAPI_list_for_each(session_management_subscription_data_1->dnn_configurations, dnn_configurations_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)dnn_configurations_node->data; - cJSON *itemLocal = OpenAPI_dnn_configuration_1_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_dnn_configuration_1_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_session_management_subscription_data_1_convertToJSON() failed [dnn_configurations]"); goto end; @@ -197,7 +199,9 @@ cJSON *OpenAPI_session_management_subscription_data_1_convertToJSON(OpenAPI_sess if (session_management_subscription_data_1->expected_ue_behaviours_list) { OpenAPI_list_for_each(session_management_subscription_data_1->expected_ue_behaviours_list, expected_ue_behaviours_list_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)expected_ue_behaviours_list_node->data; - cJSON *itemLocal = OpenAPI_expected_ue_behaviour_data_1_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_expected_ue_behaviour_data_1_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_session_management_subscription_data_1_convertToJSON() failed [expected_ue_behaviours_list]"); goto end; @@ -218,7 +222,9 @@ cJSON *OpenAPI_session_management_subscription_data_1_convertToJSON(OpenAPI_sess if (session_management_subscription_data_1->suggested_packet_num_dl_list) { OpenAPI_list_for_each(session_management_subscription_data_1->suggested_packet_num_dl_list, suggested_packet_num_dl_list_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)suggested_packet_num_dl_list_node->data; - cJSON *itemLocal = OpenAPI_suggested_packet_num_dl_1_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_suggested_packet_num_dl_1_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_session_management_subscription_data_1_convertToJSON() failed [suggested_packet_num_dl_list]"); goto end; @@ -264,12 +270,15 @@ OpenAPI_session_management_subscription_data_1_t *OpenAPI_session_management_sub OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(dnn_configurations_local_map, dnn_configurations) { cJSON *localMapObject = dnn_configurations_local_map; - if (!cJSON_IsObject(dnn_configurations_local_map)) { + if (cJSON_IsObject(dnn_configurations_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_dnn_configuration_1_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(dnn_configurations_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_session_management_subscription_data_1_parseFromJSON() failed [dnn_configurations]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_dnn_configuration_1_parseFromJSON(localMapObject)); OpenAPI_list_add(dnn_configurationsList , localMapKeyPair); } } @@ -360,12 +369,15 @@ OpenAPI_session_management_subscription_data_1_t *OpenAPI_session_management_sub OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(expected_ue_behaviours_list_local_map, expected_ue_behaviours_list) { cJSON *localMapObject = expected_ue_behaviours_list_local_map; - if (!cJSON_IsObject(expected_ue_behaviours_list_local_map)) { + if (cJSON_IsObject(expected_ue_behaviours_list_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_expected_ue_behaviour_data_1_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(expected_ue_behaviours_list_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_session_management_subscription_data_1_parseFromJSON() failed [expected_ue_behaviours_list]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_expected_ue_behaviour_data_1_parseFromJSON(localMapObject)); OpenAPI_list_add(expected_ue_behaviours_listList , localMapKeyPair); } } @@ -383,12 +395,15 @@ OpenAPI_session_management_subscription_data_1_t *OpenAPI_session_management_sub OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(suggested_packet_num_dl_list_local_map, suggested_packet_num_dl_list) { cJSON *localMapObject = suggested_packet_num_dl_list_local_map; - if (!cJSON_IsObject(suggested_packet_num_dl_list_local_map)) { + if (cJSON_IsObject(suggested_packet_num_dl_list_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_suggested_packet_num_dl_1_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(suggested_packet_num_dl_list_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_session_management_subscription_data_1_parseFromJSON() failed [suggested_packet_num_dl_list]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_suggested_packet_num_dl_1_parseFromJSON(localMapObject)); OpenAPI_list_add(suggested_packet_num_dl_listList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/shared_data.c b/lib/sbi/openapi/model/shared_data.c index f60cadbe3..ab06532d5 100644 --- a/lib/sbi/openapi/model/shared_data.c +++ b/lib/sbi/openapi/model/shared_data.c @@ -128,7 +128,9 @@ cJSON *OpenAPI_shared_data_convertToJSON(OpenAPI_shared_data_t *shared_data) if (shared_data->shared_dnn_configurations) { OpenAPI_list_for_each(shared_data->shared_dnn_configurations, shared_dnn_configurations_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)shared_dnn_configurations_node->data; - cJSON *itemLocal = OpenAPI_dnn_configuration_1_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_dnn_configuration_1_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_shared_data_convertToJSON() failed [shared_dnn_configurations]"); goto end; @@ -162,7 +164,9 @@ cJSON *OpenAPI_shared_data_convertToJSON(OpenAPI_shared_data_t *shared_data) if (shared_data->shared_snssai_infos) { OpenAPI_list_for_each(shared_data->shared_snssai_infos, shared_snssai_infos_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)shared_snssai_infos_node->data; - cJSON *itemLocal = OpenAPI_snssai_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_snssai_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_shared_data_convertToJSON() failed [shared_snssai_infos]"); goto end; @@ -183,7 +187,9 @@ cJSON *OpenAPI_shared_data_convertToJSON(OpenAPI_shared_data_t *shared_data) if (shared_data->shared_vn_group_datas) { OpenAPI_list_for_each(shared_data->shared_vn_group_datas, shared_vn_group_datas_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)shared_vn_group_datas_node->data; - cJSON *itemLocal = OpenAPI_vn_group_data_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_vn_group_data_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_shared_data_convertToJSON() failed [shared_vn_group_datas]"); goto end; @@ -245,12 +251,15 @@ OpenAPI_shared_data_t *OpenAPI_shared_data_parseFromJSON(cJSON *shared_dataJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(shared_dnn_configurations_local_map, shared_dnn_configurations) { cJSON *localMapObject = shared_dnn_configurations_local_map; - if (!cJSON_IsObject(shared_dnn_configurations_local_map)) { + if (cJSON_IsObject(shared_dnn_configurations_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_dnn_configuration_1_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(shared_dnn_configurations_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_shared_data_parseFromJSON() failed [shared_dnn_configurations]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_dnn_configuration_1_parseFromJSON(localMapObject)); OpenAPI_list_add(shared_dnn_configurationsList , localMapKeyPair); } } @@ -275,12 +284,15 @@ OpenAPI_shared_data_t *OpenAPI_shared_data_parseFromJSON(cJSON *shared_dataJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(shared_snssai_infos_local_map, shared_snssai_infos) { cJSON *localMapObject = shared_snssai_infos_local_map; - if (!cJSON_IsObject(shared_snssai_infos_local_map)) { + if (cJSON_IsObject(shared_snssai_infos_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_snssai_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(shared_snssai_infos_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_shared_data_parseFromJSON() failed [shared_snssai_infos]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_snssai_info_parseFromJSON(localMapObject)); OpenAPI_list_add(shared_snssai_infosList , localMapKeyPair); } } @@ -298,12 +310,15 @@ OpenAPI_shared_data_t *OpenAPI_shared_data_parseFromJSON(cJSON *shared_dataJSON) OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(shared_vn_group_datas_local_map, shared_vn_group_datas) { cJSON *localMapObject = shared_vn_group_datas_local_map; - if (!cJSON_IsObject(shared_vn_group_datas_local_map)) { + if (cJSON_IsObject(shared_vn_group_datas_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_vn_group_data_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(shared_vn_group_datas_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_shared_data_parseFromJSON() failed [shared_vn_group_datas]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_vn_group_data_parseFromJSON(localMapObject)); OpenAPI_list_add(shared_vn_group_datasList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/sm_policy_data.c b/lib/sbi/openapi/model/sm_policy_data.c index c7f02948e..b4623db99 100644 --- a/lib/sbi/openapi/model/sm_policy_data.c +++ b/lib/sbi/openapi/model/sm_policy_data.c @@ -71,7 +71,9 @@ cJSON *OpenAPI_sm_policy_data_convertToJSON(OpenAPI_sm_policy_data_t *sm_policy_ if (sm_policy_data->sm_policy_snssai_data) { OpenAPI_list_for_each(sm_policy_data->sm_policy_snssai_data, sm_policy_snssai_data_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)sm_policy_snssai_data_node->data; - cJSON *itemLocal = OpenAPI_sm_policy_snssai_data_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_sm_policy_snssai_data_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_sm_policy_data_convertToJSON() failed [sm_policy_snssai_data]"); goto end; @@ -91,7 +93,9 @@ cJSON *OpenAPI_sm_policy_data_convertToJSON(OpenAPI_sm_policy_data_t *sm_policy_ if (sm_policy_data->um_data_limits) { OpenAPI_list_for_each(sm_policy_data->um_data_limits, um_data_limits_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)um_data_limits_node->data; - cJSON *itemLocal = OpenAPI_usage_mon_data_limit_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_usage_mon_data_limit_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_sm_policy_data_convertToJSON() failed [um_data_limits]"); goto end; @@ -112,7 +116,9 @@ cJSON *OpenAPI_sm_policy_data_convertToJSON(OpenAPI_sm_policy_data_t *sm_policy_ if (sm_policy_data->um_data) { OpenAPI_list_for_each(sm_policy_data->um_data, um_data_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)um_data_node->data; - cJSON *itemLocal = OpenAPI_usage_mon_data_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_usage_mon_data_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_sm_policy_data_convertToJSON() failed [um_data]"); goto end; @@ -152,12 +158,15 @@ OpenAPI_sm_policy_data_t *OpenAPI_sm_policy_data_parseFromJSON(cJSON *sm_policy_ OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(sm_policy_snssai_data_local_map, sm_policy_snssai_data) { cJSON *localMapObject = sm_policy_snssai_data_local_map; - if (!cJSON_IsObject(sm_policy_snssai_data_local_map)) { + if (cJSON_IsObject(sm_policy_snssai_data_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_sm_policy_snssai_data_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(sm_policy_snssai_data_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_sm_policy_data_parseFromJSON() failed [sm_policy_snssai_data]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_sm_policy_snssai_data_parseFromJSON(localMapObject)); OpenAPI_list_add(sm_policy_snssai_dataList , localMapKeyPair); } @@ -174,12 +183,15 @@ OpenAPI_sm_policy_data_t *OpenAPI_sm_policy_data_parseFromJSON(cJSON *sm_policy_ OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(um_data_limits_local_map, um_data_limits) { cJSON *localMapObject = um_data_limits_local_map; - if (!cJSON_IsObject(um_data_limits_local_map)) { + if (cJSON_IsObject(um_data_limits_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_usage_mon_data_limit_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(um_data_limits_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_sm_policy_data_parseFromJSON() failed [um_data_limits]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_usage_mon_data_limit_parseFromJSON(localMapObject)); OpenAPI_list_add(um_data_limitsList , localMapKeyPair); } } @@ -197,12 +209,15 @@ OpenAPI_sm_policy_data_t *OpenAPI_sm_policy_data_parseFromJSON(cJSON *sm_policy_ OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(um_data_local_map, um_data) { cJSON *localMapObject = um_data_local_map; - if (!cJSON_IsObject(um_data_local_map)) { + if (cJSON_IsObject(um_data_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_usage_mon_data_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(um_data_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_sm_policy_data_parseFromJSON() failed [um_data]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_usage_mon_data_parseFromJSON(localMapObject)); OpenAPI_list_add(um_dataList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/sm_policy_data_patch.c b/lib/sbi/openapi/model/sm_policy_data_patch.c index ca270bbb3..f04a27e6b 100644 --- a/lib/sbi/openapi/model/sm_policy_data_patch.c +++ b/lib/sbi/openapi/model/sm_policy_data_patch.c @@ -61,7 +61,9 @@ cJSON *OpenAPI_sm_policy_data_patch_convertToJSON(OpenAPI_sm_policy_data_patch_t if (sm_policy_data_patch->um_data) { OpenAPI_list_for_each(sm_policy_data_patch->um_data, um_data_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)um_data_node->data; - cJSON *itemLocal = OpenAPI_usage_mon_data_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_usage_mon_data_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_sm_policy_data_patch_convertToJSON() failed [um_data]"); goto end; @@ -82,7 +84,9 @@ cJSON *OpenAPI_sm_policy_data_patch_convertToJSON(OpenAPI_sm_policy_data_patch_t if (sm_policy_data_patch->sm_policy_snssai_data) { OpenAPI_list_for_each(sm_policy_data_patch->sm_policy_snssai_data, sm_policy_snssai_data_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)sm_policy_snssai_data_node->data; - cJSON *itemLocal = OpenAPI_sm_policy_snssai_data_patch_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_sm_policy_snssai_data_patch_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_sm_policy_data_patch_convertToJSON() failed [sm_policy_snssai_data]"); goto end; @@ -112,12 +116,15 @@ OpenAPI_sm_policy_data_patch_t *OpenAPI_sm_policy_data_patch_parseFromJSON(cJSON OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(um_data_local_map, um_data) { cJSON *localMapObject = um_data_local_map; - if (!cJSON_IsObject(um_data_local_map)) { + if (cJSON_IsObject(um_data_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_usage_mon_data_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(um_data_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_sm_policy_data_patch_parseFromJSON() failed [um_data]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_usage_mon_data_parseFromJSON(localMapObject)); OpenAPI_list_add(um_dataList , localMapKeyPair); } } @@ -135,12 +142,15 @@ OpenAPI_sm_policy_data_patch_t *OpenAPI_sm_policy_data_patch_parseFromJSON(cJSON OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(sm_policy_snssai_data_local_map, sm_policy_snssai_data) { cJSON *localMapObject = sm_policy_snssai_data_local_map; - if (!cJSON_IsObject(sm_policy_snssai_data_local_map)) { + if (cJSON_IsObject(sm_policy_snssai_data_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_sm_policy_snssai_data_patch_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(sm_policy_snssai_data_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_sm_policy_data_patch_parseFromJSON() failed [sm_policy_snssai_data]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_sm_policy_snssai_data_patch_parseFromJSON(localMapObject)); OpenAPI_list_add(sm_policy_snssai_dataList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/sm_policy_decision.c b/lib/sbi/openapi/model/sm_policy_decision.c index ac8ff9e91..84759207f 100644 --- a/lib/sbi/openapi/model/sm_policy_decision.c +++ b/lib/sbi/openapi/model/sm_policy_decision.c @@ -190,7 +190,9 @@ cJSON *OpenAPI_sm_policy_decision_convertToJSON(OpenAPI_sm_policy_decision_t *sm if (sm_policy_decision->sess_rules) { OpenAPI_list_for_each(sm_policy_decision->sess_rules, sess_rules_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)sess_rules_node->data; - cJSON *itemLocal = OpenAPI_session_rule_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_session_rule_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_sm_policy_decision_convertToJSON() failed [sess_rules]"); goto end; @@ -211,7 +213,9 @@ cJSON *OpenAPI_sm_policy_decision_convertToJSON(OpenAPI_sm_policy_decision_t *sm if (sm_policy_decision->pcc_rules) { OpenAPI_list_for_each(sm_policy_decision->pcc_rules, pcc_rules_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)pcc_rules_node->data; - cJSON *itemLocal = OpenAPI_pcc_rule_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_pcc_rule_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_sm_policy_decision_convertToJSON() failed [pcc_rules]"); goto end; @@ -239,7 +243,9 @@ cJSON *OpenAPI_sm_policy_decision_convertToJSON(OpenAPI_sm_policy_decision_t *sm if (sm_policy_decision->qos_decs) { OpenAPI_list_for_each(sm_policy_decision->qos_decs, qos_decs_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)qos_decs_node->data; - cJSON *itemLocal = OpenAPI_qos_data_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_qos_data_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_sm_policy_decision_convertToJSON() failed [qos_decs]"); goto end; @@ -260,7 +266,9 @@ cJSON *OpenAPI_sm_policy_decision_convertToJSON(OpenAPI_sm_policy_decision_t *sm if (sm_policy_decision->chg_decs) { OpenAPI_list_for_each(sm_policy_decision->chg_decs, chg_decs_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)chg_decs_node->data; - cJSON *itemLocal = OpenAPI_charging_data_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_charging_data_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_sm_policy_decision_convertToJSON() failed [chg_decs]"); goto end; @@ -294,7 +302,9 @@ cJSON *OpenAPI_sm_policy_decision_convertToJSON(OpenAPI_sm_policy_decision_t *sm if (sm_policy_decision->traff_cont_decs) { OpenAPI_list_for_each(sm_policy_decision->traff_cont_decs, traff_cont_decs_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)traff_cont_decs_node->data; - cJSON *itemLocal = OpenAPI_traffic_control_data_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_traffic_control_data_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_sm_policy_decision_convertToJSON() failed [traff_cont_decs]"); goto end; @@ -315,7 +325,9 @@ cJSON *OpenAPI_sm_policy_decision_convertToJSON(OpenAPI_sm_policy_decision_t *sm if (sm_policy_decision->um_decs) { OpenAPI_list_for_each(sm_policy_decision->um_decs, um_decs_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)um_decs_node->data; - cJSON *itemLocal = OpenAPI_usage_monitoring_data_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_usage_monitoring_data_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_sm_policy_decision_convertToJSON() failed [um_decs]"); goto end; @@ -336,7 +348,9 @@ cJSON *OpenAPI_sm_policy_decision_convertToJSON(OpenAPI_sm_policy_decision_t *sm if (sm_policy_decision->qos_chars) { OpenAPI_list_for_each(sm_policy_decision->qos_chars, qos_chars_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)qos_chars_node->data; - cJSON *itemLocal = OpenAPI_qos_characteristics_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_qos_characteristics_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_sm_policy_decision_convertToJSON() failed [qos_chars]"); goto end; @@ -357,7 +371,9 @@ cJSON *OpenAPI_sm_policy_decision_convertToJSON(OpenAPI_sm_policy_decision_t *sm if (sm_policy_decision->qos_mon_decs) { OpenAPI_list_for_each(sm_policy_decision->qos_mon_decs, qos_mon_decs_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)qos_mon_decs_node->data; - cJSON *itemLocal = OpenAPI_qos_monitoring_data_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_qos_monitoring_data_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_sm_policy_decision_convertToJSON() failed [qos_mon_decs]"); goto end; @@ -385,7 +401,9 @@ cJSON *OpenAPI_sm_policy_decision_convertToJSON(OpenAPI_sm_policy_decision_t *sm if (sm_policy_decision->conds) { OpenAPI_list_for_each(sm_policy_decision->conds, conds_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)conds_node->data; - cJSON *itemLocal = OpenAPI_condition_data_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_condition_data_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_sm_policy_decision_convertToJSON() failed [conds]"); goto end; @@ -475,7 +493,9 @@ cJSON *OpenAPI_sm_policy_decision_convertToJSON(OpenAPI_sm_policy_decision_t *sm if (sm_policy_decision->pra_infos) { OpenAPI_list_for_each(sm_policy_decision->pra_infos, pra_infos_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)pra_infos_node->data; - cJSON *itemLocal = OpenAPI_presence_info_rm_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_presence_info_rm_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_sm_policy_decision_convertToJSON() failed [pra_infos]"); goto end; @@ -593,12 +613,15 @@ OpenAPI_sm_policy_decision_t *OpenAPI_sm_policy_decision_parseFromJSON(cJSON *sm OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(sess_rules_local_map, sess_rules) { cJSON *localMapObject = sess_rules_local_map; - if (!cJSON_IsObject(sess_rules_local_map)) { + if (cJSON_IsObject(sess_rules_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_session_rule_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(sess_rules_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_sm_policy_decision_parseFromJSON() failed [sess_rules]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_session_rule_parseFromJSON(localMapObject)); OpenAPI_list_add(sess_rulesList , localMapKeyPair); } } @@ -616,12 +639,15 @@ OpenAPI_sm_policy_decision_t *OpenAPI_sm_policy_decision_parseFromJSON(cJSON *sm OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(pcc_rules_local_map, pcc_rules) { cJSON *localMapObject = pcc_rules_local_map; - if (!cJSON_IsObject(pcc_rules_local_map)) { + if (cJSON_IsObject(pcc_rules_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_pcc_rule_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(pcc_rules_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_sm_policy_decision_parseFromJSON() failed [pcc_rules]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_pcc_rule_parseFromJSON(localMapObject)); OpenAPI_list_add(pcc_rulesList , localMapKeyPair); } } @@ -648,12 +674,15 @@ OpenAPI_sm_policy_decision_t *OpenAPI_sm_policy_decision_parseFromJSON(cJSON *sm OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(qos_decs_local_map, qos_decs) { cJSON *localMapObject = qos_decs_local_map; - if (!cJSON_IsObject(qos_decs_local_map)) { + if (cJSON_IsObject(qos_decs_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_qos_data_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(qos_decs_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_sm_policy_decision_parseFromJSON() failed [qos_decs]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_qos_data_parseFromJSON(localMapObject)); OpenAPI_list_add(qos_decsList , localMapKeyPair); } } @@ -671,12 +700,15 @@ OpenAPI_sm_policy_decision_t *OpenAPI_sm_policy_decision_parseFromJSON(cJSON *sm OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(chg_decs_local_map, chg_decs) { cJSON *localMapObject = chg_decs_local_map; - if (!cJSON_IsObject(chg_decs_local_map)) { + if (cJSON_IsObject(chg_decs_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_charging_data_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(chg_decs_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_sm_policy_decision_parseFromJSON() failed [chg_decs]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_charging_data_parseFromJSON(localMapObject)); OpenAPI_list_add(chg_decsList , localMapKeyPair); } } @@ -701,12 +733,15 @@ OpenAPI_sm_policy_decision_t *OpenAPI_sm_policy_decision_parseFromJSON(cJSON *sm OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(traff_cont_decs_local_map, traff_cont_decs) { cJSON *localMapObject = traff_cont_decs_local_map; - if (!cJSON_IsObject(traff_cont_decs_local_map)) { + if (cJSON_IsObject(traff_cont_decs_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_traffic_control_data_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(traff_cont_decs_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_sm_policy_decision_parseFromJSON() failed [traff_cont_decs]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_traffic_control_data_parseFromJSON(localMapObject)); OpenAPI_list_add(traff_cont_decsList , localMapKeyPair); } } @@ -724,12 +759,15 @@ OpenAPI_sm_policy_decision_t *OpenAPI_sm_policy_decision_parseFromJSON(cJSON *sm OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(um_decs_local_map, um_decs) { cJSON *localMapObject = um_decs_local_map; - if (!cJSON_IsObject(um_decs_local_map)) { + if (cJSON_IsObject(um_decs_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_usage_monitoring_data_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(um_decs_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_sm_policy_decision_parseFromJSON() failed [um_decs]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_usage_monitoring_data_parseFromJSON(localMapObject)); OpenAPI_list_add(um_decsList , localMapKeyPair); } } @@ -747,12 +785,15 @@ OpenAPI_sm_policy_decision_t *OpenAPI_sm_policy_decision_parseFromJSON(cJSON *sm OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(qos_chars_local_map, qos_chars) { cJSON *localMapObject = qos_chars_local_map; - if (!cJSON_IsObject(qos_chars_local_map)) { + if (cJSON_IsObject(qos_chars_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_qos_characteristics_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(qos_chars_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_sm_policy_decision_parseFromJSON() failed [qos_chars]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_qos_characteristics_parseFromJSON(localMapObject)); OpenAPI_list_add(qos_charsList , localMapKeyPair); } } @@ -770,12 +811,15 @@ OpenAPI_sm_policy_decision_t *OpenAPI_sm_policy_decision_parseFromJSON(cJSON *sm OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(qos_mon_decs_local_map, qos_mon_decs) { cJSON *localMapObject = qos_mon_decs_local_map; - if (!cJSON_IsObject(qos_mon_decs_local_map)) { + if (cJSON_IsObject(qos_mon_decs_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_qos_monitoring_data_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(qos_mon_decs_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_sm_policy_decision_parseFromJSON() failed [qos_mon_decs]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_qos_monitoring_data_parseFromJSON(localMapObject)); OpenAPI_list_add(qos_mon_decsList , localMapKeyPair); } } @@ -802,12 +846,15 @@ OpenAPI_sm_policy_decision_t *OpenAPI_sm_policy_decision_parseFromJSON(cJSON *sm OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(conds_local_map, conds) { cJSON *localMapObject = conds_local_map; - if (!cJSON_IsObject(conds_local_map)) { + if (cJSON_IsObject(conds_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_condition_data_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(conds_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_sm_policy_decision_parseFromJSON() failed [conds]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_condition_data_parseFromJSON(localMapObject)); OpenAPI_list_add(condsList , localMapKeyPair); } } @@ -904,12 +951,15 @@ OpenAPI_sm_policy_decision_t *OpenAPI_sm_policy_decision_parseFromJSON(cJSON *sm OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(pra_infos_local_map, pra_infos) { cJSON *localMapObject = pra_infos_local_map; - if (!cJSON_IsObject(pra_infos_local_map)) { + if (cJSON_IsObject(pra_infos_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_presence_info_rm_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(pra_infos_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_sm_policy_decision_parseFromJSON() failed [pra_infos]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_presence_info_rm_parseFromJSON(localMapObject)); OpenAPI_list_add(pra_infosList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/sm_policy_dnn_data.c b/lib/sbi/openapi/model/sm_policy_dnn_data.c index 695d7cb0d..7af7487e3 100644 --- a/lib/sbi/openapi/model/sm_policy_dnn_data.c +++ b/lib/sbi/openapi/model/sm_policy_dnn_data.c @@ -247,7 +247,9 @@ cJSON *OpenAPI_sm_policy_dnn_data_convertToJSON(OpenAPI_sm_policy_dnn_data_t *sm if (sm_policy_dnn_data->ref_um_data_limit_ids) { OpenAPI_list_for_each(sm_policy_dnn_data->ref_um_data_limit_ids, ref_um_data_limit_ids_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)ref_um_data_limit_ids_node->data; - cJSON *itemLocal = OpenAPI_limit_id_to_monitoring_key_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_limit_id_to_monitoring_key_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_sm_policy_dnn_data_convertToJSON() failed [ref_um_data_limit_ids]"); goto end; @@ -303,7 +305,9 @@ cJSON *OpenAPI_sm_policy_dnn_data_convertToJSON(OpenAPI_sm_policy_dnn_data_t *sm if (sm_policy_dnn_data->pra_infos) { OpenAPI_list_for_each(sm_policy_dnn_data->pra_infos, pra_infos_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)pra_infos_node->data; - cJSON *itemLocal = OpenAPI_presence_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_presence_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_sm_policy_dnn_data_convertToJSON() failed [pra_infos]"); goto end; @@ -485,12 +489,15 @@ OpenAPI_sm_policy_dnn_data_t *OpenAPI_sm_policy_dnn_data_parseFromJSON(cJSON *sm OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(ref_um_data_limit_ids_local_map, ref_um_data_limit_ids) { cJSON *localMapObject = ref_um_data_limit_ids_local_map; - if (!cJSON_IsObject(ref_um_data_limit_ids_local_map)) { + if (cJSON_IsObject(ref_um_data_limit_ids_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_limit_id_to_monitoring_key_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(ref_um_data_limit_ids_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_sm_policy_dnn_data_parseFromJSON() failed [ref_um_data_limit_ids]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_limit_id_to_monitoring_key_parseFromJSON(localMapObject)); OpenAPI_list_add(ref_um_data_limit_idsList , localMapKeyPair); } } @@ -553,12 +560,15 @@ OpenAPI_sm_policy_dnn_data_t *OpenAPI_sm_policy_dnn_data_parseFromJSON(cJSON *sm OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(pra_infos_local_map, pra_infos) { cJSON *localMapObject = pra_infos_local_map; - if (!cJSON_IsObject(pra_infos_local_map)) { + if (cJSON_IsObject(pra_infos_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_presence_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(pra_infos_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_sm_policy_dnn_data_parseFromJSON() failed [pra_infos]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_presence_info_parseFromJSON(localMapObject)); OpenAPI_list_add(pra_infosList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/sm_policy_snssai_data.c b/lib/sbi/openapi/model/sm_policy_snssai_data.c index ddf8175ac..e66712aeb 100644 --- a/lib/sbi/openapi/model/sm_policy_snssai_data.c +++ b/lib/sbi/openapi/model/sm_policy_snssai_data.c @@ -67,7 +67,9 @@ cJSON *OpenAPI_sm_policy_snssai_data_convertToJSON(OpenAPI_sm_policy_snssai_data if (sm_policy_snssai_data->sm_policy_dnn_data) { OpenAPI_list_for_each(sm_policy_snssai_data->sm_policy_dnn_data, sm_policy_dnn_data_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)sm_policy_dnn_data_node->data; - cJSON *itemLocal = OpenAPI_sm_policy_dnn_data_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_sm_policy_dnn_data_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_sm_policy_snssai_data_convertToJSON() failed [sm_policy_dnn_data]"); goto end; @@ -106,12 +108,15 @@ OpenAPI_sm_policy_snssai_data_t *OpenAPI_sm_policy_snssai_data_parseFromJSON(cJS OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(sm_policy_dnn_data_local_map, sm_policy_dnn_data) { cJSON *localMapObject = sm_policy_dnn_data_local_map; - if (!cJSON_IsObject(sm_policy_dnn_data_local_map)) { + if (cJSON_IsObject(sm_policy_dnn_data_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_sm_policy_dnn_data_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(sm_policy_dnn_data_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_sm_policy_snssai_data_parseFromJSON() failed [sm_policy_dnn_data]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_sm_policy_dnn_data_parseFromJSON(localMapObject)); OpenAPI_list_add(sm_policy_dnn_dataList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/sm_policy_snssai_data_patch.c b/lib/sbi/openapi/model/sm_policy_snssai_data_patch.c index 635f13305..57654c2cb 100644 --- a/lib/sbi/openapi/model/sm_policy_snssai_data_patch.c +++ b/lib/sbi/openapi/model/sm_policy_snssai_data_patch.c @@ -67,7 +67,9 @@ cJSON *OpenAPI_sm_policy_snssai_data_patch_convertToJSON(OpenAPI_sm_policy_snssa if (sm_policy_snssai_data_patch->sm_policy_dnn_data) { OpenAPI_list_for_each(sm_policy_snssai_data_patch->sm_policy_dnn_data, sm_policy_dnn_data_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)sm_policy_dnn_data_node->data; - cJSON *itemLocal = OpenAPI_sm_policy_dnn_data_patch_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_sm_policy_dnn_data_patch_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_sm_policy_snssai_data_patch_convertToJSON() failed [sm_policy_dnn_data]"); goto end; @@ -106,12 +108,15 @@ OpenAPI_sm_policy_snssai_data_patch_t *OpenAPI_sm_policy_snssai_data_patch_parse OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(sm_policy_dnn_data_local_map, sm_policy_dnn_data) { cJSON *localMapObject = sm_policy_dnn_data_local_map; - if (!cJSON_IsObject(sm_policy_dnn_data_local_map)) { + if (cJSON_IsObject(sm_policy_dnn_data_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_sm_policy_dnn_data_patch_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(sm_policy_dnn_data_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_sm_policy_snssai_data_patch_parseFromJSON() failed [sm_policy_dnn_data]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_sm_policy_dnn_data_patch_parseFromJSON(localMapObject)); OpenAPI_list_add(sm_policy_dnn_dataList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/sm_policy_update_context_data.c b/lib/sbi/openapi/model/sm_policy_update_context_data.c index ad6a593d2..315c4dd17 100644 --- a/lib/sbi/openapi/model/sm_policy_update_context_data.c +++ b/lib/sbi/openapi/model/sm_policy_update_context_data.c @@ -589,7 +589,9 @@ cJSON *OpenAPI_sm_policy_update_context_data_convertToJSON(OpenAPI_sm_policy_upd if (sm_policy_update_context_data->rep_pra_infos) { OpenAPI_list_for_each(sm_policy_update_context_data->rep_pra_infos, rep_pra_infos_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)rep_pra_infos_node->data; - cJSON *itemLocal = OpenAPI_presence_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_presence_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_sm_policy_update_context_data_convertToJSON() failed [rep_pra_infos]"); goto end; @@ -1231,12 +1233,15 @@ OpenAPI_sm_policy_update_context_data_t *OpenAPI_sm_policy_update_context_data_p OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(rep_pra_infos_local_map, rep_pra_infos) { cJSON *localMapObject = rep_pra_infos_local_map; - if (!cJSON_IsObject(rep_pra_infos_local_map)) { + if (cJSON_IsObject(rep_pra_infos_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_presence_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(rep_pra_infos_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_sm_policy_update_context_data_parseFromJSON() failed [rep_pra_infos]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_presence_info_parseFromJSON(localMapObject)); OpenAPI_list_add(rep_pra_infosList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/smf_selection_data.c b/lib/sbi/openapi/model/smf_selection_data.c index 48eef1455..4612f5325 100644 --- a/lib/sbi/openapi/model/smf_selection_data.c +++ b/lib/sbi/openapi/model/smf_selection_data.c @@ -73,7 +73,9 @@ cJSON *OpenAPI_smf_selection_data_convertToJSON(OpenAPI_smf_selection_data_t *sm if (smf_selection_data->candidates) { OpenAPI_list_for_each(smf_selection_data->candidates, candidates_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)candidates_node->data; - cJSON *itemLocal = OpenAPI_candidate_for_replacement_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_candidate_for_replacement_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_smf_selection_data_convertToJSON() failed [candidates]"); goto end; @@ -145,12 +147,15 @@ OpenAPI_smf_selection_data_t *OpenAPI_smf_selection_data_parseFromJSON(cJSON *sm OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(candidates_local_map, candidates) { cJSON *localMapObject = candidates_local_map; - if (!cJSON_IsObject(candidates_local_map)) { + if (cJSON_IsObject(candidates_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_candidate_for_replacement_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(candidates_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_smf_selection_data_parseFromJSON() failed [candidates]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_candidate_for_replacement_parseFromJSON(localMapObject)); OpenAPI_list_add(candidatesList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/smf_selection_subscription_data.c b/lib/sbi/openapi/model/smf_selection_subscription_data.c index f055152b6..03cb83f59 100644 --- a/lib/sbi/openapi/model/smf_selection_subscription_data.c +++ b/lib/sbi/openapi/model/smf_selection_subscription_data.c @@ -66,7 +66,9 @@ cJSON *OpenAPI_smf_selection_subscription_data_convertToJSON(OpenAPI_smf_selecti if (smf_selection_subscription_data->subscribed_snssai_infos) { OpenAPI_list_for_each(smf_selection_subscription_data->subscribed_snssai_infos, subscribed_snssai_infos_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)subscribed_snssai_infos_node->data; - cJSON *itemLocal = OpenAPI_snssai_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_snssai_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_smf_selection_subscription_data_convertToJSON() failed [subscribed_snssai_infos]"); goto end; @@ -112,12 +114,15 @@ OpenAPI_smf_selection_subscription_data_t *OpenAPI_smf_selection_subscription_da OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(subscribed_snssai_infos_local_map, subscribed_snssai_infos) { cJSON *localMapObject = subscribed_snssai_infos_local_map; - if (!cJSON_IsObject(subscribed_snssai_infos_local_map)) { + if (cJSON_IsObject(subscribed_snssai_infos_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_snssai_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(subscribed_snssai_infos_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_smf_selection_subscription_data_parseFromJSON() failed [subscribed_snssai_infos]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_snssai_info_parseFromJSON(localMapObject)); OpenAPI_list_add(subscribed_snssai_infosList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/smf_selection_subscription_data_1.c b/lib/sbi/openapi/model/smf_selection_subscription_data_1.c index ccd498560..d2edfa8a9 100644 --- a/lib/sbi/openapi/model/smf_selection_subscription_data_1.c +++ b/lib/sbi/openapi/model/smf_selection_subscription_data_1.c @@ -66,7 +66,9 @@ cJSON *OpenAPI_smf_selection_subscription_data_1_convertToJSON(OpenAPI_smf_selec if (smf_selection_subscription_data_1->subscribed_snssai_infos) { OpenAPI_list_for_each(smf_selection_subscription_data_1->subscribed_snssai_infos, subscribed_snssai_infos_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)subscribed_snssai_infos_node->data; - cJSON *itemLocal = OpenAPI_snssai_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_snssai_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_smf_selection_subscription_data_1_convertToJSON() failed [subscribed_snssai_infos]"); goto end; @@ -112,12 +114,15 @@ OpenAPI_smf_selection_subscription_data_1_t *OpenAPI_smf_selection_subscription_ OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(subscribed_snssai_infos_local_map, subscribed_snssai_infos) { cJSON *localMapObject = subscribed_snssai_infos_local_map; - if (!cJSON_IsObject(subscribed_snssai_infos_local_map)) { + if (cJSON_IsObject(subscribed_snssai_infos_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_snssai_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(subscribed_snssai_infos_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_smf_selection_subscription_data_1_parseFromJSON() failed [subscribed_snssai_infos]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_snssai_info_parseFromJSON(localMapObject)); OpenAPI_list_add(subscribed_snssai_infosList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/spatial_validity.c b/lib/sbi/openapi/model/spatial_validity.c index 437397fa2..edc8dd19b 100644 --- a/lib/sbi/openapi/model/spatial_validity.c +++ b/lib/sbi/openapi/model/spatial_validity.c @@ -52,7 +52,9 @@ cJSON *OpenAPI_spatial_validity_convertToJSON(OpenAPI_spatial_validity_t *spatia if (spatial_validity->presence_info_list) { OpenAPI_list_for_each(spatial_validity->presence_info_list, presence_info_list_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)presence_info_list_node->data; - cJSON *itemLocal = OpenAPI_presence_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_presence_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_spatial_validity_convertToJSON() failed [presence_info_list]"); goto end; @@ -84,12 +86,15 @@ OpenAPI_spatial_validity_t *OpenAPI_spatial_validity_parseFromJSON(cJSON *spatia OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(presence_info_list_local_map, presence_info_list) { cJSON *localMapObject = presence_info_list_local_map; - if (!cJSON_IsObject(presence_info_list_local_map)) { + if (cJSON_IsObject(presence_info_list_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_presence_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(presence_info_list_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_spatial_validity_parseFromJSON() failed [presence_info_list]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_presence_info_parseFromJSON(localMapObject)); OpenAPI_list_add(presence_info_listList , localMapKeyPair); } diff --git a/lib/sbi/openapi/model/spatial_validity_rm.c b/lib/sbi/openapi/model/spatial_validity_rm.c index 74cff95f9..0bd073db8 100644 --- a/lib/sbi/openapi/model/spatial_validity_rm.c +++ b/lib/sbi/openapi/model/spatial_validity_rm.c @@ -52,7 +52,9 @@ cJSON *OpenAPI_spatial_validity_rm_convertToJSON(OpenAPI_spatial_validity_rm_t * if (spatial_validity_rm->presence_info_list) { OpenAPI_list_for_each(spatial_validity_rm->presence_info_list, presence_info_list_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)presence_info_list_node->data; - cJSON *itemLocal = OpenAPI_presence_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_presence_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_spatial_validity_rm_convertToJSON() failed [presence_info_list]"); goto end; @@ -84,12 +86,15 @@ OpenAPI_spatial_validity_rm_t *OpenAPI_spatial_validity_rm_parseFromJSON(cJSON * OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(presence_info_list_local_map, presence_info_list) { cJSON *localMapObject = presence_info_list_local_map; - if (!cJSON_IsObject(presence_info_list_local_map)) { + if (cJSON_IsObject(presence_info_list_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_presence_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(presence_info_list_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_spatial_validity_rm_parseFromJSON() failed [presence_info_list]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_presence_info_parseFromJSON(localMapObject)); OpenAPI_list_add(presence_info_listList , localMapKeyPair); } diff --git a/lib/sbi/openapi/model/ue_context_in_smf_data.c b/lib/sbi/openapi/model/ue_context_in_smf_data.c index 62f1bc384..f5459e637 100644 --- a/lib/sbi/openapi/model/ue_context_in_smf_data.c +++ b/lib/sbi/openapi/model/ue_context_in_smf_data.c @@ -62,7 +62,9 @@ cJSON *OpenAPI_ue_context_in_smf_data_convertToJSON(OpenAPI_ue_context_in_smf_da if (ue_context_in_smf_data->pdu_sessions) { OpenAPI_list_for_each(ue_context_in_smf_data->pdu_sessions, pdu_sessions_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)pdu_sessions_node->data; - cJSON *itemLocal = OpenAPI_pdu_session_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_pdu_session_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_ue_context_in_smf_data_convertToJSON() failed [pdu_sessions]"); goto end; @@ -125,12 +127,15 @@ OpenAPI_ue_context_in_smf_data_t *OpenAPI_ue_context_in_smf_data_parseFromJSON(c OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(pdu_sessions_local_map, pdu_sessions) { cJSON *localMapObject = pdu_sessions_local_map; - if (!cJSON_IsObject(pdu_sessions_local_map)) { + if (cJSON_IsObject(pdu_sessions_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_pdu_session_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(pdu_sessions_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_ue_context_in_smf_data_parseFromJSON() failed [pdu_sessions]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_pdu_session_parseFromJSON(localMapObject)); OpenAPI_list_add(pdu_sessionsList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/ue_context_in_smf_data_1.c b/lib/sbi/openapi/model/ue_context_in_smf_data_1.c index 2546942ed..fd1bcab8f 100644 --- a/lib/sbi/openapi/model/ue_context_in_smf_data_1.c +++ b/lib/sbi/openapi/model/ue_context_in_smf_data_1.c @@ -62,7 +62,9 @@ cJSON *OpenAPI_ue_context_in_smf_data_1_convertToJSON(OpenAPI_ue_context_in_smf_ if (ue_context_in_smf_data_1->pdu_sessions) { OpenAPI_list_for_each(ue_context_in_smf_data_1->pdu_sessions, pdu_sessions_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)pdu_sessions_node->data; - cJSON *itemLocal = OpenAPI_pdu_session_1_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_pdu_session_1_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_ue_context_in_smf_data_1_convertToJSON() failed [pdu_sessions]"); goto end; @@ -125,12 +127,15 @@ OpenAPI_ue_context_in_smf_data_1_t *OpenAPI_ue_context_in_smf_data_1_parseFromJS OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(pdu_sessions_local_map, pdu_sessions) { cJSON *localMapObject = pdu_sessions_local_map; - if (!cJSON_IsObject(pdu_sessions_local_map)) { + if (cJSON_IsObject(pdu_sessions_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_pdu_session_1_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(pdu_sessions_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_ue_context_in_smf_data_1_parseFromJSON() failed [pdu_sessions]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_pdu_session_1_parseFromJSON(localMapObject)); OpenAPI_list_add(pdu_sessionsList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/ue_policy_set.c b/lib/sbi/openapi/model/ue_policy_set.c index 69e695d70..ffe209303 100644 --- a/lib/sbi/openapi/model/ue_policy_set.c +++ b/lib/sbi/openapi/model/ue_policy_set.c @@ -97,7 +97,9 @@ cJSON *OpenAPI_ue_policy_set_convertToJSON(OpenAPI_ue_policy_set_t *ue_policy_se if (ue_policy_set->pra_infos) { OpenAPI_list_for_each(ue_policy_set->pra_infos, pra_infos_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)pra_infos_node->data; - cJSON *itemLocal = OpenAPI_presence_info_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_presence_info_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_ue_policy_set_convertToJSON() failed [pra_infos]"); goto end; @@ -134,7 +136,9 @@ cJSON *OpenAPI_ue_policy_set_convertToJSON(OpenAPI_ue_policy_set_t *ue_policy_se if (ue_policy_set->ue_policy_sections) { OpenAPI_list_for_each(ue_policy_set->ue_policy_sections, ue_policy_sections_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)ue_policy_sections_node->data; - cJSON *itemLocal = OpenAPI_ue_policy_section_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_ue_policy_section_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_ue_policy_set_convertToJSON() failed [ue_policy_sections]"); goto end; @@ -171,7 +175,9 @@ cJSON *OpenAPI_ue_policy_set_convertToJSON(OpenAPI_ue_policy_set_t *ue_policy_se if (ue_policy_set->allowed_route_sel_descs) { OpenAPI_list_for_each(ue_policy_set->allowed_route_sel_descs, allowed_route_sel_descs_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)allowed_route_sel_descs_node->data; - cJSON *itemLocal = OpenAPI_plmn_route_selection_descriptor_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_plmn_route_selection_descriptor_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_ue_policy_set_convertToJSON() failed [allowed_route_sel_descs]"); goto end; @@ -238,12 +244,15 @@ OpenAPI_ue_policy_set_t *OpenAPI_ue_policy_set_parseFromJSON(cJSON *ue_policy_se OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(pra_infos_local_map, pra_infos) { cJSON *localMapObject = pra_infos_local_map; - if (!cJSON_IsObject(pra_infos_local_map)) { + if (cJSON_IsObject(pra_infos_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_presence_info_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(pra_infos_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_ue_policy_set_parseFromJSON() failed [pra_infos]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_presence_info_parseFromJSON(localMapObject)); OpenAPI_list_add(pra_infosList , localMapKeyPair); } } @@ -281,12 +290,15 @@ OpenAPI_ue_policy_set_t *OpenAPI_ue_policy_set_parseFromJSON(cJSON *ue_policy_se OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(ue_policy_sections_local_map, ue_policy_sections) { cJSON *localMapObject = ue_policy_sections_local_map; - if (!cJSON_IsObject(ue_policy_sections_local_map)) { + if (cJSON_IsObject(ue_policy_sections_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_ue_policy_section_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(ue_policy_sections_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_ue_policy_set_parseFromJSON() failed [ue_policy_sections]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_ue_policy_section_parseFromJSON(localMapObject)); OpenAPI_list_add(ue_policy_sectionsList , localMapKeyPair); } } @@ -324,12 +336,15 @@ OpenAPI_ue_policy_set_t *OpenAPI_ue_policy_set_parseFromJSON(cJSON *ue_policy_se OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(allowed_route_sel_descs_local_map, allowed_route_sel_descs) { cJSON *localMapObject = allowed_route_sel_descs_local_map; - if (!cJSON_IsObject(allowed_route_sel_descs_local_map)) { + if (cJSON_IsObject(allowed_route_sel_descs_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_plmn_route_selection_descriptor_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(allowed_route_sel_descs_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_ue_policy_set_parseFromJSON() failed [allowed_route_sel_descs]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_plmn_route_selection_descriptor_parseFromJSON(localMapObject)); OpenAPI_list_add(allowed_route_sel_descsList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/ue_policy_set_patch.c b/lib/sbi/openapi/model/ue_policy_set_patch.c index d6964c050..89745ae29 100644 --- a/lib/sbi/openapi/model/ue_policy_set_patch.c +++ b/lib/sbi/openapi/model/ue_policy_set_patch.c @@ -72,7 +72,9 @@ cJSON *OpenAPI_ue_policy_set_patch_convertToJSON(OpenAPI_ue_policy_set_patch_t * if (ue_policy_set_patch->ue_policy_sections) { OpenAPI_list_for_each(ue_policy_set_patch->ue_policy_sections, ue_policy_sections_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)ue_policy_sections_node->data; - cJSON *itemLocal = OpenAPI_ue_policy_section_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_ue_policy_section_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_ue_policy_set_patch_convertToJSON() failed [ue_policy_sections]"); goto end; @@ -148,12 +150,15 @@ OpenAPI_ue_policy_set_patch_t *OpenAPI_ue_policy_set_patch_parseFromJSON(cJSON * OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(ue_policy_sections_local_map, ue_policy_sections) { cJSON *localMapObject = ue_policy_sections_local_map; - if (!cJSON_IsObject(ue_policy_sections_local_map)) { + if (cJSON_IsObject(ue_policy_sections_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_ue_policy_section_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(ue_policy_sections_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_ue_policy_set_patch_parseFromJSON() failed [ue_policy_sections]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_ue_policy_section_parseFromJSON(localMapObject)); OpenAPI_list_add(ue_policy_sectionsList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/usage_mon_data.c b/lib/sbi/openapi/model/usage_mon_data.c index 3e35e878e..6e83e5f59 100644 --- a/lib/sbi/openapi/model/usage_mon_data.c +++ b/lib/sbi/openapi/model/usage_mon_data.c @@ -73,7 +73,9 @@ cJSON *OpenAPI_usage_mon_data_convertToJSON(OpenAPI_usage_mon_data_t *usage_mon_ if (usage_mon_data->scopes) { OpenAPI_list_for_each(usage_mon_data->scopes, scopes_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)scopes_node->data; - cJSON *itemLocal = OpenAPI_usage_mon_data_scope_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_usage_mon_data_scope_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_usage_mon_data_convertToJSON() failed [scopes]"); goto end; @@ -160,12 +162,15 @@ OpenAPI_usage_mon_data_t *OpenAPI_usage_mon_data_parseFromJSON(cJSON *usage_mon_ OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(scopes_local_map, scopes) { cJSON *localMapObject = scopes_local_map; - if (!cJSON_IsObject(scopes_local_map)) { + if (cJSON_IsObject(scopes_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_usage_mon_data_scope_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(scopes_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_usage_mon_data_parseFromJSON() failed [scopes]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_usage_mon_data_scope_parseFromJSON(localMapObject)); OpenAPI_list_add(scopesList , localMapKeyPair); } } diff --git a/lib/sbi/openapi/model/usage_mon_data_limit.c b/lib/sbi/openapi/model/usage_mon_data_limit.c index 8d6c4b9f5..4adf3a480 100644 --- a/lib/sbi/openapi/model/usage_mon_data_limit.c +++ b/lib/sbi/openapi/model/usage_mon_data_limit.c @@ -76,7 +76,9 @@ cJSON *OpenAPI_usage_mon_data_limit_convertToJSON(OpenAPI_usage_mon_data_limit_t if (usage_mon_data_limit->scopes) { OpenAPI_list_for_each(usage_mon_data_limit->scopes, scopes_node) { OpenAPI_map_t *localKeyValue = (OpenAPI_map_t*)scopes_node->data; - cJSON *itemLocal = OpenAPI_usage_mon_data_scope_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_usage_mon_data_scope_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_usage_mon_data_limit_convertToJSON() failed [scopes]"); goto end; @@ -164,12 +166,15 @@ OpenAPI_usage_mon_data_limit_t *OpenAPI_usage_mon_data_limit_parseFromJSON(cJSON OpenAPI_map_t *localMapKeyPair = NULL; cJSON_ArrayForEach(scopes_local_map, scopes) { cJSON *localMapObject = scopes_local_map; - if (!cJSON_IsObject(scopes_local_map)) { + if (cJSON_IsObject(scopes_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_usage_mon_data_scope_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull(scopes_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_usage_mon_data_limit_parseFromJSON() failed [scopes]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_usage_mon_data_scope_parseFromJSON(localMapObject)); OpenAPI_list_add(scopesList , localMapKeyPair); } } diff --git a/lib/sbi/support/20210629/openapi-generator/templates/model-body.mustache b/lib/sbi/support/20210629/openapi-generator/templates/model-body.mustache index 5f1988415..c46e9823d 100644 --- a/lib/sbi/support/20210629/openapi-generator/templates/model-body.mustache +++ b/lib/sbi/support/20210629/openapi-generator/templates/model-body.mustache @@ -505,7 +505,9 @@ cJSON *OpenAPI_{{classname}}_convertToJSON(OpenAPI_{{classname}}_t *{{classname} {{/isBoolean}} {{/isPrimitiveType}} {{^isPrimitiveType}} - cJSON *itemLocal = OpenAPI_{{complexType}}_convertToJSON(localKeyValue->value); + cJSON *itemLocal = localKeyValue->value ? + OpenAPI_{{complexType}}_convertToJSON(localKeyValue->value) : + cJSON_CreateNull(); if (itemLocal == NULL) { ogs_error("OpenAPI_{{classname}}_convertToJSON() failed [{{{name}}}]"); goto end; @@ -798,12 +800,15 @@ OpenAPI_{{classname}}_t *OpenAPI_{{classname}}_parseFromJSON(cJSON *{{classname} {{/isNumeric}} {{/isPrimitiveType}} {{^isPrimitiveType}} - if (!cJSON_IsObject({{{name}}}_local_map)) { + if (cJSON_IsObject({{{name}}}_local_map)) { + localMapKeyPair = OpenAPI_map_create( + localMapObject->string, OpenAPI_{{complexType}}_parseFromJSON(localMapObject)); + } else if (cJSON_IsNull({{{name}}}_local_map)) { + localMapKeyPair = OpenAPI_map_create(localMapObject->string, NULL); + } else { ogs_error("OpenAPI_{{classname}}_parseFromJSON() failed [{{{name}}}]"); goto end; } - localMapKeyPair = OpenAPI_map_create( - localMapObject->string, OpenAPI_{{complexType}}_parseFromJSON(localMapObject)); {{/isPrimitiveType}} OpenAPI_list_add({{{name}}}List , localMapKeyPair); } diff --git a/lib/sbi/support/20210629/openapitools.json b/lib/sbi/support/20210629/openapitools.json new file mode 100644 index 000000000..29f5d0699 --- /dev/null +++ b/lib/sbi/support/20210629/openapitools.json @@ -0,0 +1,7 @@ +{ + "$schema": "node_modules/@openapitools/openapi-generator-cli/config.schema.json", + "spaces": 2, + "generator-cli": { + "version": "5.2.0" + } +} diff --git a/src/amf/context.c b/src/amf/context.c index 72d30ad1c..0c791fd95 100644 --- a/src/amf/context.c +++ b/src/amf/context.c @@ -1206,6 +1206,9 @@ void amf_ue_remove(amf_ue_t *amf_ue) /* Clear N2 Transfer */ AMF_UE_CLEAR_N2_TRANSFER(amf_ue, pdu_session_resource_setup_request); + /* Clear 5GSM Message */ + AMF_UE_CLEAR_5GSM_MESSAGE(amf_ue); + /* Remove all session context */ amf_sess_remove_all(amf_ue); @@ -1677,6 +1680,7 @@ void amf_sess_remove(amf_sess_t *sess) ogs_pkbuf_free(sess->pdu_session_establishment_accept); AMF_SESS_CLEAR_N2_TRANSFER(sess, pdu_session_resource_setup_request); + AMF_SESS_CLEAR_N2_TRANSFER(sess, pdu_session_resource_modification_command); AMF_SESS_CLEAR_N2_TRANSFER(sess, path_switch_request_ack); AMF_SESS_CLEAR_N2_TRANSFER(sess, handover_request); AMF_SESS_CLEAR_N2_TRANSFER(sess, handover_command); @@ -1827,6 +1831,33 @@ bool amf_handover_request_transfer_needed(amf_ue_t *amf_ue) return false; } +bool amf_paging_ongoing(amf_ue_t *amf_ue) +{ + amf_sess_t *sess = NULL; + + ogs_assert(amf_ue); + + ogs_list_for_each(&amf_ue->sess_list, sess) { + if (sess->paging.ongoing == true) + return true; + } + + return false; +} + +bool amf_downlink_signalling_pending(amf_ue_t *amf_ue) +{ + amf_sess_t *sess = NULL; + + ogs_assert(amf_ue); + + ogs_list_for_each(&amf_ue->sess_list, sess) + if (sess->gsm_message.type) + return true; + + return false; +} + int amf_find_served_tai(ogs_5gs_tai_t *nr_tai) { int i = 0, j = 0, k = 0; diff --git a/src/amf/context.h b/src/amf/context.h index 4c4a4244e..95cad8d11 100644 --- a/src/amf/context.h +++ b/src/amf/context.h @@ -459,6 +459,7 @@ typedef struct amf_sess_s { struct { ogs_pkbuf_t *pdu_session_resource_setup_request; + ogs_pkbuf_t *pdu_session_resource_modification_command; ogs_pkbuf_t *path_switch_request_ack; ogs_pkbuf_t *handover_request; ogs_pkbuf_t *handover_command; @@ -467,13 +468,13 @@ typedef struct amf_sess_s { do { \ ogs_assert(__sESS); \ ogs_assert((__sESS)->amf_ue); \ - if (sess->transfer.__n2Type) { \ + if ((__sESS)->transfer.__n2Type) { \ ogs_warn("[%s:%d] N2 transfer message duplicated. Overwritten", \ - ((__sESS)->amf_ue)->supi, sess->psi); \ - ogs_pkbuf_free(sess->transfer.__n2Type); \ + ((__sESS)->amf_ue)->supi, (__sESS)->psi); \ + ogs_pkbuf_free((__sESS)->transfer.__n2Type); \ } \ - sess->transfer.__n2Type = __n2Buf; \ - ogs_assert(sess->transfer.__n2Type); \ + (__sESS)->transfer.__n2Type = __n2Buf; \ + ogs_assert((__sESS)->transfer.__n2Type); \ } while(0); #define AMF_SESS_CLEAR_N2_TRANSFER(__sESS, __n2Type) \ @@ -505,13 +506,14 @@ typedef struct amf_sess_s { do { \ ogs_assert(__sESS); \ ogs_assert(__lOCATION); \ - ogs_assert(__uRI); \ AMF_SESS_CLEAR_PAGING_INFO(__sESS) \ (__sESS)->paging.ongoing = true; \ ((__sESS)->paging.location) = ogs_strdup(__lOCATION); \ ogs_assert((__sESS)->paging.location); \ - ((__sESS)->paging.n1n2_failure_txf_notif_uri) = ogs_strdup(__uRI); \ - ogs_assert((__sESS)->paging.n1n2_failure_txf_notif_uri); \ + if (__uRI) { \ + ((__sESS)->paging.n1n2_failure_txf_notif_uri) = ogs_strdup(__uRI); \ + ogs_assert((__sESS)->paging.n1n2_failure_txf_notif_uri); \ + } \ } while(0); #define AMF_SESS_CLEAR_PAGING_INFO(__sESS) \ do { \ @@ -519,9 +521,10 @@ typedef struct amf_sess_s { ogs_assert((__sESS)->paging.location); \ ogs_free((__sESS)->paging.location); \ ((__sESS)->paging.location) = NULL; \ - ogs_assert((__sESS)->paging.n1n2_failure_txf_notif_uri); \ - ogs_free((__sESS)->paging.n1n2_failure_txf_notif_uri); \ - ((__sESS)->paging.n1n2_failure_txf_notif_uri) = NULL; \ + if ((__sESS)->paging.n1n2_failure_txf_notif_uri) { \ + ogs_free((__sESS)->paging.n1n2_failure_txf_notif_uri); \ + ((__sESS)->paging.n1n2_failure_txf_notif_uri) = NULL; \ + } \ ((__sESS)->paging.ongoing) = false; \ } \ } while(0); @@ -533,6 +536,52 @@ typedef struct amf_sess_s { } \ } while(0); + struct { + uint8_t type; + ogs_pkbuf_t *n1buf; + ogs_pkbuf_t *n2buf; + } gsm_message; + +#define AMF_SESS_STORE_5GSM_MESSAGE(__sESS, __tYPE, __n1Buf, __n2Buf) \ + do { \ + ogs_assert(__sESS); \ + ogs_assert((__sESS)->amf_ue); \ + if ((__sESS)->gsm_message.n1buf) { \ + ogs_warn("[%s:%d] N1 message duplicated. Overwritten", \ + ((__sESS)->amf_ue)->supi, (__sESS)->psi); \ + ogs_pkbuf_free((__sESS)->gsm_message.n1buf); \ + } \ + (__sESS)->gsm_message.n1buf = __n1Buf; \ + ogs_assert((__sESS)->gsm_message.n1buf); \ + if ((__sESS)->gsm_message.n2buf) { \ + ogs_warn("[%s:%d] N2 message duplicated. Overwritten", \ + ((__sESS)->amf_ue)->supi, (__sESS)->psi); \ + ogs_pkbuf_free((__sESS)->gsm_message.n2buf); \ + } \ + (__sESS)->gsm_message.n2buf = __n2Buf; \ + ogs_assert((__sESS)->gsm_message.n2buf); \ + (__sESS)->gsm_message.type = __tYPE; \ + } while(0); + +#define AMF_SESS_CLEAR_5GSM_MESSAGE(__sESS) \ + do { \ + if ((__sESS)->gsm_message.n1buf) \ + ogs_pkbuf_free((__sESS)->gsm_message.n1buf); \ + (__sESS)->gsm_message.n1buf = NULL; \ + if ((__sESS)->gsm_message.n2buf) \ + ogs_pkbuf_free((__sESS)->gsm_message.n2buf); \ + (__sESS)->gsm_message.n2buf = NULL; \ + (__sESS)->gsm_message.type = 0; \ + } while(0); + +#define AMF_UE_CLEAR_5GSM_MESSAGE(__aMF) \ + do { \ + amf_sess_t *sess = NULL; \ + ogs_list_for_each(&((__aMF)->sess_list), sess) { \ + AMF_SESS_CLEAR_5GSM_MESSAGE(sess) \ + } \ + } while(0); + struct { char *nsi_id; struct { @@ -691,6 +740,13 @@ bool amf_pdu_res_setup_req_transfer_needed(amf_ue_t *amf_ue); (amf_handover_request_transfer_needed(__aMF) == true) bool amf_handover_request_transfer_needed(amf_ue_t *amf_ue); +#define PAGING_ONGOING(__aMF) \ + (amf_paging_ongoing(__aMF) == true) +bool amf_paging_ongoing(amf_ue_t *amf_ue); +#define DOWNLINK_SIGNALLING_PENDING(__aMF) \ + (amf_downlink_signalling_pending(__aMF) == true) +bool amf_downlink_signalling_pending(amf_ue_t *amf_ue); + int amf_find_served_tai(ogs_5gs_tai_t *nr_tai); ogs_s_nssai_t *amf_find_s_nssai( ogs_plmn_id_t *served_plmn_id, ogs_s_nssai_t *s_nssai); diff --git a/src/amf/gmm-handler.c b/src/amf/gmm-handler.c index c63cd8bb3..0f71a0a24 100644 --- a/src/amf/gmm-handler.c +++ b/src/amf/gmm-handler.c @@ -201,6 +201,7 @@ int gmm_handle_registration_request(amf_ue_t *amf_ue, */ AMF_UE_CLEAR_PAGING_INFO(amf_ue); AMF_UE_CLEAR_N2_TRANSFER(amf_ue, pdu_session_resource_setup_request); + AMF_UE_CLEAR_5GSM_MESSAGE(amf_ue); CLEAR_AMF_UE_ALL_TIMERS(amf_ue); if (SECURITY_CONTEXT_IS_VALID(amf_ue)) { @@ -1101,10 +1102,46 @@ int gmm_handle_ul_nas_transport(amf_ue_t *amf_ue, sess, AMF_UPDATE_SM_CONTEXT_N1_RELEASED, ¶m, amf_nsmf_pdusession_build_update_sm_context)); - if (gsm_header->message_type == - OGS_NAS_5GS_PDU_SESSION_RELEASE_COMPLETE) { + switch (gsm_header->message_type) { + case OGS_NAS_5GS_PDU_SESSION_MODIFICATION_COMPLETE: + case OGS_NAS_5GS_PDU_SESSION_MODIFICATION_COMMAND_REJECT: + if (PAGING_ONGOING(amf_ue) == true) { + + gmm_configuration_update_command_param_t param; + /* + * TS24.501 + * 5.4.4 Generic UE configuration update procedure + * 5.4.4.1 General + * + * This procedure shall be initiated by the network to assign + * a new 5G-GUTI to the UE after a successful service request + * procedure invoked as a response to a paging request + * from the network and before the release + * of the N1 NAS signalling connection. + * + * If the service request procedure was triggered + * due to 5GSM downlink signalling pending, the procedure + * for assigning a new 5G-GUTI can be initiated by the network + * after the transport of the 5GSM downlink signalling. + */ + amf_ue_new_guti(amf_ue); + + memset(¶m, 0, sizeof(param)); + param.acknowledgement_requested = 1; + param.guti = 1; + ogs_assert(OGS_OK == + nas_5gs_send_configuration_update_command( + amf_ue, ¶m)); + + AMF_UE_CLEAR_PAGING_INFO(amf_ue); + } + break; + case OGS_NAS_5GS_PDU_SESSION_RELEASE_COMPLETE: /* Prevent to invoke SMF for this session */ CLEAR_SM_CONTEXT_REF(sess); + break; + default: + break; } } break; diff --git a/src/amf/gmm-handler.h b/src/amf/gmm-handler.h index a0b71df96..9cab5905d 100644 --- a/src/amf/gmm-handler.h +++ b/src/amf/gmm-handler.h @@ -53,14 +53,6 @@ int gmm_handle_security_mode_complete(amf_ue_t *amf_ue, int gmm_handle_ul_nas_transport(amf_ue_t *amf_ue, ogs_nas_5gs_ul_nas_transport_t *ul_nas_transport); -#if 0 -int gmm_handle_tau_request(amf_ue_t *amf_ue, - ogs_nas_5gs_tracking_area_update_request_t *tau_request); - -int gmm_handle_extended_service_request(amf_ue_t *amf_ue, - ogs_nas_5gs_extended_service_request_t *extended_service_request); -#endif - #ifdef __cplusplus } #endif diff --git a/src/amf/gmm-sm.c b/src/amf/gmm-sm.c index 9ea86fbd9..f25e40a90 100644 --- a/src/amf/gmm-sm.c +++ b/src/amf/gmm-sm.c @@ -66,6 +66,7 @@ void gmm_state_de_registered(ogs_fsm_t *s, amf_event_t *e) case OGS_FSM_ENTRY_SIG: AMF_UE_CLEAR_PAGING_INFO(amf_ue); AMF_UE_CLEAR_N2_TRANSFER(amf_ue, pdu_session_resource_setup_request); + AMF_UE_CLEAR_5GSM_MESSAGE(amf_ue); CLEAR_AMF_UE_ALL_TIMERS(amf_ue); break; case OGS_FSM_EXIT_SIG: @@ -367,7 +368,8 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e) ogs_warn("[%s] Paging failed. Stop", amf_ue->supi); ogs_list_for_each(&amf_ue->sess_list, sess) { - if (sess->paging.ongoing == true) { + if (sess->paging.ongoing == true && + sess->paging.n1n2_failure_txf_notif_uri != NULL) { ogs_assert(true == amf_sbi_send_n1_n2_failure_notify( sess, @@ -382,6 +384,9 @@ static void common_register_state(ogs_fsm_t *s, amf_event_t *e) AMF_UE_CLEAR_N2_TRANSFER( amf_ue, pdu_session_resource_setup_request); + /* Clear 5GSM Message */ + AMF_UE_CLEAR_5GSM_MESSAGE(amf_ue); + /* Clear t3513 Timers */ CLEAR_AMF_UE_TIMER(amf_ue->t3513); @@ -1181,6 +1186,7 @@ void gmm_state_exception(ogs_fsm_t *s, amf_event_t *e) case OGS_FSM_ENTRY_SIG: AMF_UE_CLEAR_PAGING_INFO(amf_ue); AMF_UE_CLEAR_N2_TRANSFER(amf_ue, pdu_session_resource_setup_request); + AMF_UE_CLEAR_5GSM_MESSAGE(amf_ue); CLEAR_AMF_UE_ALL_TIMERS(amf_ue); amf_sbi_send_release_all_sessions( diff --git a/src/amf/namf-handler.c b/src/amf/namf-handler.c index 8105c8e57..c52938e12 100644 --- a/src/amf/namf-handler.c +++ b/src/amf/namf-handler.c @@ -143,23 +143,6 @@ int amf_namf_comm_handle_n1_n2_message_transfer( ogs_assert(n2buf); } - switch (n2InfoContent->ngap_ie_type) { - case OpenAPI_ngap_ie_type_PDU_RES_SETUP_REQ: - case OpenAPI_ngap_ie_type_PDU_RES_MOD_REQ: - case OpenAPI_ngap_ie_type_PDU_RES_REL_CMD: - /* N1 SM Message */ - if (n1buf) { - gmmbuf = gmm_build_dl_nas_transport(sess, - OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, n1buf, 0, 0); - ogs_assert(gmmbuf); - } - break; - default: - ogs_error("Not implemented ngap_ie_type[%d]", - n2InfoContent->ngap_ie_type); - return OGS_ERROR; - } - memset(&sendmsg, 0, sizeof(sendmsg)); status = OGS_SBI_HTTP_STATUS_OK; @@ -177,6 +160,12 @@ int amf_namf_comm_handle_n1_n2_message_transfer( return OGS_ERROR; } + if (n1buf) { + gmmbuf = gmm_build_dl_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, n1buf, 0, 0); + ogs_assert(gmmbuf); + } + if (gmmbuf) { ran_ue_t *ran_ue = NULL; @@ -301,7 +290,7 @@ int amf_namf_comm_handle_n1_n2_message_transfer( break; case OpenAPI_ngap_ie_type_PDU_RES_MOD_REQ: - if (!gmmbuf) { + if (!n1buf) { ogs_error("[%s] No N1 SM Content", amf_ue->supi); return OGS_ERROR; } @@ -311,10 +300,45 @@ int amf_namf_comm_handle_n1_n2_message_transfer( } if (CM_IDLE(amf_ue)) { - ogs_fatal("[%s] IDLE state is not implemented", amf_ue->supi); - ogs_assert_if_reached(); + ogs_sbi_server_t *server = NULL; + ogs_sbi_header_t header; + + status = OGS_SBI_HTTP_STATUS_ACCEPTED; + N1N2MessageTransferRspData.cause = + OpenAPI_n1_n2_message_transfer_cause_ATTEMPTING_TO_REACH_UE; + + /* Location */ + server = ogs_sbi_server_from_stream(stream); + ogs_assert(server); + + memset(&header, 0, sizeof(header)); + header.service.name = (char *)OGS_SBI_SERVICE_NAME_NAMF_COMM; + header.api.version = (char *)OGS_SBI_API_V1; + header.resource.component[0] = + (char *)OGS_SBI_RESOURCE_NAME_UE_CONTEXTS; + header.resource.component[1] = amf_ue->supi; + header.resource.component[2] = + (char *)OGS_SBI_RESOURCE_NAME_N1_N2_MESSAGES; + header.resource.component[3] = sess->sm_context_ref; + + sendmsg.http.location = ogs_sbi_server_uri(server, &header); + + /* Store Paging Info */ + AMF_SESS_STORE_PAGING_INFO( + sess, sendmsg.http.location, NULL); + + /* Store 5GSM Message */ + AMF_SESS_STORE_5GSM_MESSAGE(sess, + OGS_NAS_5GS_PDU_SESSION_MODIFICATION_COMMAND, + n1buf, n2buf); + + ogs_assert(OGS_OK == ngap_send_paging(amf_ue)); } else if (CM_CONNECTED(amf_ue)) { + gmmbuf = gmm_build_dl_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, n1buf, 0, 0); + ogs_assert(gmmbuf); + ngapbuf = ngap_build_pdu_session_resource_modify_request( sess, gmmbuf, n2buf); ogs_assert(ngapbuf); @@ -335,9 +359,10 @@ int amf_namf_comm_handle_n1_n2_message_transfer( return OGS_ERROR; } + if (n1buf) + ogs_pkbuf_free(n1buf); + if (CM_IDLE(amf_ue)) { - if (gmmbuf) - ogs_pkbuf_free(gmmbuf); if (n2buf) ogs_pkbuf_free(n2buf); diff --git a/src/amf/nas-path.c b/src/amf/nas-path.c index 8714276dd..d19f99ded 100644 --- a/src/amf/nas-path.c +++ b/src/amf/nas-path.c @@ -416,6 +416,37 @@ int nas_5gs_send_configuration_update_command( return rv; } +int nas_send_pdu_session_modification_command(amf_sess_t *sess, + ogs_pkbuf_t *n1smbuf, ogs_pkbuf_t *n2smbuf) +{ + int rv; + + amf_ue_t *amf_ue = NULL; + + ogs_pkbuf_t *gmmbuf = NULL; + ogs_pkbuf_t *ngapbuf = NULL; + + ogs_assert(sess); + amf_ue = sess->amf_ue; + ogs_assert(amf_ue); + ogs_assert(n1smbuf); + ogs_assert(n2smbuf); + + gmmbuf = gmm_build_dl_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, n1smbuf, 0, 0); + ogs_expect_or_return_val(gmmbuf, OGS_ERROR); + + ngapbuf = ngap_build_pdu_session_resource_modify_request( + sess, gmmbuf, n2smbuf); + ogs_expect_or_return_val(ngapbuf, OGS_ERROR); + + rv = nas_5gs_send_to_gnb(amf_ue, ngapbuf); + ogs_expect(rv == OGS_OK); + + return rv; +} + + int nas_send_pdu_session_release_command(amf_sess_t *sess, ogs_pkbuf_t *n1smbuf, ogs_pkbuf_t *n2smbuf) { diff --git a/src/amf/nas-path.h b/src/amf/nas-path.h index 1a9a0736e..27f50efd0 100644 --- a/src/amf/nas-path.h +++ b/src/amf/nas-path.h @@ -52,6 +52,9 @@ int nas_5gs_send_security_mode_command(amf_ue_t *amf_ue); int nas_5gs_send_configuration_update_command( amf_ue_t *amf_ue, gmm_configuration_update_command_param_t *param); +int nas_send_pdu_session_modification_command(amf_sess_t *sess, + ogs_pkbuf_t *n1smbuf, ogs_pkbuf_t *n2smbuf); + int nas_send_pdu_session_release_command(amf_sess_t *sess, ogs_pkbuf_t *n1smbuf, ogs_pkbuf_t *n2smbuf); diff --git a/src/amf/ngap-handler.c b/src/amf/ngap-handler.c index 9e402908c..71481a30b 100644 --- a/src/amf/ngap-handler.c +++ b/src/amf/ngap-handler.c @@ -759,8 +759,6 @@ void ngap_handle_initial_context_setup_response( uint64_t amf_ue_ngap_id; amf_nsmf_pdusession_sm_context_param_t param; - bool paging_ongoing = false; - NGAP_SuccessfulOutcome_t *successfulOutcome = NULL; NGAP_InitialContextSetupResponse_t *InitialContextSetupResponse = NULL; @@ -913,14 +911,60 @@ void ngap_handle_initial_context_setup_response( ogs_pkbuf_free(param.n2smbuf); } - ogs_list_for_each(&amf_ue->sess_list, sess) { - if (sess->paging.ongoing == true) { - paging_ongoing = true; - break; - } - } + /* + * TS24.501 + * 5.4.4 Generic UE configuration update procedure + * 5.4.4.1 General + * + * This procedure shall be initiated by the network to assign + * a new 5G-GUTI to the UE after a successful service request + * procedure invoked as a response to a paging request + * from the network and before the release of the N1 NAS signalling + * connection. + */ + if (DOWNLINK_SIGNALLING_PENDING(amf_ue) == true) { + /* + * TS24.501 + * 5.4.4 Generic UE configuration update procedure + * 5.4.4.1 General + * + * If the service request procedure was triggered + * due to 5GSM downlink signalling pending, the procedure + * for assigning a new 5G-GUTI can be initiated by the network + * after the transport of the 5GSM downlink signalling. + */ + ogs_list_for_each(&amf_ue->sess_list, sess) { + ogs_pkbuf_t *ngapbuf = NULL; + ogs_pkbuf_t *gmmbuf = NULL; - if (paging_ongoing == true) { + /* There is no Downlink Signalling Pending in this sesssion */ + if (sess->gsm_message.type == 0) continue; + + switch (sess->gsm_message.type) { + case OGS_NAS_5GS_PDU_SESSION_MODIFICATION_COMMAND: + gmmbuf = gmm_build_dl_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, + sess->gsm_message.n1buf, 0, 0); + ogs_assert(gmmbuf); + + ngapbuf = ngap_build_pdu_session_resource_modify_request( + sess, gmmbuf, sess->gsm_message.n2buf); + ogs_assert(ngapbuf); + + if (nas_5gs_send_to_gnb(amf_ue, ngapbuf) != OGS_OK) { + ogs_error("nas_5gs_send_to_gnb() failed"); + } + + AMF_SESS_CLEAR_5GSM_MESSAGE(sess); + + break; + default: + ogs_fatal("Unknown GSM Message Type[%d]", + sess->gsm_message.type); + ogs_assert_if_reached(); + } + } + } else if (PAGING_ONGOING(amf_ue) == true) { gmm_configuration_update_command_param_t param; /* @@ -951,9 +995,9 @@ void ngap_handle_initial_context_setup_response( param.guti = 1; ogs_assert(OGS_OK == nas_5gs_send_configuration_update_command(amf_ue, ¶m)); - } - AMF_UE_CLEAR_PAGING_INFO(amf_ue); + AMF_UE_CLEAR_PAGING_INFO(amf_ue); + } } void ngap_handle_initial_context_setup_failure( diff --git a/src/amf/nsmf-handler.c b/src/amf/nsmf-handler.c index 64578b0fb..670f01a5d 100644 --- a/src/amf/nsmf-handler.c +++ b/src/amf/nsmf-handler.c @@ -255,6 +255,43 @@ int amf_nsmf_pdusession_handle_update_sm_context( } break; + case OpenAPI_n2_sm_info_type_PDU_RES_MOD_REQ: + if (!n1smbuf) { + ogs_error("[%s:%d] No N1 SM Content [%s]", + amf_ue->supi, sess->psi, n1SmMsg->content_id); + ogs_assert(OGS_OK == + nas_5gs_send_back_gsm_message(sess, + OGS_5GMM_CAUSE_PAYLOAD_WAS_NOT_FORWARDED, + AMF_NAS_BACKOFF_TIME)); + return OGS_ERROR; + } + + if (!n2smbuf) { + ogs_error("[%s:%d] No N2 SM Content", + amf_ue->supi, sess->psi); + ogs_assert(OGS_OK == + nas_5gs_send_back_gsm_message(sess, + OGS_5GMM_CAUSE_PAYLOAD_WAS_NOT_FORWARDED, + AMF_NAS_BACKOFF_TIME)); + return OGS_ERROR; + } + + /* + * NOTE : The pkbuf created in the SBI message will be removed + * from ogs_sbi_message_free(), so it must be copied. + */ + n1smbuf = ogs_pkbuf_copy(n1smbuf); + ogs_assert(n1smbuf); + + n2smbuf = ogs_pkbuf_copy(n2smbuf); + ogs_assert(n2smbuf); + + ogs_assert(OGS_OK == + nas_send_pdu_session_modification_command( + sess, n1smbuf, n2smbuf)); + break; + + case OpenAPI_n2_sm_info_type_PDU_RES_REL_CMD: if (!n1smbuf) { ogs_error("[%s:%d] No N1 SM Content [%s]", diff --git a/src/pcf/context.c b/src/pcf/context.c index 943c4b283..129fcba09 100644 --- a/src/pcf/context.c +++ b/src/pcf/context.c @@ -25,6 +25,7 @@ int __pcf_log_domain; static OGS_POOL(pcf_ue_pool, pcf_ue_t); static OGS_POOL(pcf_sess_pool, pcf_sess_t); +static OGS_POOL(pcf_app_pool, pcf_app_t); static int context_initialized = 0; @@ -43,6 +44,7 @@ void pcf_context_init(void) ogs_pool_init(&pcf_ue_pool, ogs_app()->max.ue); ogs_pool_init(&pcf_sess_pool, ogs_app()->pool.sess); + ogs_pool_init(&pcf_app_pool, ogs_app()->pool.sess); ogs_list_init(&self.pcf_ue_list); @@ -69,6 +71,7 @@ void pcf_context_final(void) ogs_assert(self.ipv6prefix_hash); ogs_hash_destroy(self.ipv6prefix_hash); + ogs_pool_final(&pcf_app_pool); ogs_pool_final(&pcf_sess_pool); ogs_pool_final(&pcf_ue_pool); @@ -238,6 +241,8 @@ pcf_sess_t *pcf_sess_add(pcf_ue_t *pcf_ue, uint8_t psi) ogs_assert(sess); memset(sess, 0, sizeof *sess); + ogs_list_init(&sess->app_list); + /* SBI Type */ sess->sbi.type = OGS_SBI_OBJ_SESS_TYPE; @@ -257,10 +262,6 @@ pcf_sess_t *pcf_sess_add(pcf_ue_t *pcf_ue, uint8_t psi) (int)ogs_pool_index(&pcf_sess_pool, sess)); ogs_assert(sess->sm_policy_id); - sess->app_session_id = ogs_msprintf("%d", - (int)ogs_pool_index(&pcf_sess_pool, sess)); - ogs_assert(sess->app_session_id); - sess->pcf_ue = pcf_ue; sess->psi = psi; @@ -294,12 +295,11 @@ void pcf_sess_remove(pcf_sess_t *sess) /* Free SBI object memory */ ogs_sbi_object_free(&sess->sbi); + pcf_app_remove_all(sess); + ogs_assert(sess->sm_policy_id); ogs_free(sess->sm_policy_id); - ogs_assert(sess->app_session_id); - ogs_free(sess->app_session_id); - if (sess->binding_id) ogs_free(sess->binding_id); @@ -410,12 +410,6 @@ pcf_sess_t *pcf_sess_find_by_sm_policy_id(char *sm_policy_id) return pcf_sess_find(atoll(sm_policy_id)); } -pcf_sess_t *pcf_sess_find_by_app_session_id(char *app_session_id) -{ - ogs_assert(app_session_id); - return pcf_sess_find(atoll(app_session_id)); -} - pcf_sess_t *pcf_sess_find_by_psi(pcf_ue_t *pcf_ue, uint8_t psi) { pcf_sess_t *sess = NULL; @@ -511,3 +505,70 @@ void pcf_sess_select_nf(pcf_sess_t *sess, OpenAPI_nf_type_e nf_type) else ogs_sbi_select_first_nf(&sess->sbi, nf_type, pcf_nf_state_registered); } + +pcf_app_t *pcf_app_add(pcf_sess_t *sess) +{ + pcf_app_t *app = NULL; + + ogs_assert(sess); + + ogs_pool_alloc(&pcf_app_pool, &app); + ogs_assert(app); + memset(app, 0, sizeof *app); + + app->app_session_id = ogs_msprintf("%d", + (int)ogs_pool_index(&pcf_app_pool, app)); + ogs_assert(app->app_session_id); + + app->sess = sess; + + ogs_list_add(&sess->app_list, app); + + return app; +} + +int pcf_app_remove(pcf_app_t *app) +{ + int i; + + ogs_assert(app); + ogs_assert(app->sess); + + ogs_list_remove(&app->sess->app_list, app); + + for (i = 0; i < app->num_of_pcc_rule; i++) { + OGS_PCC_RULE_FREE(&app->pcc_rule[i]); + } + + if (app->notif_uri) + ogs_free(app->notif_uri); + if (app->naf.client) + ogs_sbi_client_remove(app->naf.client); + + ogs_assert(app->app_session_id); + ogs_free(app->app_session_id); + + ogs_pool_free(&pcf_app_pool, app); + + return OGS_OK; +} + +void pcf_app_remove_all(pcf_sess_t *sess) +{ + pcf_app_t *app = NULL, *next_app = NULL; + + ogs_assert(sess); + ogs_list_for_each_safe(&sess->app_list, next_app, app) + pcf_app_remove(app); +} + +pcf_app_t *pcf_app_find(uint32_t index) +{ + return ogs_pool_find(&pcf_app_pool, index); +} + +pcf_app_t *pcf_app_find_by_app_session_id(char *app_session_id) +{ + ogs_assert(app_session_id); + return pcf_app_find(atoll(app_session_id)); +} diff --git a/src/pcf/context.h b/src/pcf/context.h index 75eeccf48..d2b449da3 100644 --- a/src/pcf/context.h +++ b/src/pcf/context.h @@ -122,8 +122,6 @@ struct pcf_sess_s { uint8_t addr6[OGS_IPV6_LEN]; } ipv6prefix; - char *app_session_id; - ogs_s_nssai_t s_nssai; /* SBI Features */ @@ -134,10 +132,28 @@ struct pcf_sess_s { OpenAPI_ambr_t *subscribed_sess_ambr; OpenAPI_subscribed_default_qos_t *subscribed_default_qos; + ogs_list_t app_list; + /* Related Context */ pcf_ue_t *pcf_ue; }; +typedef struct pcf_app_s { + ogs_lnode_t lnode; + + char *app_session_id; + + char *notif_uri; + struct { + ogs_sbi_client_t *client; + } naf; + + ogs_pcc_rule_t pcc_rule[OGS_MAX_NUM_OF_PCC_RULE]; + int num_of_pcc_rule; + + pcf_sess_t *sess; +} pcf_app_t; + void pcf_context_init(void); void pcf_context_final(void); pcf_context_t *pcf_self(void); @@ -159,7 +175,6 @@ bool pcf_sess_set_ipv6prefix(pcf_sess_t *sess, char *ipv6prefix); pcf_sess_t *pcf_sess_find(uint32_t index); pcf_sess_t *pcf_sess_find_by_sm_policy_id(char *sm_policy_id); -pcf_sess_t *pcf_sess_find_by_app_session_id(char *app_session_id); pcf_sess_t *pcf_sess_find_by_psi(pcf_ue_t *pcf_ue, uint8_t psi); pcf_sess_t *pcf_sess_find_by_dnn(pcf_ue_t *pcf_ue, char *dnn); pcf_sess_t *pcf_sess_find_by_ipv4addr(char *ipv4addr_string); @@ -172,6 +187,12 @@ pcf_sess_t *pcf_sess_cycle(pcf_sess_t *sess); void pcf_ue_select_nf(pcf_ue_t *pcf_ue, OpenAPI_nf_type_e nf_type); void pcf_sess_select_nf(pcf_sess_t *sess, OpenAPI_nf_type_e nf_type); +pcf_app_t *pcf_app_add(pcf_sess_t *sess); +int pcf_app_remove(pcf_app_t *app); +void pcf_app_remove_all(pcf_sess_t *sess); +pcf_app_t *pcf_app_find(uint32_t index); +pcf_app_t *pcf_app_find_by_app_session_id(char *app_session_id); + #ifdef __cplusplus } #endif diff --git a/src/pcf/event.h b/src/pcf/event.h index bc2ab5006..58de3e609 100644 --- a/src/pcf/event.h +++ b/src/pcf/event.h @@ -34,6 +34,7 @@ typedef struct ogs_sbi_subscription_s ogs_sbi_subscription_t; typedef struct pcf_ue_s pcf_ue_t; typedef struct pcf_sess_s pcf_sess_t; +typedef struct pcf_app_s pcf_app_t; typedef enum { PCF_EVT_BASE = OGS_FSM_USER_SIG, @@ -60,6 +61,7 @@ typedef struct pcf_event_s { pcf_ue_t *pcf_ue; pcf_sess_t *sess; + pcf_app_t *app; ogs_timer_t *timer; } pcf_event_t; diff --git a/src/pcf/meson.build b/src/pcf/meson.build index d6e04010d..72ed9125e 100644 --- a/src/pcf/meson.build +++ b/src/pcf/meson.build @@ -34,6 +34,7 @@ libpcf_sources = files(''' namf-build.c nsmf-build.c + naf-build.c am-sm.c sm-sm.c diff --git a/src/pcf/naf-build.c b/src/pcf/naf-build.c new file mode 100644 index 000000000..e74fdf92e --- /dev/null +++ b/src/pcf/naf-build.c @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2019 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "naf-build.h" + +ogs_sbi_request_t *pcf_naf_callback_build_policyauthorization_terminate( + pcf_app_t *app_session, void *data) +{ + ogs_sbi_message_t message; + ogs_sbi_request_t *request = NULL; + + ogs_assert(app_session); + + memset(&message, 0, sizeof(message)); + message.h.method = (char *)OGS_SBI_HTTP_METHOD_POST; + message.h.uri = ogs_mstrcatf( + app_session->notif_uri, "/%s", OGS_SBI_RESOURCE_NAME_TERMINATE); + ogs_assert(message.h.uri); + + request = ogs_sbi_build_request(&message); + ogs_assert(request); + + ogs_free(message.h.uri); + + return request; +} diff --git a/src/pcf/naf-build.h b/src/pcf/naf-build.h new file mode 100644 index 000000000..d36aaa45e --- /dev/null +++ b/src/pcf/naf-build.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2019 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef PCF_NAF_BUILD_H +#define PCF_NAF_BUILD_H + +#include "context.h" + +#ifdef __cplusplus +extern "C" { +#endif + +ogs_sbi_request_t *pcf_naf_callback_build_policyauthorization_terminate( + pcf_app_t *app_session, void *data); + +#ifdef __cplusplus +} +#endif + +#endif /* PCF_NAF_BUILD_H */ diff --git a/src/pcf/nbsf-handler.c b/src/pcf/nbsf-handler.c index 58e7bca0b..fc48a5e28 100644 --- a/src/pcf/nbsf-handler.c +++ b/src/pcf/nbsf-handler.c @@ -24,7 +24,7 @@ bool pcf_nbsf_management_handle_register( pcf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg) { - int i, j, rv, status = 0; + int i, rv, status = 0; char *strerror = NULL; pcf_ue_t *pcf_ue = NULL; ogs_sbi_server_t *server = NULL; @@ -43,7 +43,7 @@ bool pcf_nbsf_management_handle_register( OpenAPI_sm_policy_decision_t SmPolicyDecision; - OpenAPI_lnode_t *node = NULL, *node2 = NULL; + OpenAPI_lnode_t *node = NULL; OpenAPI_list_t *SessRuleList = NULL; OpenAPI_map_t *SessRuleMap = NULL; @@ -55,7 +55,6 @@ bool pcf_nbsf_management_handle_register( OpenAPI_list_t *PccRuleList = NULL; OpenAPI_map_t *PccRuleMap = NULL; OpenAPI_pcc_rule_t *PccRule = NULL; - OpenAPI_flow_information_t *FlowInformation = NULL; OpenAPI_list_t *QosDecisionList = NULL; OpenAPI_map_t *QosDecisionMap = NULL; @@ -275,110 +274,26 @@ bool pcf_nbsf_management_handle_register( ogs_assert(QosDecisionList); for (i = 0; i < session_data.num_of_pcc_rule; i++) { - OpenAPI_list_t *FlowInformationList = NULL; ogs_pcc_rule_t *pcc_rule = &session_data.pcc_rule[i]; ogs_assert(pcc_rule); - PccRule = ogs_calloc(1, sizeof(*PccRule)); - ogs_assert(PccRule); - QosData = ogs_calloc(1, sizeof(*QosData)); - ogs_assert(QosData); - - /* - * At this point, only 1 QosData is used for PccRule. - * Therefore, QoS ID uses the same value as PCC Rule ID. - */ - PccRule->pcc_rule_id = pcc_rule->id; - QosData->qos_id = pcc_rule->id; - - PccRule->ref_qos_data = OpenAPI_list_create(); - ogs_assert(PccRule->ref_qos_data); - - OpenAPI_list_add(PccRule->ref_qos_data, QosData->qos_id); - - PccRule->is_precedence = true; - PccRule->precedence = pcc_rule->precedence; - - FlowInformationList = OpenAPI_list_create(); - ogs_assert(FlowInformationList); - - for (j = 0; j < pcc_rule->num_of_flow; j++) { - ogs_flow_t *flow = &pcc_rule->flow[j]; - ogs_assert(flow); - - FlowInformation = ogs_calloc(1, sizeof(*FlowInformation)); - ogs_assert(FlowInformation); - - if (flow->direction == OGS_FLOW_UPLINK_ONLY) - FlowInformation->flow_direction = - OpenAPI_flow_direction_UPLINK; - else if (flow->direction == OGS_FLOW_DOWNLINK_ONLY) - FlowInformation->flow_direction = - OpenAPI_flow_direction_DOWNLINK; - else { - ogs_fatal("Unsupported direction [%d]", flow->direction); - ogs_assert_if_reached(); - } - - ogs_assert(flow->description); - FlowInformation->flow_description = flow->description; - - OpenAPI_list_add(FlowInformationList, FlowInformation); + if (!pcc_rule->num_of_flow) { + /* No Flow */ + continue; } - if (FlowInformationList->count) - PccRule->flow_infos = FlowInformationList; - else - OpenAPI_list_free(FlowInformationList); + PccRule = ogs_sbi_build_pcc_rule(pcc_rule, 1); + ogs_assert(PccRule->pcc_rule_id); PccRuleMap = OpenAPI_map_create(PccRule->pcc_rule_id, PccRule); ogs_assert(PccRuleMap); OpenAPI_list_add(PccRuleList, PccRuleMap); - QosData->is__5qi = true; - QosData->_5qi = pcc_rule->qos.index; - QosData->is_priority_level = true; - QosData->priority_level = pcc_rule->qos.arp.priority_level; - - QosData->arp = ogs_calloc(1, sizeof(OpenAPI_arp_t)); - ogs_assert(QosData->arp); - - if (pcc_rule->qos.arp.pre_emption_capability == - OGS_5GC_PRE_EMPTION_ENABLED) - QosData->arp->preempt_cap = - OpenAPI_preemption_capability_MAY_PREEMPT; - else if (pcc_rule->qos.arp.pre_emption_capability == - OGS_5GC_PRE_EMPTION_DISABLED) - QosData->arp->preempt_cap = - OpenAPI_preemption_capability_NOT_PREEMPT; - ogs_assert(pcc_rule->qos.arp.pre_emption_capability); - - if (pcc_rule->qos.arp.pre_emption_vulnerability == - OGS_5GC_PRE_EMPTION_ENABLED) - QosData->arp->preempt_vuln = - OpenAPI_preemption_vulnerability_PREEMPTABLE; - else if (pcc_rule->qos.arp.pre_emption_vulnerability == - OGS_5GC_PRE_EMPTION_DISABLED) - QosData->arp->preempt_vuln = - OpenAPI_preemption_vulnerability_NOT_PREEMPTABLE; - ogs_assert(pcc_rule->qos.arp.pre_emption_vulnerability); - QosData->arp->priority_level = pcc_rule->qos.arp.priority_level; - - if (pcc_rule->qos.mbr.uplink) - QosData->maxbr_ul = ogs_sbi_bitrate_to_string( - pcc_rule->qos.mbr.uplink, OGS_SBI_BITRATE_KBPS); - if (pcc_rule->qos.mbr.downlink) - QosData->maxbr_dl = ogs_sbi_bitrate_to_string( - pcc_rule->qos.mbr.downlink, OGS_SBI_BITRATE_KBPS); - - if (pcc_rule->qos.gbr.uplink) - QosData->gbr_ul = ogs_sbi_bitrate_to_string( - pcc_rule->qos.gbr.uplink, OGS_SBI_BITRATE_KBPS); - if (pcc_rule->qos.gbr.downlink) - QosData->gbr_dl = ogs_sbi_bitrate_to_string( - pcc_rule->qos.gbr.downlink, OGS_SBI_BITRATE_KBPS); + QosData = ogs_sbi_build_qos_data(pcc_rule); + ogs_assert(QosData); + ogs_assert(QosData->qos_id); QosDecisionMap = OpenAPI_map_create(QosData->qos_id, QosData); ogs_assert(QosDecisionMap); @@ -446,18 +361,8 @@ bool pcf_nbsf_management_handle_register( PccRuleMap = node->data; if (PccRuleMap) { PccRule = PccRuleMap->value; - if (PccRule) { - if (PccRule->ref_qos_data) - OpenAPI_list_free(PccRule->ref_qos_data); - if (PccRule->flow_infos) { - OpenAPI_list_for_each(PccRule->flow_infos, node2) { - FlowInformation = node2->data; - if (FlowInformation) ogs_free(FlowInformation); - } - OpenAPI_list_free(PccRule->flow_infos); - } - ogs_free(PccRule); - } + if (PccRule) + ogs_sbi_free_pcc_rule(PccRule); ogs_free(PccRuleMap); } } @@ -467,15 +372,8 @@ bool pcf_nbsf_management_handle_register( QosDecisionMap = node->data; if (QosDecisionMap) { QosData = QosDecisionMap->value; - if (QosData) { - if (QosData->arp) ogs_free(QosData->arp); - if (QosData->maxbr_ul) ogs_free(QosData->maxbr_ul); - if (QosData->maxbr_dl) ogs_free(QosData->maxbr_dl); - if (QosData->gbr_ul) ogs_free(QosData->gbr_ul); - if (QosData->gbr_dl) ogs_free(QosData->gbr_dl); - - ogs_free(QosData); - } + if (QosData) + ogs_sbi_free_qos_data(QosData); ogs_free(QosDecisionMap); } } diff --git a/src/pcf/npcf-handler.c b/src/pcf/npcf-handler.c index 50e48acab..fe398bfc6 100644 --- a/src/pcf/npcf-handler.c +++ b/src/pcf/npcf-handler.c @@ -133,7 +133,7 @@ bool pcf_npcf_am_policy_contrtol_handle_create(pcf_ue_t *pcf_ue, return true; } -bool pcf_npcf_smpolicycontrtol_handle_create(pcf_sess_t *sess, +bool pcf_npcf_smpolicycontrol_handle_create(pcf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_sbi_message_t *message) { int status = 0; @@ -293,12 +293,13 @@ cleanup: return false; } -bool pcf_npcf_smpolicycontrtol_handle_delete(pcf_sess_t *sess, +bool pcf_npcf_smpolicycontrol_handle_delete(pcf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_sbi_message_t *message) { int status = 0; char *strerror = NULL; pcf_ue_t *pcf_ue = NULL; + pcf_app_t *app_session = NULL; OpenAPI_sm_policy_delete_data_t *SmPolicyDeleteData = NULL; @@ -315,6 +316,10 @@ bool pcf_npcf_smpolicycontrtol_handle_delete(pcf_sess_t *sess, goto cleanup; } + ogs_list_for_each(&sess->app_list, app_session) { + pcf_sbi_send_policyauthorization_terminate_notify(app_session); + } + ogs_assert(true == pcf_sess_sbi_discover_and_send(OpenAPI_nf_type_BSF, sess, stream, NULL, pcf_nbsf_management_build_de_register)); @@ -335,9 +340,13 @@ cleanup: bool pcf_npcf_policyauthorization_handle_create(pcf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg) { - int status = 0; + int i, j, rv, status = 0; char *strerror = NULL; pcf_ue_t *pcf_ue = NULL; + pcf_app_t *app_session = NULL; + + ogs_sbi_client_t *client = NULL; + ogs_sockaddr_t *addr = NULL; OpenAPI_app_session_context_t *AppSessionContext = NULL; OpenAPI_app_session_context_req_data_t *AscReqData = NULL; @@ -349,6 +358,8 @@ bool pcf_npcf_policyauthorization_handle_create(pcf_sess_t *sess, ogs_sbi_message_t sendmsg; ogs_sbi_response_t *response = NULL; + ogs_session_data_t session_data; + ogs_ims_data_t ims_data; ogs_media_component_t *media_component = NULL; ogs_media_sub_component_t *sub = NULL; @@ -363,6 +374,16 @@ bool pcf_npcf_policyauthorization_handle_create(pcf_sess_t *sess, OpenAPI_list_t *fDescList = NULL; + OpenAPI_sm_policy_decision_t SmPolicyDecision; + + OpenAPI_list_t *PccRuleList = NULL; + OpenAPI_map_t *PccRuleMap = NULL; + OpenAPI_pcc_rule_t *PccRule = NULL; + + OpenAPI_list_t *QosDecisionList = NULL; + OpenAPI_map_t *QosDecisionMap = NULL; + OpenAPI_qos_data_t *QosData = NULL; + OpenAPI_lnode_t *node = NULL, *node2 = NULL, *node3 = NULL; ogs_assert(sess); @@ -370,8 +391,6 @@ bool pcf_npcf_policyauthorization_handle_create(pcf_sess_t *sess, ogs_assert(stream); ogs_assert(recvmsg); - ogs_assert(sess->app_session_id); - server = ogs_sbi_server_from_stream(stream); ogs_assert(server); @@ -412,6 +431,14 @@ bool pcf_npcf_policyauthorization_handle_create(pcf_sess_t *sess, goto cleanup; } + addr = ogs_sbi_getaddr_from_uri(AscReqData->notif_uri); + if (!addr) { + strerror = ogs_msprintf("[%s:%d] Invalid URI [%s]", + pcf_ue->supi, sess->psi, AscReqData->notif_uri); + status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; + goto cleanup; + } + supported_features = ogs_uint64_from_string(AscReqData->supp_feat); sess->policyauthorization_features &= supported_features; @@ -423,8 +450,6 @@ bool pcf_npcf_policyauthorization_handle_create(pcf_sess_t *sess, } memset(&ims_data, 0, sizeof(ims_data)); - media_component = &ims_data. - media_component[ims_data.num_of_media_component]; MediaComponentList = AscReqData->med_components; OpenAPI_list_for_each(MediaComponentList, node) { @@ -432,6 +457,8 @@ bool pcf_npcf_policyauthorization_handle_create(pcf_sess_t *sess, if (MediaComponentMap) { MediaComponent = MediaComponentMap->value; if (MediaComponent) { + media_component = &ims_data. + media_component[ims_data.num_of_media_component]; media_component->media_component_number = MediaComponent->med_comp_n; media_component->media_type = MediaComponent->med_type; @@ -447,12 +474,18 @@ bool pcf_npcf_policyauthorization_handle_create(pcf_sess_t *sess, if (MediaComponent->mir_bw_ul) media_component->min_requested_bandwidth_ul = ogs_sbi_bitrate_from_string(MediaComponent->mir_bw_ul); + if (MediaComponent->rr_bw) + media_component->rr_bandwidth = + ogs_sbi_bitrate_from_string(MediaComponent->rr_bw); + if (MediaComponent->rs_bw) + media_component->rs_bandwidth = + ogs_sbi_bitrate_from_string(MediaComponent->rs_bw); media_component->flow_status = MediaComponent->f_status; - sub = &media_component->sub[media_component->num_of_sub]; - SubComponentList = MediaComponent->med_sub_comps; OpenAPI_list_for_each(SubComponentList, node2) { + sub = &media_component->sub[media_component->num_of_sub]; + SubComponentMap = node2->data; if (SubComponentMap) { SubComponent = SubComponentMap->value; @@ -474,22 +507,225 @@ bool pcf_npcf_policyauthorization_handle_create(pcf_sess_t *sess, sub->num_of_flow++; } } + media_component->num_of_sub++; } } - media_component->num_of_sub++; + } + ims_data.num_of_media_component++; + } + } + } + + app_session = pcf_app_add(sess); + ogs_assert(app_session); + + if (app_session->notif_uri) + ogs_free(app_session->notif_uri); + app_session->notif_uri = ogs_strdup(AscReqData->notif_uri); + ogs_assert(app_session->notif_uri); + + client = ogs_sbi_client_find(addr); + if (!client) { + client = ogs_sbi_client_add(addr); + ogs_assert(client); + } + OGS_SETUP_SBI_CLIENT(&app_session->naf, client); + + ogs_freeaddrinfo(addr); + + memset(&session_data, 0, sizeof(ogs_session_data_t)); + rv = ogs_dbi_session_data( + pcf_ue->supi, &sess->s_nssai, sess->dnn, &session_data); + if (rv != OGS_OK) { + strerror = ogs_msprintf("[%s:%d] Cannot find SUPI in DB", + pcf_ue->supi, sess->psi); + status = OGS_SBI_HTTP_STATUS_NOT_FOUND; + goto cleanup; + } + + memset(&SmPolicyDecision, 0, sizeof(SmPolicyDecision)); + + PccRuleList = OpenAPI_list_create(); + ogs_assert(PccRuleList); + + QosDecisionList = OpenAPI_list_create(); + ogs_assert(QosDecisionList); + + for (i = 0; i < ims_data.num_of_media_component; i++) { + int flow_presence = 0; + + ogs_pcc_rule_t *pcc_rule = NULL; + ogs_pcc_rule_t *db_pcc_rule = NULL; + uint8_t qos_index = 0; + ogs_media_component_t *media_component = &ims_data.media_component[i]; + + switch(media_component->media_type) { + case OpenAPI_media_type_AUDIO: + qos_index = OGS_QOS_INDEX_1; + break; + case OpenAPI_media_type_VIDEO: + qos_index = OGS_QOS_INDEX_2; + break; + case OpenAPI_media_type_CONTROL: + qos_index = OGS_QOS_INDEX_5; + break; + default: + strerror = ogs_msprintf("[%s:%d] Not implemented : [Media-Type:%d]", + pcf_ue->supi, sess->psi, media_component->media_type); + status = OGS_SBI_HTTP_STATUS_INTERNAL_SERVER_ERROR; + goto cleanup; + } + + for (j = 0; j < session_data.num_of_pcc_rule; j++) { + if (session_data.pcc_rule[j].qos.index == qos_index) { + db_pcc_rule = &session_data.pcc_rule[j]; + break; + } + } + + if (!db_pcc_rule && + (media_component->media_type == OpenAPI_media_type_CONTROL)) { + /* + * Check for default bearer for IMS signalling + * QCI 5 and ARP 1 + */ + if (session_data.session.qos.index != OGS_QOS_INDEX_5 || + session_data.session.qos.arp.priority_level != 1) { + strerror = ogs_msprintf("[%s:%d] CHECK WEBUI : " + "Even the Default Bearer(QCI:%d,ARP:%d) " + "cannot support IMS signalling.", + pcf_ue->supi, sess->psi, + session_data.session.qos.index, + session_data.session.qos.arp.priority_level); + status = OGS_SBI_HTTP_STATUS_FORBIDDEN; + goto cleanup; + } else { + continue; + } + } + + if (!db_pcc_rule) { + strerror = ogs_msprintf("[%s:%d] CHECK WEBUI : " + "No PCC Rule in DB [QoS Index:%d] - " + "Please add PCC Rule using WEBUI", + pcf_ue->supi, sess->psi, qos_index); + status = OGS_SBI_HTTP_STATUS_FORBIDDEN; + goto cleanup; + } + + for (j = 0; j < app_session->num_of_pcc_rule; j++) { + if (app_session->pcc_rule[j].qos.index == qos_index) { + pcc_rule = &app_session->pcc_rule[j]; + break; + } + } + + if (!pcc_rule) { + pcc_rule = &app_session->pcc_rule[app_session->num_of_pcc_rule]; + ogs_assert(pcc_rule); + + pcc_rule->id = ogs_msprintf("%s-a%s", + db_pcc_rule->id, app_session->app_session_id); + ogs_assert(pcc_rule->id); + + memcpy(&pcc_rule->qos, &db_pcc_rule->qos, sizeof(ogs_qos_t)); + + pcc_rule->flow_status = db_pcc_rule->flow_status; + pcc_rule->precedence = db_pcc_rule->precedence; + + /* Install Flow */ + flow_presence = 1; + rv = ogs_pcc_rule_install_flow_from_media( + pcc_rule, media_component); + if (rv != OGS_OK) { + strerror = ogs_msprintf("[%s:%d] install_flow() failed", + pcf_ue->supi, sess->psi); + status = OGS_SBI_HTTP_STATUS_FORBIDDEN; + goto cleanup; + } + + app_session->num_of_pcc_rule++; + + } else { + int count = 0; + + /* Check Flow */ + count = ogs_pcc_rule_num_of_flow_equal_to_media( + pcc_rule, media_component); + if (count == -1) { + strerror = ogs_msprintf("[%s:%d] matched_flow() failed", + pcf_ue->supi, sess->psi); + status = OGS_SBI_HTTP_STATUS_FORBIDDEN; + goto cleanup; + } + + if (pcc_rule->num_of_flow != count) { + /* Re-install Flow */ + flow_presence = 1; + rv = ogs_pcc_rule_install_flow_from_media( + pcc_rule, media_component); + if (rv != OGS_OK) { + strerror = ogs_msprintf("[%s:%d] re-install_flow() failed", + pcf_ue->supi, sess->psi); + status = OGS_SBI_HTTP_STATUS_FORBIDDEN; + goto cleanup; } } } - ims_data.num_of_media_component++; + + /* Update QoS */ + rv = ogs_pcc_rule_update_qos_from_media(pcc_rule, media_component); + if (rv != OGS_OK) { + strerror = ogs_msprintf("[%s:%d] update_qos() failed", + pcf_ue->supi, sess->psi); + status = OGS_SBI_HTTP_STATUS_FORBIDDEN; + goto cleanup; + } + + /* if we failed to get QoS from IMS, apply WEBUI QoS */ + if (pcc_rule->qos.mbr.downlink == 0) + pcc_rule->qos.mbr.downlink = db_pcc_rule->qos.mbr.downlink; + if (pcc_rule->qos.mbr.uplink == 0) + pcc_rule->qos.mbr.uplink = db_pcc_rule->qos.mbr.uplink; + if (pcc_rule->qos.gbr.downlink == 0) + pcc_rule->qos.gbr.downlink = db_pcc_rule->qos.gbr.downlink; + if (pcc_rule->qos.gbr.uplink == 0) + pcc_rule->qos.gbr.uplink = db_pcc_rule->qos.gbr.uplink; + + /************************************************************** + * Build PCC Rule & QoS Decision + *************************************************************/ + PccRule = ogs_sbi_build_pcc_rule(pcc_rule, flow_presence); + ogs_assert(PccRule->pcc_rule_id); + + PccRuleMap = OpenAPI_map_create(PccRule->pcc_rule_id, PccRule); + ogs_assert(PccRuleMap); + + OpenAPI_list_add(PccRuleList, PccRuleMap); + + QosData = ogs_sbi_build_qos_data(pcc_rule); + ogs_assert(QosData); + ogs_assert(QosData->qos_id); + + QosDecisionMap = OpenAPI_map_create(QosData->qos_id, QosData); + ogs_assert(QosDecisionMap); + + OpenAPI_list_add(QosDecisionList, QosDecisionMap); } + if (PccRuleList->count) + SmPolicyDecision.pcc_rules = PccRuleList; + + if (QosDecisionList->count) + SmPolicyDecision.qos_decs = QosDecisionList; + memset(&sendmsg, 0, sizeof(sendmsg)); memset(&header, 0, sizeof(header)); header.service.name = (char *)OGS_SBI_SERVICE_NAME_NPCF_POLICYAUTHORIZATION; header.api.version = (char *)OGS_SBI_API_V1; header.resource.component[0] = (char *)OGS_SBI_RESOURCE_NAME_APP_SESSIONS; - header.resource.component[1] = (char *)sess->app_session_id; + header.resource.component[1] = (char *)app_session->app_session_id; sendmsg.http.location = ogs_sbi_server_uri(server, &header); ogs_assert(sendmsg.http.location); @@ -501,12 +737,35 @@ bool pcf_npcf_policyauthorization_handle_create(pcf_sess_t *sess, ogs_free(sendmsg.http.location); -#if 0 - ogs_assert(true == pcf_sbi_send_smpolicycontrol_notify(sess)); - ogs_assert(true == pcf_sbi_send_am_policy_control_notify(pcf_ue)); -#endif + if (PccRuleList->count || QosDecisionList->count) { + ogs_assert(true == pcf_sbi_send_smpolicycontrol_update_notify( + sess, &SmPolicyDecision)); + } + + OpenAPI_list_for_each(PccRuleList, node) { + PccRuleMap = node->data; + if (PccRuleMap) { + PccRule = PccRuleMap->value; + if (PccRule) + ogs_sbi_free_pcc_rule(PccRule); + ogs_free(PccRuleMap); + } + } + OpenAPI_list_free(PccRuleList); + + OpenAPI_list_for_each(QosDecisionList, node) { + QosDecisionMap = node->data; + if (QosDecisionMap) { + QosData = QosDecisionMap->value; + if (QosData) + ogs_sbi_free_qos_data(QosData); + ogs_free(QosDecisionMap); + } + } + OpenAPI_list_free(QosDecisionList); ogs_ims_data_free(&ims_data); + ogs_session_data_free(&session_data); return true; @@ -518,7 +777,509 @@ cleanup: ogs_sbi_server_send_error(stream, status, recvmsg, strerror, NULL)); ogs_free(strerror); + OpenAPI_list_for_each(PccRuleList, node) { + PccRuleMap = node->data; + if (PccRuleMap) { + PccRule = PccRuleMap->value; + if (PccRule) + ogs_sbi_free_pcc_rule(PccRule); + ogs_free(PccRuleMap); + } + } + OpenAPI_list_free(PccRuleList); + + OpenAPI_list_for_each(QosDecisionList, node) { + QosDecisionMap = node->data; + if (QosDecisionMap) { + QosData = QosDecisionMap->value; + if (QosData) + ogs_sbi_free_qos_data(QosData); + ogs_free(QosDecisionMap); + } + } + OpenAPI_list_free(QosDecisionList); + ogs_ims_data_free(&ims_data); + ogs_session_data_free(&session_data); return false; } + +bool pcf_npcf_policyauthorization_handle_update( + pcf_sess_t *sess, pcf_app_t *app_session, + ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg) +{ + int i, j, rv, status = 0; + char *strerror = NULL; + pcf_ue_t *pcf_ue = NULL; + + OpenAPI_app_session_context_update_data_patch_t + *AppSessionContextUpdateDataPatch = NULL; + OpenAPI_app_session_context_update_data_t *AscUpdateData = NULL; + + ogs_sbi_message_t sendmsg; + ogs_sbi_response_t *response = NULL; + + ogs_session_data_t session_data; + + ogs_ims_data_t ims_data; + ogs_media_component_t *media_component = NULL; + ogs_media_sub_component_t *sub = NULL; + + OpenAPI_list_t *MediaComponentList = NULL; + OpenAPI_map_t *MediaComponentMap = NULL; + OpenAPI_media_component_rm_t *MediaComponent = NULL; + + OpenAPI_list_t *SubComponentList = NULL; + OpenAPI_map_t *SubComponentMap = NULL; + OpenAPI_media_sub_component_t *SubComponent = NULL; + + OpenAPI_list_t *fDescList = NULL; + + OpenAPI_sm_policy_decision_t SmPolicyDecision; + + OpenAPI_list_t *PccRuleList = NULL; + OpenAPI_map_t *PccRuleMap = NULL; + OpenAPI_pcc_rule_t *PccRule = NULL; + + OpenAPI_list_t *QosDecisionList = NULL; + OpenAPI_map_t *QosDecisionMap = NULL; + OpenAPI_qos_data_t *QosData = NULL; + + OpenAPI_lnode_t *node = NULL, *node2 = NULL, *node3 = NULL; + + ogs_assert(sess); + pcf_ue = sess->pcf_ue; + ogs_assert(app_session); + ogs_assert(stream); + ogs_assert(recvmsg); + + AppSessionContextUpdateDataPatch = + recvmsg->AppSessionContextUpdateDataPatch; + if (!AppSessionContextUpdateDataPatch) { + strerror = ogs_msprintf("[%s:%d] No AppSessionContextUpdateDataPatch", + pcf_ue->supi, sess->psi); + status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; + goto cleanup; + } + + AscUpdateData = AppSessionContextUpdateDataPatch->asc_req_data; + if (!AscUpdateData) { + strerror = ogs_msprintf("[%s:%d] No AscUpdateData", + pcf_ue->supi, sess->psi); + status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; + goto cleanup; + } + + if (!AscUpdateData->med_components) { + strerror = ogs_msprintf("[%s:%d] No AscUpdateData->MediaCompoenent", + pcf_ue->supi, sess->psi); + status = OGS_SBI_HTTP_STATUS_BAD_REQUEST; + goto cleanup; + } + + memset(&ims_data, 0, sizeof(ims_data)); + + MediaComponentList = AscUpdateData->med_components; + OpenAPI_list_for_each(MediaComponentList, node) { + MediaComponentMap = node->data; + if (MediaComponentMap) { + MediaComponent = MediaComponentMap->value; + if (MediaComponent) { + media_component = &ims_data. + media_component[ims_data.num_of_media_component]; + + media_component->media_component_number = + MediaComponent->med_comp_n; + media_component->media_type = MediaComponent->med_type; + if (MediaComponent->mar_bw_dl) + media_component->max_requested_bandwidth_dl = + ogs_sbi_bitrate_from_string(MediaComponent->mar_bw_dl); + if (MediaComponent->mar_bw_ul) + media_component->max_requested_bandwidth_ul = + ogs_sbi_bitrate_from_string(MediaComponent->mar_bw_ul); + if (MediaComponent->mir_bw_dl) + media_component->min_requested_bandwidth_dl = + ogs_sbi_bitrate_from_string(MediaComponent->mir_bw_dl); + if (MediaComponent->mir_bw_ul) + media_component->min_requested_bandwidth_ul = + ogs_sbi_bitrate_from_string(MediaComponent->mir_bw_ul); + if (MediaComponent->rr_bw) + media_component->rr_bandwidth = + ogs_sbi_bitrate_from_string(MediaComponent->rr_bw); + if (MediaComponent->rs_bw) + media_component->rs_bandwidth = + ogs_sbi_bitrate_from_string(MediaComponent->rs_bw); + media_component->flow_status = MediaComponent->f_status; + + SubComponentList = MediaComponent->med_sub_comps; + OpenAPI_list_for_each(SubComponentList, node2) { + sub = &media_component->sub[media_component->num_of_sub]; + + SubComponentMap = node2->data; + if (SubComponentMap) { + SubComponent = SubComponentMap->value; + if (SubComponent) { + sub->flow_number = SubComponent->f_num; + sub->flow_usage = SubComponent->flow_usage; + + fDescList = SubComponent->f_descs; + OpenAPI_list_for_each(fDescList, node3) { + ogs_flow_t *flow = NULL; + + ogs_assert(sub->num_of_flow < + OGS_MAX_NUM_OF_FLOW_IN_MEDIA_SUB_COMPONENT); + flow = &sub->flow[sub->num_of_flow]; + if (node3->data) { + flow->description = ogs_strdup(node3->data); + ogs_assert(flow->description); + + sub->num_of_flow++; + } + } + media_component->num_of_sub++; + } + } + } + ims_data.num_of_media_component++; + } + } + } + + memset(&session_data, 0, sizeof(ogs_session_data_t)); + rv = ogs_dbi_session_data( + pcf_ue->supi, &sess->s_nssai, sess->dnn, &session_data); + if (rv != OGS_OK) { + strerror = ogs_msprintf("[%s:%d] Cannot find SUPI in DB", + pcf_ue->supi, sess->psi); + status = OGS_SBI_HTTP_STATUS_NOT_FOUND; + goto cleanup; + } + + memset(&SmPolicyDecision, 0, sizeof(SmPolicyDecision)); + + PccRuleList = OpenAPI_list_create(); + ogs_assert(PccRuleList); + + QosDecisionList = OpenAPI_list_create(); + ogs_assert(QosDecisionList); + + for (i = 0; i < ims_data.num_of_media_component; i++) { + int flow_presence = 0; + + ogs_pcc_rule_t *pcc_rule = NULL; + ogs_pcc_rule_t *db_pcc_rule = NULL; + uint8_t qos_index = 0; + ogs_media_component_t *media_component = &ims_data.media_component[i]; + + switch(media_component->media_type) { + case OpenAPI_media_type_AUDIO: + qos_index = OGS_QOS_INDEX_1; + break; + case OpenAPI_media_type_VIDEO: + qos_index = OGS_QOS_INDEX_2; + break; + case OpenAPI_media_type_CONTROL: + qos_index = OGS_QOS_INDEX_5; + break; + default: + strerror = ogs_msprintf("[%s:%d] Not implemented : [Media-Type:%d]", + pcf_ue->supi, sess->psi, media_component->media_type); + status = OGS_SBI_HTTP_STATUS_INTERNAL_SERVER_ERROR; + goto cleanup; + } + + for (j = 0; j < session_data.num_of_pcc_rule; j++) { + if (session_data.pcc_rule[j].qos.index == qos_index) { + db_pcc_rule = &session_data.pcc_rule[j]; + break; + } + } + + if (!db_pcc_rule && + (media_component->media_type == OpenAPI_media_type_CONTROL)) { + /* + * Check for default bearer for IMS signalling + * QCI 5 and ARP 1 + */ + if (session_data.session.qos.index != OGS_QOS_INDEX_5 || + session_data.session.qos.arp.priority_level != 1) { + strerror = ogs_msprintf("[%s:%d] CHECK WEBUI : " + "Even the Default Bearer(QCI:%d,ARP:%d) " + "cannot support IMS signalling.", + pcf_ue->supi, sess->psi, + session_data.session.qos.index, + session_data.session.qos.arp.priority_level); + status = OGS_SBI_HTTP_STATUS_FORBIDDEN; + goto cleanup; + } else { + continue; + } + } + + if (!db_pcc_rule) { + strerror = ogs_msprintf("[%s:%d] CHECK WEBUI : " + "No PCC Rule in DB [QoS Index:%d] - " + "Please add PCC Rule using WEBUI", + pcf_ue->supi, sess->psi, qos_index); + status = OGS_SBI_HTTP_STATUS_FORBIDDEN; + goto cleanup; + } + + for (j = 0; j < app_session->num_of_pcc_rule; j++) { + if (app_session->pcc_rule[j].qos.index == qos_index) { + pcc_rule = &app_session->pcc_rule[j]; + break; + } + } + + if (!pcc_rule) { + pcc_rule = &app_session->pcc_rule[app_session->num_of_pcc_rule]; + ogs_assert(pcc_rule); + + pcc_rule->id = ogs_strdup(app_session->app_session_id); + ogs_assert(pcc_rule->id); + + memcpy(&pcc_rule->qos, &db_pcc_rule->qos, sizeof(ogs_qos_t)); + + pcc_rule->flow_status = db_pcc_rule->flow_status; + pcc_rule->precedence = db_pcc_rule->precedence; + + /* Install Flow */ + flow_presence = 1; + rv = ogs_pcc_rule_install_flow_from_media( + pcc_rule, media_component); + if (rv != OGS_OK) { + strerror = ogs_msprintf("[%s:%d] install_flow() failed", + pcf_ue->supi, sess->psi); + status = OGS_SBI_HTTP_STATUS_FORBIDDEN; + goto cleanup; + } + + app_session->num_of_pcc_rule++; + + } else { + int count = 0; + + /* Check Flow */ + count = ogs_pcc_rule_num_of_flow_equal_to_media( + pcc_rule, media_component); + if (count == -1) { + strerror = ogs_msprintf("[%s:%d] matched_flow() failed", + pcf_ue->supi, sess->psi); + status = OGS_SBI_HTTP_STATUS_FORBIDDEN; + goto cleanup; + } + + if (pcc_rule->num_of_flow != count) { + /* Re-install Flow */ + flow_presence = 1; + rv = ogs_pcc_rule_install_flow_from_media( + pcc_rule, media_component); + if (rv != OGS_OK) { + strerror = ogs_msprintf("[%s:%d] re-install_flow() failed", + pcf_ue->supi, sess->psi); + status = OGS_SBI_HTTP_STATUS_FORBIDDEN; + goto cleanup; + } + } + } + + /* Update QoS */ + rv = ogs_pcc_rule_update_qos_from_media(pcc_rule, media_component); + if (rv != OGS_OK) { + strerror = ogs_msprintf("[%s:%d] update_qos() failed", + pcf_ue->supi, sess->psi); + status = OGS_SBI_HTTP_STATUS_FORBIDDEN; + goto cleanup; + } + + /* if we failed to get QoS from IMS, apply WEBUI QoS */ + if (pcc_rule->qos.mbr.downlink == 0) + pcc_rule->qos.mbr.downlink = db_pcc_rule->qos.mbr.downlink; + if (pcc_rule->qos.mbr.uplink == 0) + pcc_rule->qos.mbr.uplink = db_pcc_rule->qos.mbr.uplink; + if (pcc_rule->qos.gbr.downlink == 0) + pcc_rule->qos.gbr.downlink = db_pcc_rule->qos.gbr.downlink; + if (pcc_rule->qos.gbr.uplink == 0) + pcc_rule->qos.gbr.uplink = db_pcc_rule->qos.gbr.uplink; + + /************************************************************** + * Build PCC Rule & QoS Decision + *************************************************************/ + PccRule = ogs_sbi_build_pcc_rule(pcc_rule, flow_presence); + ogs_assert(PccRule->pcc_rule_id); + + PccRuleMap = OpenAPI_map_create(PccRule->pcc_rule_id, PccRule); + ogs_assert(PccRuleMap); + + OpenAPI_list_add(PccRuleList, PccRuleMap); + + QosData = ogs_sbi_build_qos_data(pcc_rule); + ogs_assert(QosData); + ogs_assert(QosData->qos_id); + + QosDecisionMap = OpenAPI_map_create(QosData->qos_id, QosData); + ogs_assert(QosDecisionMap); + + OpenAPI_list_add(QosDecisionList, QosDecisionMap); + } + + if (PccRuleList->count) + SmPolicyDecision.pcc_rules = PccRuleList; + + if (QosDecisionList->count) + SmPolicyDecision.qos_decs = QosDecisionList; + + memset(&sendmsg, 0, sizeof(sendmsg)); + + sendmsg.AppSessionContextUpdateDataPatch = + recvmsg->AppSessionContextUpdateDataPatch; + + response = ogs_sbi_build_response(&sendmsg, OGS_SBI_HTTP_STATUS_OK); + ogs_assert(response); + ogs_assert(true == ogs_sbi_server_send_response(stream, response)); + + if (PccRuleList->count || QosDecisionList->count) { + ogs_assert(true == pcf_sbi_send_smpolicycontrol_update_notify( + sess, &SmPolicyDecision)); + } + + OpenAPI_list_for_each(PccRuleList, node) { + PccRuleMap = node->data; + if (PccRuleMap) { + PccRule = PccRuleMap->value; + if (PccRule) + ogs_sbi_free_pcc_rule(PccRule); + ogs_free(PccRuleMap); + } + } + OpenAPI_list_free(PccRuleList); + + OpenAPI_list_for_each(QosDecisionList, node) { + QosDecisionMap = node->data; + if (QosDecisionMap) { + QosData = QosDecisionMap->value; + if (QosData) + ogs_sbi_free_qos_data(QosData); + ogs_free(QosDecisionMap); + } + } + OpenAPI_list_free(QosDecisionList); + + ogs_ims_data_free(&ims_data); + ogs_session_data_free(&session_data); + + return true; + +cleanup: + ogs_assert(status); + ogs_assert(strerror); + ogs_error("%s", strerror); + ogs_assert(true == + ogs_sbi_server_send_error(stream, status, recvmsg, strerror, NULL)); + ogs_free(strerror); + + OpenAPI_list_for_each(PccRuleList, node) { + PccRuleMap = node->data; + if (PccRuleMap) { + PccRule = PccRuleMap->value; + if (PccRule) + ogs_sbi_free_pcc_rule(PccRule); + ogs_free(PccRuleMap); + } + } + OpenAPI_list_free(PccRuleList); + + OpenAPI_list_for_each(QosDecisionList, node) { + QosDecisionMap = node->data; + if (QosDecisionMap) { + QosData = QosDecisionMap->value; + if (QosData) + ogs_sbi_free_qos_data(QosData); + ogs_free(QosDecisionMap); + } + } + OpenAPI_list_free(QosDecisionList); + + ogs_ims_data_free(&ims_data); + ogs_session_data_free(&session_data); + + return false; +} + +bool pcf_npcf_policyauthorization_handle_delete( + pcf_sess_t *sess, pcf_app_t *app_session, + ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg) +{ + int i; + + OpenAPI_sm_policy_decision_t SmPolicyDecision; + + OpenAPI_list_t *PccRuleList = NULL; + OpenAPI_map_t *PccRuleMap = NULL; + + OpenAPI_list_t *QosDecisionList = NULL; + OpenAPI_map_t *QosDecisionMap = NULL; + + OpenAPI_lnode_t *node = NULL; + + ogs_assert(true == ogs_sbi_send_http_status_no_content(stream)); + + ogs_assert(app_session); + + memset(&SmPolicyDecision, 0, sizeof(SmPolicyDecision)); + + PccRuleList = OpenAPI_list_create(); + ogs_assert(PccRuleList); + + QosDecisionList = OpenAPI_list_create(); + ogs_assert(QosDecisionList); + + for (i = 0; i < app_session->num_of_pcc_rule; i++) { + ogs_pcc_rule_t *pcc_rule = &app_session->pcc_rule[i]; + + ogs_assert(pcc_rule); + + PccRuleMap = OpenAPI_map_create(pcc_rule->id, NULL); + ogs_assert(PccRuleMap); + + OpenAPI_list_add(PccRuleList, PccRuleMap); + + QosDecisionMap = OpenAPI_map_create(pcc_rule->id, NULL); + ogs_assert(QosDecisionMap); + + OpenAPI_list_add(QosDecisionList, QosDecisionMap); + } + + if (PccRuleList->count) + SmPolicyDecision.pcc_rules = PccRuleList; + + if (QosDecisionList->count) + SmPolicyDecision.qos_decs = QosDecisionList; + + if (PccRuleList->count || QosDecisionList->count) { + ogs_assert(true == pcf_sbi_send_smpolicycontrol_delete_notify( + sess, app_session, &SmPolicyDecision)); + } else { + pcf_app_remove(app_session); + } + + OpenAPI_list_for_each(PccRuleList, node) { + PccRuleMap = node->data; + if (PccRuleMap) { + ogs_free(PccRuleMap); + } + } + OpenAPI_list_free(PccRuleList); + + OpenAPI_list_for_each(QosDecisionList, node) { + QosDecisionMap = node->data; + if (QosDecisionMap) { + ogs_free(QosDecisionMap); + } + } + OpenAPI_list_free(QosDecisionList); + + return true; +} diff --git a/src/pcf/npcf-handler.h b/src/pcf/npcf-handler.h index ab5db4955..de750ea67 100644 --- a/src/pcf/npcf-handler.h +++ b/src/pcf/npcf-handler.h @@ -29,13 +29,19 @@ extern "C" { bool pcf_npcf_am_policy_contrtol_handle_create(pcf_ue_t *pcf_ue, ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg); -bool pcf_npcf_smpolicycontrtol_handle_create(pcf_sess_t *sess, +bool pcf_npcf_smpolicycontrol_handle_create(pcf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg); -bool pcf_npcf_smpolicycontrtol_handle_delete(pcf_sess_t *sess, +bool pcf_npcf_smpolicycontrol_handle_delete(pcf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg); bool pcf_npcf_policyauthorization_handle_create(pcf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg); +bool pcf_npcf_policyauthorization_handle_update( + pcf_sess_t *sess, pcf_app_t *app, + ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg); +bool pcf_npcf_policyauthorization_handle_delete( + pcf_sess_t *sess, pcf_app_t *app, + ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg); #ifdef __cplusplus } diff --git a/src/pcf/nsmf-build.c b/src/pcf/nsmf-build.c index ac105a43b..67d1c1391 100644 --- a/src/pcf/nsmf-build.c +++ b/src/pcf/nsmf-build.c @@ -19,27 +19,86 @@ #include "nsmf-build.h" -ogs_sbi_request_t *pcf_nsmf_callback_build_smpolicycontrol( +ogs_sbi_request_t *pcf_nsmf_callback_build_smpolicycontrol_update( pcf_sess_t *sess, void *data) { ogs_sbi_message_t message; + ogs_sbi_header_t header; ogs_sbi_request_t *request = NULL; + ogs_sbi_server_t *server = NULL; OpenAPI_sm_policy_notification_t SmPolicyNotification; + OpenAPI_sm_policy_decision_t *SmPolicyDecision; ogs_assert(sess); + ogs_assert(sess->sm_policy_id); ogs_assert(sess->notification_uri); + server = ogs_list_first(&ogs_sbi_self()->server_list); + ogs_assert(server); + + memset(&header, 0, sizeof(header)); + header.service.name = (char *)OGS_SBI_SERVICE_NAME_NPCF_SMPOLICYCONTROL; + header.api.version = (char *)OGS_SBI_API_V1; + header.resource.component[0] = (char *)OGS_SBI_RESOURCE_NAME_SM_POLICIES; + header.resource.component[1] = sess->sm_policy_id; + header.resource.component[2] = (char *)OGS_SBI_RESOURCE_NAME_UPDATE; + memset(&SmPolicyNotification, 0, sizeof(SmPolicyNotification)); + SmPolicyNotification.resource_uri = ogs_sbi_server_uri(server, &header); + ogs_assert(SmPolicyNotification.resource_uri); + + SmPolicyDecision = data; + ogs_assert(SmPolicyDecision); + + SmPolicyNotification.sm_policy_decision = SmPolicyDecision; + memset(&message, 0, sizeof(message)); message.h.method = (char *)OGS_SBI_HTTP_METHOD_POST; - message.h.uri = sess->notification_uri; + message.h.uri = ogs_mstrcatf( + sess->notification_uri, "/%s", OGS_SBI_RESOURCE_NAME_UPDATE); + ogs_assert(message.h.uri); message.SmPolicyNotification = &SmPolicyNotification; request = ogs_sbi_build_request(&message); ogs_assert(request); + ogs_free(SmPolicyNotification.resource_uri); + ogs_free(message.h.uri); + + return request; +} + +ogs_sbi_request_t *pcf_nsmf_callback_build_smpolicycontrol_terminate( + pcf_sess_t *sess, void *data) +{ + ogs_sbi_message_t message; + ogs_sbi_header_t header; + ogs_sbi_request_t *request = NULL; + + ogs_assert(sess); + ogs_assert(sess->sm_policy_id); + ogs_assert(sess->notification_uri); + + memset(&header, 0, sizeof(header)); + header.service.name = (char *)OGS_SBI_SERVICE_NAME_NPCF_SMPOLICYCONTROL; + header.api.version = (char *)OGS_SBI_API_V1; + header.resource.component[0] = (char *)OGS_SBI_RESOURCE_NAME_SM_POLICIES; + header.resource.component[1] = sess->sm_policy_id; + header.resource.component[2] = (char *)OGS_SBI_RESOURCE_NAME_UPDATE; + + memset(&message, 0, sizeof(message)); + message.h.method = (char *)OGS_SBI_HTTP_METHOD_POST; + message.h.uri = ogs_mstrcatf( + sess->notification_uri, "/%s", OGS_SBI_RESOURCE_NAME_TERMINATE); + ogs_assert(message.h.uri); + + request = ogs_sbi_build_request(&message); + ogs_assert(request); + + ogs_free(message.h.uri); + return request; } diff --git a/src/pcf/nsmf-build.h b/src/pcf/nsmf-build.h index a40e96cbc..0ccbe418c 100644 --- a/src/pcf/nsmf-build.h +++ b/src/pcf/nsmf-build.h @@ -26,7 +26,9 @@ extern "C" { #endif -ogs_sbi_request_t *pcf_nsmf_callback_build_smpolicycontrol( +ogs_sbi_request_t *pcf_nsmf_callback_build_smpolicycontrol_update( + pcf_sess_t *sess, void *data); +ogs_sbi_request_t *pcf_nsmf_callback_build_smpolicycontrol_terminate( pcf_sess_t *sess, void *data); #ifdef __cplusplus diff --git a/src/pcf/pcf-sm.c b/src/pcf/pcf-sm.c index 78600903b..7ce9e4bf1 100644 --- a/src/pcf/pcf-sm.c +++ b/src/pcf/pcf-sm.c @@ -53,6 +53,7 @@ void pcf_state_operational(ogs_fsm_t *s, pcf_event_t *e) pcf_ue_t *pcf_ue = NULL; pcf_sess_t *sess = NULL; + pcf_app_t *app_session = NULL; pcf_sm_debug(e); @@ -231,8 +232,10 @@ void pcf_state_operational(ogs_fsm_t *s, pcf_event_t *e) AppSessionContext->asc_req_data->ue_ipv6); } } else { - sess = pcf_sess_find_by_app_session_id( + app_session = pcf_app_find_by_app_session_id( message.h.resource.component[1]); + if (app_session) + sess = app_session->sess; } break; @@ -251,6 +254,7 @@ void pcf_state_operational(ogs_fsm_t *s, pcf_event_t *e) ogs_assert(OGS_FSM_STATE(&sess->sm)); e->sess = sess; + e->app = app_session; e->sbi.message = &message; ogs_fsm_dispatch(&sess->sm, e); if (OGS_FSM_CHECK(&sess->sm, pcf_sm_state_exception)) { diff --git a/src/pcf/sbi-path.c b/src/pcf/sbi-path.c index d42c517c7..4abd4b8b8 100644 --- a/src/pcf/sbi-path.c +++ b/src/pcf/sbi-path.c @@ -240,6 +240,18 @@ static int client_notify_cb(ogs_sbi_response_t *response, void *data) return OGS_OK; } +static int client_delete_notify_cb(ogs_sbi_response_t *response, void *data) +{ + pcf_app_t *app_session = data; + + ogs_assert(app_session); + client_notify_cb(response, data); + + pcf_app_remove(app_session); + + return OGS_OK; +} + bool pcf_sbi_send_am_policy_control_notify(pcf_ue_t *pcf_ue) { ogs_sbi_request_t *request = NULL; @@ -254,7 +266,8 @@ bool pcf_sbi_send_am_policy_control_notify(pcf_ue_t *pcf_ue) return ogs_sbi_client_send_request(client, client_notify_cb, request, NULL); } -bool pcf_sbi_send_smpolicycontrol_notify(pcf_sess_t *sess) +bool pcf_sbi_send_smpolicycontrol_update_notify( + pcf_sess_t *sess, OpenAPI_sm_policy_decision_t *SmPolicyDecision) { ogs_sbi_request_t *request = NULL; ogs_sbi_client_t *client = NULL; @@ -263,7 +276,54 @@ bool pcf_sbi_send_smpolicycontrol_notify(pcf_sess_t *sess) client = sess->nsmf.client; ogs_assert(client); - request = pcf_nsmf_callback_build_smpolicycontrol(sess, NULL); + request = pcf_nsmf_callback_build_smpolicycontrol_update( + sess, SmPolicyDecision); + ogs_expect_or_return_val(request, false); + return ogs_sbi_client_send_request(client, client_notify_cb, request, NULL); +} + +bool pcf_sbi_send_smpolicycontrol_delete_notify( + pcf_sess_t *sess, pcf_app_t *app_session, + OpenAPI_sm_policy_decision_t *SmPolicyDecision) +{ + ogs_sbi_request_t *request = NULL; + ogs_sbi_client_t *client = NULL; + + ogs_assert(sess); + client = sess->nsmf.client; + ogs_assert(client); + + request = pcf_nsmf_callback_build_smpolicycontrol_update( + sess, SmPolicyDecision); + ogs_expect_or_return_val(request, false); + return ogs_sbi_client_send_request( + client, client_delete_notify_cb, request, app_session); +} + +bool pcf_sbi_send_smpolicycontrol_terminate_notify(pcf_sess_t *sess) +{ + ogs_sbi_request_t *request = NULL; + ogs_sbi_client_t *client = NULL; + + ogs_assert(sess); + client = sess->nsmf.client; + ogs_assert(client); + + request = pcf_nsmf_callback_build_smpolicycontrol_terminate(sess, NULL); + ogs_expect_or_return_val(request, false); + return ogs_sbi_client_send_request(client, client_notify_cb, request, NULL); +} + +bool pcf_sbi_send_policyauthorization_terminate_notify(pcf_app_t *app) +{ + ogs_sbi_request_t *request = NULL; + ogs_sbi_client_t *client = NULL; + + ogs_assert(app); + client = app->naf.client; + ogs_assert(client); + + request = pcf_naf_callback_build_policyauthorization_terminate(app, NULL); ogs_expect_or_return_val(request, false); return ogs_sbi_client_send_request(client, client_notify_cb, request, NULL); } diff --git a/src/pcf/sbi-path.h b/src/pcf/sbi-path.h index fdd46f0ee..7004e290e 100644 --- a/src/pcf/sbi-path.h +++ b/src/pcf/sbi-path.h @@ -25,6 +25,7 @@ #include "nbsf-build.h" #include "namf-build.h" #include "nsmf-build.h" +#include "naf-build.h" #ifdef __cplusplus extern "C" { @@ -44,7 +45,14 @@ bool pcf_sess_sbi_discover_and_send(OpenAPI_nf_type_e target_nf_type, ogs_sbi_request_t *(*build)(pcf_sess_t *sess, void *data)); bool pcf_sbi_send_am_policy_control_notify(pcf_ue_t *pcf_ue); -bool pcf_sbi_send_smpolicycontrol_notify(pcf_sess_t *sess); +bool pcf_sbi_send_smpolicycontrol_update_notify( + pcf_sess_t *sess, OpenAPI_sm_policy_decision_t *SmPolicyDecision); +bool pcf_sbi_send_smpolicycontrol_delete_notify( + pcf_sess_t *sess, pcf_app_t *app_session, + OpenAPI_sm_policy_decision_t *SmPolicyDecision); +bool pcf_sbi_send_smpolicycontrol_terminate_notify(pcf_sess_t *sess); + +bool pcf_sbi_send_policyauthorization_terminate_notify(pcf_app_t *app); #ifdef __cplusplus } diff --git a/src/pcf/sm-sm.c b/src/pcf/sm-sm.c index 32f988bd0..8715dfca1 100644 --- a/src/pcf/sm-sm.c +++ b/src/pcf/sm-sm.c @@ -70,22 +70,22 @@ void pcf_sm_state_operational(ogs_fsm_t *s, pcf_event_t *e) SWITCH(message->h.service.name) CASE(OGS_SBI_SERVICE_NAME_NPCF_SMPOLICYCONTROL) if (!message->h.resource.component[1]) { - handled = pcf_npcf_smpolicycontrtol_handle_create( + handled = pcf_npcf_smpolicycontrol_handle_create( sess, stream, message); if (!handled) { ogs_error("[%s:%d] " - "pcf_npcf_smpolicycontrtol_handle_create() failed", + "pcf_npcf_smpolicycontrol_handle_create() failed", pcf_ue->supi, sess->psi); OGS_FSM_TRAN(s, pcf_sm_state_exception); } } else { SWITCH(message->h.resource.component[2]) CASE(OGS_SBI_RESOURCE_NAME_DELETE) - handled = pcf_npcf_smpolicycontrtol_handle_delete( + handled = pcf_npcf_smpolicycontrol_handle_delete( sess, stream, message); if (!handled) { ogs_error("[%s:%d] " - "pcf_npcf_smpolicycontrtol_handle_delete() failed", + "pcf_npcf_smpolicycontrol_handle_delete() failed", pcf_ue->supi, sess->psi); OGS_FSM_TRAN(s, pcf_sm_state_exception); } @@ -103,17 +103,46 @@ void pcf_sm_state_operational(ogs_fsm_t *s, pcf_event_t *e) break; CASE(OGS_SBI_SERVICE_NAME_NPCF_POLICYAUTHORIZATION) - if (!message->h.resource.component[1]) { - handled = pcf_npcf_policyauthorization_handle_create( - sess, stream, message); + if (message->h.resource.component[1]) { + if (message->h.resource.component[2]) { + SWITCH(message->h.resource.component[2]) + CASE(OGS_SBI_RESOURCE_NAME_DELETE) + handled = pcf_npcf_policyauthorization_handle_delete( + sess, e->app, stream, message); + break; + DEFAULT + ogs_error("[%s:%d] Invalid resource name [%s]", + pcf_ue->supi, sess->psi, + message->h.resource.component[2]); + ogs_assert(true == + ogs_sbi_server_send_error(stream, + OGS_SBI_HTTP_STATUS_FORBIDDEN, message, + "Invalid resource name", message->h.uri)); + END + } else { + SWITCH(message->h.method) + CASE(OGS_SBI_HTTP_METHOD_PATCH) + handled = pcf_npcf_policyauthorization_handle_update( + sess, e->app, stream, message); + break; + DEFAULT + ogs_error("[%s:%d] Unknown method [%s]", + pcf_ue->supi, sess->psi, message->h.method); + ogs_assert(true == + ogs_sbi_server_send_error(stream, + OGS_SBI_HTTP_STATUS_FORBIDDEN, message, + "Invalid HTTP method", message->h.uri)); + END + } } else { - SWITCH(message->h.resource.component[2]) - CASE(OGS_SBI_RESOURCE_NAME_DELETE) - ogs_fatal("TODO"); + SWITCH(message->h.method) + CASE(OGS_SBI_HTTP_METHOD_POST) + handled = pcf_npcf_policyauthorization_handle_create( + sess, stream, message); break; DEFAULT - ogs_error("[%s:%d] Invalid HTTP URI [%s]", - pcf_ue->supi, sess->psi, message->h.uri); + ogs_error("[%s:%d] Unknown method [%s]", + pcf_ue->supi, sess->psi, message->h.method); ogs_assert(true == ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_FORBIDDEN, message, diff --git a/src/pcrf/pcrf-gx-path.c b/src/pcrf/pcrf-gx-path.c index 1d35470a8..16c8e0ce0 100644 --- a/src/pcrf/pcrf-gx-path.c +++ b/src/pcrf/pcrf-gx-path.c @@ -62,12 +62,6 @@ static void pcrf_gx_raa_cb(void *data, struct msg **msg); static int encode_pcc_rule_definition( struct avp *avp, ogs_pcc_rule_t *pcc_rule, int flow_presence); -static int matched_flow(ogs_pcc_rule_t *pcc_rule, - ogs_media_component_t *media_component); -static int install_flow(ogs_pcc_rule_t *pcc_rule, - ogs_media_component_t *media_component); -static int update_qos(ogs_pcc_rule_t *pcc_rule, - ogs_media_component_t *media_component); static __inline__ struct sess_state *new_state(os0_t sid) { @@ -654,7 +648,6 @@ int pcrf_gx_send_rar( { int rv; int ret = 0, i, j; - int count = 0; struct msg *req = NULL; struct avp *avp, *avpch1; @@ -749,10 +742,6 @@ int pcrf_gx_send_rar( ogs_media_component_t *media_component = &rx_message->ims_data.media_component[i]; - if (media_component->media_component_number == 0) { - continue; - } - switch(media_component->media_type) { case OGS_DIAM_RX_MEDIA_TYPE_AUDIO: qos_index = OGS_QOS_INDEX_1; @@ -832,7 +821,8 @@ int pcrf_gx_send_rar( /* Install Flow */ flow_presence = 1; - rv = install_flow(pcc_rule, media_component); + rv = ogs_pcc_rule_install_flow_from_media( + pcc_rule, media_component); if (rv != OGS_OK) { rx_message->result_code = OGS_DIAM_RX_DIAMETER_FILTER_RESTRICTIONS; @@ -842,8 +832,11 @@ int pcrf_gx_send_rar( rx_sess_data->num_of_pcc_rule++; } else { + int count = 0; + /* Check Flow */ - count = matched_flow(pcc_rule, media_component); + count = ogs_pcc_rule_num_of_flow_equal_to_media( + pcc_rule, media_component); if (count == -1) { rx_message->result_code = OGS_DIAM_RX_DIAMETER_FILTER_RESTRICTIONS; @@ -854,7 +847,8 @@ int pcrf_gx_send_rar( if (pcc_rule->num_of_flow != count) { /* Re-install Flow */ flow_presence = 1; - rv = install_flow(pcc_rule, media_component); + rv = ogs_pcc_rule_install_flow_from_media( + pcc_rule, media_component); if (rv != OGS_OK) { rx_message->result_code = OGS_DIAM_RX_DIAMETER_FILTER_RESTRICTIONS; @@ -865,7 +859,7 @@ int pcrf_gx_send_rar( } /* Update QoS */ - rv = update_qos(pcc_rule, media_component); + rv = ogs_pcc_rule_update_qos_from_media(pcc_rule, media_component); if (rv != OGS_OK) { rx_message->result_code = OGS_DIAM_RX_DIAMETER_REQUESTED_SERVICE_NOT_AUTHORIZED; @@ -1361,295 +1355,3 @@ static int encode_pcc_rule_definition( return OGS_OK; } - -static int flow_rx_to_gx(ogs_flow_t *rx_flow, ogs_flow_t *gx_flow) -{ - int len; - char *from_str, *to_str; - - ogs_assert(rx_flow); - ogs_assert(gx_flow); - - if (!strncmp(rx_flow->description, - "permit out", strlen("permit out"))) { - gx_flow->direction = OGS_FLOW_DOWNLINK_ONLY; - gx_flow->description = ogs_strdup(rx_flow->description); - ogs_assert(gx_flow->description); - - } else if (!strncmp(rx_flow->description, - "permit in", strlen("permit in"))) { - gx_flow->direction = OGS_FLOW_UPLINK_ONLY; - - /* 'permit in' should be changed - * 'permit out' in Gx Diameter */ - len = strlen(rx_flow->description)+2; - gx_flow->description = ogs_malloc(len); - ogs_assert(gx_flow->description); - strcpy(gx_flow->description, "permit out"); - from_str = strstr(&rx_flow->description[strlen("permit in")], "from"); - ogs_assert(from_str); - to_str = strstr(&rx_flow->description[strlen("permit in")], "to"); - ogs_assert(to_str); - strncat(gx_flow->description, - &rx_flow->description[strlen("permit in")], - strlen(rx_flow->description) - - strlen("permit in") - strlen(from_str)); - strcat(gx_flow->description, "from"); - strcat(gx_flow->description, &to_str[strlen("to")]); - strcat(gx_flow->description, " to"); - strncat(gx_flow->description, &from_str[strlen("from")], - strlen(from_str) - strlen(to_str) - strlen("from") - 1); - ogs_assert(len == strlen(gx_flow->description)+1); - } else { - ogs_error("Invalid Flow Descripton : [%s]", rx_flow->description); - return OGS_ERROR; - } - - return OGS_OK; -} - -static int matched_flow(ogs_pcc_rule_t *pcc_rule, - ogs_media_component_t *media_component) -{ - int rv; - int i, j, k; - int matched = 0; - int new = 0; - - ogs_assert(pcc_rule); - ogs_assert(media_component); - - for (i = 0; i < media_component->num_of_sub; i++) { - ogs_media_sub_component_t *sub = &media_component->sub[i]; - - if (sub->flow_number == 0) { - continue; - } - - for (j = 0; j < sub->num_of_flow; j++) { - new++; - } - } - - if (new == 0) { - /* No new flow in Media-Component */ - return pcc_rule->num_of_flow; - } - - for (i = 0; i < media_component->num_of_sub; i++) { - ogs_media_sub_component_t *sub = &media_component->sub[i]; - - if (sub->flow_number == 0) { - continue; - } - - for (j = 0; j < sub->num_of_flow && - j < OGS_MAX_NUM_OF_FLOW_IN_MEDIA_SUB_COMPONENT; j++) { - ogs_flow_t gx_flow; - ogs_flow_t *rx_flow = &sub->flow[j]; - - rv = flow_rx_to_gx(rx_flow, &gx_flow); - if (rv != OGS_OK) { - ogs_error("flow reformatting error"); - return OGS_ERROR; - } - - for (k = 0; k < pcc_rule->num_of_flow; k++) { - if (gx_flow.direction == pcc_rule->flow[k].direction && - !strcmp(gx_flow.description, - pcc_rule->flow[k].description)) { - matched++; - break; - } - } - - OGS_FLOW_FREE(&gx_flow); - } - } - - return matched; -} - -static int install_flow(ogs_pcc_rule_t *pcc_rule, - ogs_media_component_t *media_component) -{ - int rv; - int i, j; - - ogs_assert(pcc_rule); - ogs_assert(media_component); - - /* Remove Flow from PCC Rule */ - for (i = 0; i < pcc_rule->num_of_flow; i++) { - OGS_FLOW_FREE(&pcc_rule->flow[i]); - } - pcc_rule->num_of_flow = 0; - - for (i = 0; i < media_component->num_of_sub; i++) { - ogs_media_sub_component_t *sub = &media_component->sub[i]; - - if (sub->flow_number == 0) { - continue; - } - - /* Copy Flow to PCC Rule */ - for (j = 0; j < sub->num_of_flow && - j < OGS_MAX_NUM_OF_FLOW_IN_MEDIA_SUB_COMPONENT; j++) { - ogs_flow_t *rx_flow = NULL; - ogs_flow_t *gx_flow = NULL; - - if (pcc_rule->num_of_flow < OGS_MAX_NUM_OF_FLOW_IN_PCC_RULE) { - rx_flow = &sub->flow[j]; - gx_flow = &pcc_rule->flow[pcc_rule->num_of_flow]; - - rv = flow_rx_to_gx(rx_flow, gx_flow); - if (rv != OGS_OK) { - ogs_error("flow reformatting error"); - return OGS_ERROR; - } - - pcc_rule->num_of_flow++; - } else { - ogs_error("Overflow: Number of Flow"); - return OGS_ERROR; - } - } - } - - return OGS_OK; -} - -static int update_qos(ogs_pcc_rule_t *pcc_rule, - ogs_media_component_t *media_component) -{ - int rv; - int i, j; - - ogs_assert(pcc_rule); - ogs_assert(media_component); - - pcc_rule->qos.mbr.downlink = 0; - pcc_rule->qos.mbr.uplink = 0; - pcc_rule->qos.gbr.downlink = 0; - pcc_rule->qos.gbr.uplink = 0; - - for (i = 0; i < media_component->num_of_sub; i++) { - ogs_media_sub_component_t *sub = &media_component->sub[i]; - - if (sub->flow_number == 0) { - continue; - } - - for (j = 0; j < sub->num_of_flow && - j < OGS_MAX_NUM_OF_FLOW_IN_MEDIA_SUB_COMPONENT; j++) { - ogs_flow_t gx_flow; - ogs_flow_t *rx_flow = &sub->flow[j]; - - rv = flow_rx_to_gx(rx_flow, &gx_flow); - if (rv != OGS_OK) { - ogs_error("flow reformatting error"); - return OGS_ERROR; - } - - if (gx_flow.direction == OGS_FLOW_DOWNLINK_ONLY) { - if (sub->flow_usage == OGS_DIAM_RX_FLOW_USAGE_RTCP) { - if (media_component->rr_bandwidth && - media_component->rs_bandwidth) { - pcc_rule->qos.mbr.downlink += - (media_component->rr_bandwidth + - media_component->rs_bandwidth); - } else if (media_component->max_requested_bandwidth_dl) { - if (media_component->rr_bandwidth && - !media_component->rs_bandwidth) { - pcc_rule->qos.mbr.downlink += - ogs_max(0.05 * - media_component->max_requested_bandwidth_dl, - media_component->rr_bandwidth); - } - if (!media_component->rr_bandwidth && - media_component->rs_bandwidth) { - pcc_rule->qos.mbr.downlink += - ogs_max(0.05 * - media_component->max_requested_bandwidth_dl, - media_component->rs_bandwidth); - } - if (!media_component->rr_bandwidth && - !media_component->rs_bandwidth) { - pcc_rule->qos.mbr.downlink += - 0.05 * - media_component->max_requested_bandwidth_dl; - } - } - } else { - if (gx_flow.description) { - pcc_rule->qos.mbr.downlink += - media_component->max_requested_bandwidth_dl; - pcc_rule->qos.gbr.downlink += - media_component->min_requested_bandwidth_dl; - } - } - } else if (gx_flow.direction == OGS_FLOW_UPLINK_ONLY) { - if (sub->flow_usage == OGS_DIAM_RX_FLOW_USAGE_RTCP) { - if (media_component->rr_bandwidth && - media_component->rs_bandwidth) { - pcc_rule->qos.mbr.uplink += - (media_component->rr_bandwidth + - media_component->rs_bandwidth); - } else if (media_component->max_requested_bandwidth_ul) { - if (media_component->rr_bandwidth && - !media_component->rs_bandwidth) { - pcc_rule->qos.mbr.uplink += - ogs_max(0.05 * - media_component->max_requested_bandwidth_ul, - media_component->rr_bandwidth); - } - if (!media_component->rr_bandwidth && - media_component->rs_bandwidth) { - pcc_rule->qos.mbr.uplink += - ogs_max(0.05 * - media_component->max_requested_bandwidth_ul, - media_component->rs_bandwidth); - } - if (!media_component->rr_bandwidth && - !media_component->rs_bandwidth) { - pcc_rule->qos.mbr.uplink += - 0.05 * - media_component->max_requested_bandwidth_ul; - } - } - } else { - if (gx_flow.description) { - pcc_rule->qos.mbr.uplink += - media_component->max_requested_bandwidth_ul; - pcc_rule->qos.gbr.uplink += - media_component->min_requested_bandwidth_ul; - } - } - } else - ogs_assert_if_reached(); - - OGS_FLOW_FREE(&gx_flow); - } - } - - if (pcc_rule->qos.mbr.downlink == 0) { - pcc_rule->qos.mbr.downlink += - media_component->max_requested_bandwidth_dl; - pcc_rule->qos.mbr.downlink += - (media_component->rr_bandwidth + media_component->rs_bandwidth); - } - - if (pcc_rule->qos.mbr.uplink == 0) { - pcc_rule->qos.mbr.uplink += - media_component->max_requested_bandwidth_ul; - pcc_rule->qos.mbr.uplink += - (media_component->rr_bandwidth + media_component->rs_bandwidth); - } - - if (pcc_rule->qos.gbr.downlink == 0) - pcc_rule->qos.gbr.downlink = pcc_rule->qos.mbr.downlink; - if (pcc_rule->qos.gbr.uplink == 0) - pcc_rule->qos.gbr.uplink = pcc_rule->qos.mbr.uplink; - - return OGS_OK; -} diff --git a/src/pcrf/pcrf-rx-path.c b/src/pcrf/pcrf-rx-path.c index 89eaae983..cc87a9ffe 100644 --- a/src/pcrf/pcrf-rx-path.c +++ b/src/pcrf/pcrf-rx-path.c @@ -273,12 +273,23 @@ static int pcrf_rx_aar_cb( struct msg **msg, struct avp *avp, ogs_assert(ret == 0); switch (hdr->avp_code) { case OGS_DIAM_RX_AVP_CODE_FLOW_NUMBER: - sub->flow_number = - hdr->avp_value->i32; + sub->flow_number = hdr->avp_value->i32; break; case OGS_DIAM_RX_AVP_CODE_FLOW_USAGE: - sub->flow_usage = - hdr->avp_value->i32; + switch (hdr->avp_value->i32) { + case OGS_DIAM_RX_FLOW_USAGE_NO_INFORMATION: + sub->flow_usage = OGS_FLOW_USAGE_NO_INFO; + break; + case OGS_DIAM_RX_FLOW_USAGE_RTCP: + sub->flow_usage = OGS_FLOW_USAGE_RTCP; + break; + case OGS_DIAM_RX_FLOW_USAGE_AF_SIGNALLING: + sub->flow_usage = OGS_FLOW_USAGE_AF_SIGNALLING; + break; + default: + ogs_error("Invalid flow usage = %d", + hdr->avp_value->i32); + } break; case OGS_DIAM_RX_AVP_CODE_FLOW_DESCRIPTION: ogs_assert(sub->num_of_flow < diff --git a/src/smf/binding.c b/src/smf/binding.c index db3a540c0..03fc64856 100644 --- a/src/smf/binding.c +++ b/src/smf/binding.c @@ -115,15 +115,12 @@ void smf_bearer_binding(smf_sess_t *sess) ogs_assert(sess); - for (i = 0; i < sess->num_of_pcc_rule; i++) { + for (i = 0; i < sess->policy.num_of_pcc_rule; i++) { ogs_gtp_xact_t *xact = NULL; ogs_gtp_header_t h; ogs_pkbuf_t *pkbuf = NULL; smf_bearer_t *bearer = NULL; - - ogs_pcc_rule_t *pcc_rule = &sess->pcc_rule[i]; - int bearer_created = 0; - int qos_presence = 0; + ogs_pcc_rule_t *pcc_rule = &sess->policy.pcc_rule[i]; ogs_assert(pcc_rule); if (pcc_rule->name == NULL) { @@ -132,10 +129,13 @@ void smf_bearer_binding(smf_sess_t *sess) } if (pcc_rule->type == OGS_PCC_RULE_TYPE_INSTALL) { - ogs_pfcp_pdr_t *dl_pdr = NULL, *ul_pdr = NULL; + bool bearer_created = false; + bool qos_presence = false; bearer = smf_bearer_find_by_pcc_rule_name(sess, pcc_rule->name); if (!bearer) { + ogs_pfcp_pdr_t *dl_pdr = NULL, *ul_pdr = NULL; + if (pcc_rule->num_of_flow == 0) { /* TFT is mandatory in * activate dedicated EPS bearer context request */ @@ -210,7 +210,7 @@ void smf_bearer_binding(smf_sess_t *sess) memcpy(&bearer->qos, &pcc_rule->qos, sizeof(ogs_qos_t)); - bearer_created = 1; + bearer_created = true; } else { ogs_assert(strcmp(bearer->pcc_rule.name, pcc_rule->name) == 0); @@ -227,55 +227,46 @@ void smf_bearer_binding(smf_sess_t *sess) memcpy(&bearer->qos, &pcc_rule->qos, sizeof(ogs_qos_t)); /* Update Bearer Request encodes updated QoS parameter */ - qos_presence = 1; - } - - if (pcc_rule->num_of_flow == 0 && qos_presence == 0) { - ogs_warn("No need to send 'Update Bearer Request'"); - ogs_warn(" - Both QoS and TFT are same as before"); - continue; + qos_presence = true; } } - dl_pdr = bearer->dl_pdr; - ogs_assert(dl_pdr); - ul_pdr = bearer->ul_pdr; - ogs_assert(ul_pdr); - - dl_pdr->num_of_flow = 0; - ul_pdr->num_of_flow = 0; - + /* + * We only use the method of adding a flow to an existing tft. + * + * EPC: OGS_GTP_TFT_CODE_ADD_PACKET_FILTERS_TO_EXISTING_TFT + * 5GC: OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_ADD_PACKET_FILTERS + */ ogs_list_init(&bearer->pf_to_add_list); for (j = 0; j < pcc_rule->num_of_flow; j++) { - ogs_flow_t *flow = &pcc_rule->flow[j]; smf_pf_t *pf = NULL; + ogs_flow_t *flow = &pcc_rule->flow[j]; ogs_expect_or_return(flow); ogs_expect_or_return(flow->description); + /* + * To add a flow to an existing tft. + * duplicated flows are not added + */ if (smf_pf_find_by_flow( bearer, flow->direction, flow->description) != NULL) { continue; } - if (flow->direction == OGS_FLOW_DOWNLINK_ONLY) { - dl_pdr->flow_description[dl_pdr->num_of_flow++] = - flow->description; - } else if (flow->direction == OGS_FLOW_UPLINK_ONLY) { - ul_pdr->flow_description[ul_pdr->num_of_flow++] = - flow->description; - } else { - ogs_error("Flow Bidirectional is not supported[%d]", - flow->direction); - } - + /* + * To add a flow to an existing tft. + * + * Only new flows are added to the PF list. + * Then, in the PF list, there are all flows + * from the beginning to the present. + */ pf = smf_pf_add(bearer); if (!pf) { ogs_error("Overflow: PacketFilter in Bearer"); break; } - ogs_assert(pf); pf->direction = flow->direction; pf->flow_description = ogs_strdup(flow->description); @@ -307,45 +298,37 @@ void smf_bearer_binding(smf_sess_t *sess) break; } + /* + * To add a flow to an existing tft. + * + * 'pf_to_add_list' now has the added flow. + */ ogs_list_add(&bearer->pf_to_add_list, &pf->to_add_node); } - if (bearer_created == 1) { - /* Setup QER */ - if (bearer->qos.mbr.downlink || bearer->qos.mbr.uplink || - bearer->qos.gbr.downlink || bearer->qos.gbr.uplink) { - ogs_pfcp_qer_t *qer = NULL; + if (bearer_created == false && + qos_presence == false && + ogs_list_count(&bearer->pf_to_add_list) == 0) { + ogs_error("No need to send 'Update Bearer Request'"); + ogs_error("bearer_created:%d, qos_presence:%d, rule_count:%d", + bearer_created, qos_presence, + ogs_list_count(&bearer->pf_to_add_list)); + continue; + } - /* Only 1 QER is used per bearer */ - qer = bearer->qer; - if (!qer) { - qer = ogs_pfcp_qer_add(&sess->pfcp); - ogs_assert(qer); - bearer->qer = qer; - } + if (bearer_created == true) { - ogs_pfcp_pdr_associate_qer(bearer->dl_pdr, qer); - ogs_pfcp_pdr_associate_qer(bearer->ul_pdr, qer); - - qer->mbr.uplink = bearer->qos.mbr.uplink; - qer->mbr.downlink = bearer->qos.mbr.downlink; - qer->gbr.uplink = bearer->qos.gbr.uplink; - qer->gbr.downlink = bearer->qos.gbr.downlink; - } + smf_bearer_tft_update(bearer); + smf_bearer_qos_update(bearer); ogs_assert(OGS_OK == smf_epc_pfcp_send_bearer_modification_request( bearer, OGS_PFCP_MODIFY_CREATE)); - } else { ogs_gtp_tft_t tft; memset(&tft, 0, sizeof tft); - if (pcc_rule->num_of_flow) { - if (ogs_list_count(&bearer->pf_to_add_list) == 0) { - ogs_error("No need to send 'Update Bearer Request'"); - continue; - } + if (ogs_list_count(&bearer->pf_to_add_list) > 0) { encode_traffic_flow_template( &tft, bearer, OGS_GTP_TFT_CODE_ADD_PACKET_FILTERS_TO_EXISTING_TFT); @@ -358,16 +341,17 @@ void smf_bearer_binding(smf_sess_t *sess) pkbuf = smf_s5c_build_update_bearer_request( h.type, bearer, OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED, - pcc_rule->num_of_flow ? &tft : NULL, qos_presence); + (ogs_list_count(&bearer->pf_to_add_list) > 0) ? + &tft : NULL, qos_presence); ogs_expect_or_return(pkbuf); xact = ogs_gtp_xact_local_create( sess->gnode, &h, pkbuf, bearer_timeout, bearer); ogs_expect_or_return(xact); - if (pcc_rule->num_of_flow) + if (ogs_list_count(&bearer->pf_to_add_list) > 0) xact->update_flags |= OGS_GTP_MODIFY_TFT_UPDATE; - if (qos_presence) + if (qos_presence == true) xact->update_flags |= OGS_GTP_MODIFY_QOS_UPDATE; rv = ogs_gtp_xact_commit(xact); @@ -428,23 +412,16 @@ int smf_gtp_send_create_bearer_request(smf_bearer_t *bearer) return rv; } -void smf_qos_flow_binding(smf_sess_t *sess, ogs_sbi_stream_t *stream) +void smf_qos_flow_binding(smf_sess_t *sess) { int rv; int i, j; ogs_assert(sess); - for (i = 0; i < sess->num_of_pcc_rule; i++) { -#if 0 - ogs_gtp_header_t h; - ogs_pkbuf_t *pkbuf = NULL; -#endif + for (i = 0; i < sess->policy.num_of_pcc_rule; i++) { smf_bearer_t *qos_flow = NULL; - - ogs_pcc_rule_t *pcc_rule = &sess->pcc_rule[i]; - int qos_flow_created = 0; - int qos_presence = 0; + ogs_pcc_rule_t *pcc_rule = &sess->policy.pcc_rule[i]; ogs_assert(pcc_rule); if (pcc_rule->id == NULL) { @@ -453,8 +430,12 @@ void smf_qos_flow_binding(smf_sess_t *sess, ogs_sbi_stream_t *stream) } if (pcc_rule->type == OGS_PCC_RULE_TYPE_INSTALL) { + smf_pf_t *pf = NULL; ogs_pfcp_pdr_t *dl_pdr = NULL, *ul_pdr = NULL; + bool qos_flow_created = false; + bool qos_presence = false; + qos_flow = smf_qos_flow_find_by_pcc_rule_id(sess, pcc_rule->id); if (!qos_flow) { if (pcc_rule->num_of_flow == 0) { @@ -504,11 +485,9 @@ void smf_qos_flow_binding(smf_sess_t *sess, ogs_sbi_stream_t *stream) memcpy(&qos_flow->qos, &pcc_rule->qos, sizeof(ogs_qos_t)); - qos_flow_created = 1; + qos_flow_created = true; } else { - ogs_fatal("Update QoS Flow: Not implemented in 5G Core"); - ogs_assert_if_reached(); ogs_assert(strcmp(qos_flow->pcc_rule.id, pcc_rule->id) == 0); if ((pcc_rule->qos.mbr.downlink && @@ -523,51 +502,45 @@ void smf_qos_flow_binding(smf_sess_t *sess, ogs_sbi_stream_t *stream) memcpy(&qos_flow->qos, &pcc_rule->qos, sizeof(ogs_qos_t)); /* Update Bearer Request encodes updated QoS parameter */ - qos_presence = 1; - } - - if (pcc_rule->num_of_flow == 0 && qos_presence == 0) { - ogs_warn("No need to send 'Session Modification Request'"); - ogs_warn(" - Both QoS and TFT are same as before"); - continue; + qos_presence = true; } } - dl_pdr = qos_flow->dl_pdr; - ogs_assert(dl_pdr); - ul_pdr = qos_flow->ul_pdr; - ogs_assert(ul_pdr); - - dl_pdr->num_of_flow = 0; - ul_pdr->num_of_flow = 0; - + /* + * We only use the method of adding a flow to an existing tft. + * + * EPC: OGS_GTP_TFT_CODE_ADD_PACKET_FILTERS_TO_EXISTING_TFT + * 5GC: OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_ADD_PACKET_FILTERS + */ ogs_list_init(&qos_flow->pf_to_add_list); for (j = 0; j < pcc_rule->num_of_flow; j++) { ogs_flow_t *flow = &pcc_rule->flow[j]; - smf_pf_t *pf = NULL; ogs_expect_or_return(flow); ogs_expect_or_return(flow->description); + /* + * To add a flow to an existing tft. + * duplicated flows are not added + */ if (smf_pf_find_by_flow( qos_flow, flow->direction, flow->description) != NULL) { continue; } - if (flow->direction == OGS_FLOW_DOWNLINK_ONLY) { - dl_pdr->flow_description[dl_pdr->num_of_flow++] = - flow->description; - } else if (flow->direction == OGS_FLOW_UPLINK_ONLY) { - ul_pdr->flow_description[ul_pdr->num_of_flow++] = - flow->description; - } else { - ogs_error("Flow Bidirectional is not supported[%d]", - flow->direction); - } - + /* + * To add a flow to an existing tft. + * + * Only new flows are added to the PF list. + * Then, in the PF list, there are all flows + * from the beginning to the present. + */ pf = smf_pf_add(qos_flow); - ogs_assert(pf); + if (!pf) { + ogs_error("Overflow: PacketFilter in Bearer"); + break; + } pf->direction = flow->direction; pf->flow_description = ogs_strdup(flow->description); @@ -599,99 +572,67 @@ void smf_qos_flow_binding(smf_sess_t *sess, ogs_sbi_stream_t *stream) break; } + /* + * To add a flow to an existing tft. + * + * 'pf_to_add_list' now has the added flow. + */ ogs_list_add(&qos_flow->pf_to_add_list, &pf->to_add_node); } - if (qos_flow_created == 1) { - /* Setup QER */ - if (qos_flow->qos.mbr.downlink || qos_flow->qos.mbr.uplink || - qos_flow->qos.gbr.downlink || qos_flow->qos.gbr.uplink) { - ogs_pfcp_qer_t *qer = NULL; + if (qos_flow_created == false && + qos_presence == false && + ogs_list_count(&qos_flow->pf_to_add_list) == 0) { + ogs_error("No need to send 'Session Modification Request'"); + ogs_error("qos_flow_created:%d, qos_presence:%d, rule_count:%d", + qos_flow_created, qos_presence, + ogs_list_count(&qos_flow->pf_to_add_list)); + continue; + } - /* Only 1 QER is used per qos_flow */ - qer = qos_flow->qer; - if (!qer) { - qer = ogs_pfcp_qer_add(&sess->pfcp); - ogs_assert(qer); - qos_flow->qer = qer; - } + if (qos_flow_created == true) { + smf_bearer_tft_update(qos_flow); + smf_bearer_qos_update(qos_flow); - ogs_pfcp_pdr_associate_qer(qos_flow->dl_pdr, qer); - ogs_pfcp_pdr_associate_qer(qos_flow->ul_pdr, qer); + ogs_assert(OGS_OK == + smf_5gc_pfcp_send_qos_flow_modification_request( + qos_flow, NULL, + OGS_PFCP_MODIFY_NETWORK_REQUESTED| + OGS_PFCP_MODIFY_CREATE)); - qer->mbr.uplink = qos_flow->qos.mbr.uplink; - qer->mbr.downlink = qos_flow->qos.mbr.downlink; - qer->gbr.uplink = qos_flow->qos.gbr.uplink; - qer->gbr.downlink = qos_flow->qos.gbr.downlink; + } else { + uint64_t pfcp_flags = 0; + + pfcp_flags |= OGS_PFCP_MODIFY_NETWORK_REQUESTED; + + if (ogs_list_count(&qos_flow->pf_to_add_list) > 0) { + pfcp_flags |= OGS_PFCP_MODIFY_TFT_ADD; + smf_bearer_tft_update(qos_flow); + } + if (qos_presence == true) { + pfcp_flags |= OGS_PFCP_MODIFY_QOS_MODIFY; + smf_bearer_qos_update(qos_flow); } ogs_assert(OGS_OK == smf_5gc_pfcp_send_qos_flow_modification_request( - qos_flow, NULL, OGS_PFCP_MODIFY_CREATE)); - - } else { - ogs_fatal("Update Qos Flow Not Implemented"); - ogs_assert_if_reached(); -#if 0 - ogs_gtp_tft_t tft; - - memset(&tft, 0, sizeof tft); - if (pcc_rule->num_of_flow) - encode_traffic_flow_template( - &tft, qos_flow, - OGS_GTP_TFT_CODE_ADD_PACKET_FILTERS_TO_EXISTING_TFT); - - memset(&h, 0, sizeof(ogs_gtp_header_t)); - h.type = OGS_GTP_UPDATE_BEARER_REQUEST_TYPE; - h.teid = sess->sgw_s5c_teid; - - pkbuf = smf_s5c_build_update_qos_flow_request( - h.type, qos_flow, - OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED, - pcc_rule->num_of_flow ? &tft : NULL, qos_presence); - ogs_expect_or_return(pkbuf); - - xact = ogs_gtp_xact_local_create( - sess->gnode, &h, pkbuf, qos_flow_timeout, qos_flow); - ogs_expect_or_return(xact); - - if (pcc_rule->num_of_flow) - xact->update_flags |= OGS_GTP_MODIFY_TFT_UPDATE; - if (qos_presence) - xact->update_flags |= OGS_GTP_MODIFY_QOS_UPDATE; - - rv = ogs_gtp_xact_commit(xact); - ogs_expect(rv == OGS_OK); -#endif + qos_flow, NULL, pfcp_flags)); } } else if (pcc_rule->type == OGS_PCC_RULE_TYPE_REMOVE) { - ogs_fatal("Remove Type Not Implemented"); - ogs_assert_if_reached(); -#if 0 - qos_flow = smf_qos_flow_find_by_name(sess, pcc_rule->name); + qos_flow = smf_qos_flow_find_by_pcc_rule_id(sess, pcc_rule->id); if (!qos_flow) { - ogs_warn("No need to send 'Delete Bearer Request'"); - ogs_warn(" - Bearer[Name:%s] has already been removed.", - pcc_rule->name); + ogs_warn("No need to send 'Session Modification Request'"); + ogs_warn(" - QosFlow[Id:%s] has already been removed.", + pcc_rule->id); continue; } - memset(&h, 0, sizeof(ogs_gtp_header_t)); - h.type = OGS_GTP_DELETE_BEARER_REQUEST_TYPE; - h.teid = sess->sgw_s5c_teid; + ogs_assert(OGS_OK == + smf_5gc_pfcp_send_qos_flow_modification_request( + qos_flow, NULL, + OGS_PFCP_MODIFY_NETWORK_REQUESTED|OGS_PFCP_MODIFY_REMOVE)); - pkbuf = smf_s5c_build_delete_qos_flow_request(h.type, qos_flow, - OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED); - ogs_expect_or_return(pkbuf); - - xact = ogs_gtp_xact_local_create( - sess->gnode, &h, pkbuf, qos_flow_timeout, qos_flow); - ogs_expect_or_return(xact); - - rv = ogs_gtp_xact_commit(xact); - ogs_expect(rv == OGS_OK); -#endif } else { ogs_error("Invalid Type[%d]", pcc_rule->type); ogs_assert_if_reached(); diff --git a/src/smf/binding.h b/src/smf/binding.h index 45ffaab0c..eec2fd1ed 100644 --- a/src/smf/binding.h +++ b/src/smf/binding.h @@ -29,7 +29,7 @@ extern "C" { void smf_bearer_binding(smf_sess_t *sess); int smf_gtp_send_create_bearer_request(smf_bearer_t *bearer); -void smf_qos_flow_binding(smf_sess_t *sess, ogs_sbi_stream_t *stream); +void smf_qos_flow_binding(smf_sess_t *sess); #ifdef __cplusplus } diff --git a/src/smf/context.c b/src/smf/context.c index 205f577cc..0f8561a97 100644 --- a/src/smf/context.c +++ b/src/smf/context.c @@ -1423,9 +1423,9 @@ void smf_sess_remove(smf_sess_t *sess) OGS_NAS_CLEAR_DATA(&sess->nas.ue_pco); - for (i = 0; i < sess->num_of_pcc_rule; i++) - OGS_PCC_RULE_FREE(&sess->pcc_rule[i]); - sess->num_of_pcc_rule = 0; + for (i = 0; i < sess->policy.num_of_pcc_rule; i++) + OGS_PCC_RULE_FREE(&sess->policy.pcc_rule[i]); + sess->policy.num_of_pcc_rule = 0; if (sess->ipv4) { ogs_hash_set(self.ipv4_hash, sess->ipv4->addr, OGS_IPV4_LEN, NULL); @@ -1584,6 +1584,23 @@ smf_sess_t *smf_sess_find_by_paging_n1n2message_location( n1n2message_location, strlen(n1n2message_location)); } +ogs_pcc_rule_t *smf_pcc_rule_find_by_id(smf_sess_t *sess, char *pcc_rule_id) +{ + int i; + + ogs_assert(sess); + ogs_assert(pcc_rule_id); + + for (i = 0; i < sess->policy.num_of_pcc_rule; i++) { + ogs_pcc_rule_t *pcc_rule = &sess->policy.pcc_rule[i]; + if (pcc_rule->id && strcmp(pcc_rule->id, pcc_rule_id) == 0) { + return pcc_rule; + } + } + + return NULL; +} + smf_bearer_t *smf_qos_flow_add(smf_sess_t *sess) { smf_bearer_t *qos_flow = NULL; @@ -2140,6 +2157,69 @@ smf_bearer_t *smf_bearer_find_by_pdr_id( return NULL; } +void smf_bearer_tft_update(smf_bearer_t *bearer) +{ + smf_pf_t *pf = NULL; + ogs_pfcp_pdr_t *dl_pdr = NULL, *ul_pdr = NULL; + + ogs_assert(bearer); + + dl_pdr = bearer->dl_pdr; + ogs_assert(dl_pdr); + ul_pdr = bearer->ul_pdr; + ogs_assert(ul_pdr); + + dl_pdr->num_of_flow = 0; + ul_pdr->num_of_flow = 0; + + ogs_list_for_each(&bearer->pf_list, pf) { + if (pf->direction == OGS_FLOW_DOWNLINK_ONLY) { + dl_pdr->flow_description[dl_pdr->num_of_flow++] = + pf->flow_description; + + } else if (pf->direction == OGS_FLOW_UPLINK_ONLY) { + ul_pdr->flow_description[ul_pdr->num_of_flow++] = + pf->flow_description; + } else { + ogs_assert_if_reached(); + ogs_fatal("Flow Bidirectional is not supported[%d]", + pf->direction); + } + } +} + +void smf_bearer_qos_update(smf_bearer_t *bearer) +{ + smf_sess_t *sess = NULL; + + ogs_pfcp_pdr_t *dl_pdr = NULL, *ul_pdr = NULL; + ogs_pfcp_qer_t *qer = NULL; + + ogs_assert(bearer); + sess = bearer->sess; + ogs_assert(sess); + + dl_pdr = bearer->dl_pdr; + ogs_assert(dl_pdr); + ul_pdr = bearer->ul_pdr; + ogs_assert(ul_pdr); + + qer = bearer->qer; + if (!qer) { + qer = ogs_pfcp_qer_add(&sess->pfcp); + ogs_assert(qer); + bearer->qer = qer; + } + + ogs_pfcp_pdr_associate_qer(dl_pdr, qer); + ogs_pfcp_pdr_associate_qer(ul_pdr, qer); + + qer->mbr.uplink = bearer->qos.mbr.uplink; + qer->mbr.downlink = bearer->qos.mbr.downlink; + qer->gbr.uplink = bearer->qos.gbr.uplink; + qer->gbr.downlink = bearer->qos.gbr.downlink; +} + smf_bearer_t *smf_default_bearer_in_sess(smf_sess_t *sess) { ogs_assert(sess); diff --git a/src/smf/context.h b/src/smf/context.h index 018f3ed52..e7d3e1b4e 100644 --- a/src/smf/context.h +++ b/src/smf/context.h @@ -137,7 +137,6 @@ ED3(uint8_t spare:2;, uint8_t identifier:4;) uint8_t precedence; /* Only used in EPC */ - uint8_t epc_precedence; /* Only used in EPC */ uint8_t *identifier_node; /* Pool-Node for Identifier */ uint8_t *precedence_node; /* Pool-Node for Precedence */ @@ -150,6 +149,10 @@ ED3(uint8_t spare:2;, typedef struct smf_bearer_s { ogs_lnode_t lnode; /**< A node of list_t */ + + ogs_lnode_t to_update_node; + ogs_lnode_t to_delete_node; + uint32_t index; ogs_pfcp_pdr_t *dl_pdr; @@ -182,6 +185,9 @@ typedef struct smf_bearer_s { ogs_list_t pf_list; ogs_list_t pf_to_add_list; + uint8_t num_of_pf_to_delete; + uint8_t pf_to_delete[OGS_MAX_NUM_OF_FLOW_IN_NAS]; + smf_sess_t *sess; } smf_bearer_t; @@ -285,8 +291,10 @@ typedef struct smf_sess_s { ogs_nas_extended_protocol_configuration_options_t ue_pco; } nas; /* Saved from NAS-5GS */ - ogs_pcc_rule_t pcc_rule[OGS_MAX_NUM_OF_PCC_RULE]; /* Saved from Gx */ - int num_of_pcc_rule; + struct { + ogs_pcc_rule_t pcc_rule[OGS_MAX_NUM_OF_PCC_RULE]; + int num_of_pcc_rule; + } policy; /* Saved from N7 or Gx */ /* Paging */ struct { @@ -300,7 +308,8 @@ typedef struct smf_sess_s { /* State */ #define SMF_NGAP_STATE_NONE 0 #define SMF_NGAP_STATE_DELETE_TRIGGER_UE_REQUESTED 1 -#define SMF_NGAP_STATE_ERROR_INDICATION_RECEIVED_FROM_5G_AN 2 +#define SMF_NGAP_STATE_DELETE_TRIGGER_PCF_INITIATED 2 +#define SMF_NGAP_STATE_ERROR_INDICATION_RECEIVED_FROM_5G_AN 3 struct { int pdu_session_resource_release; } ngap_state; @@ -391,6 +400,8 @@ void smf_sess_delete_indirect_data_forwarding(smf_sess_t *sess); void smf_sess_create_cp_up_data_forwarding(smf_sess_t *sess); void smf_sess_delete_cp_up_data_forwarding(smf_sess_t *sess); +ogs_pcc_rule_t *smf_pcc_rule_find_by_id(smf_sess_t *sess, char *pcc_rule_id); + smf_bearer_t *smf_qos_flow_add(smf_sess_t *sess); smf_bearer_t *smf_qos_flow_find_by_qfi(smf_sess_t *sess, uint8_t qfi); smf_bearer_t *smf_qos_flow_find_by_pcc_rule_id( @@ -408,6 +419,9 @@ smf_bearer_t *smf_bearer_find_by_pdr_id( smf_sess_t *sess, ogs_pfcp_pdr_id_t pdr_id); smf_bearer_t *smf_default_bearer_in_sess(smf_sess_t *sess); +void smf_bearer_tft_update(smf_bearer_t *bearer); +void smf_bearer_qos_update(smf_bearer_t *bearer); + smf_ue_t *smf_ue_cycle(smf_ue_t *smf_ue); smf_sess_t *smf_sess_cycle(smf_sess_t *sess); smf_bearer_t *smf_qos_flow_cycle(smf_bearer_t *qos_flow); diff --git a/src/smf/gsm-build.c b/src/smf/gsm-build.c index c370ba359..d0253f7a3 100644 --- a/src/smf/gsm-build.c +++ b/src/smf/gsm-build.c @@ -242,6 +242,9 @@ ogs_pkbuf_t *gsm_build_pdu_session_establishment_reject( pdu_session_establishment_reject = &message.gsm.pdu_session_establishment_reject; + ogs_assert(sess); + ogs_assert(gsm_cause); + memset(&message, 0, sizeof(message)); message.gsm.h.extended_protocol_discriminator = OGS_NAS_EXTENDED_PROTOCOL_DISCRIMINATOR_5GSM; @@ -263,21 +266,33 @@ static void encode_qos_rule_packet_filter( ogs_assert(qos_rule); ogs_assert(qos_flow); - i = 0; - ogs_list_for_each(&qos_flow->pf_list, pf) { - ogs_assert(i < OGS_MAX_NUM_OF_FLOW_IN_NAS); - qos_rule->pf[i].direction = pf->direction; - qos_rule->pf[i].identifier = pf->identifier; + if (qos_rule->code == OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_DELETE_PACKET_FILTERS) { + + for (i = 0; i < qos_flow->num_of_pf_to_delete; i++) { + qos_rule->pf[i].identifier = qos_flow->pf_to_delete[i]; + } + qos_rule->num_of_packet_filter = qos_flow->num_of_pf_to_delete; + + } else { + + i = 0; + ogs_list_for_each_entry(&qos_flow->pf_to_add_list, pf, to_add_node) { + ogs_assert(i < OGS_MAX_NUM_OF_FLOW_IN_NAS); + qos_rule->pf[i].direction = pf->direction; + qos_rule->pf[i].identifier = pf->identifier; + + ogs_pf_content_from_ipfw_rule( + pf->direction, &qos_rule->pf[i].content, &pf->ipfw_rule); + i++; + } + qos_rule->num_of_packet_filter = i; - ogs_pf_content_from_ipfw_rule( - pf->direction, &qos_rule->pf[i].content, &pf->ipfw_rule); - i++; } - qos_rule->num_of_packet_filter = i; } ogs_pkbuf_t *gsm_build_qos_flow_modification_command( - smf_bearer_t *qos_flow, uint8_t pti) + smf_bearer_t *qos_flow, uint8_t pti, + uint8_t qos_rule_code, uint8_t qos_flow_description_code) { ogs_pkbuf_t *pkbuf = NULL; smf_sess_t *sess = NULL; @@ -317,97 +332,145 @@ ogs_pkbuf_t *gsm_build_qos_flow_modification_command( message.gsm.h.message_type = OGS_NAS_5GS_PDU_SESSION_MODIFICATION_COMMAND; /* QoS rule */ - memset(qos_rule, 0, sizeof(qos_rule)); - qos_rule[0].identifier = qos_flow->qfi; /* Use QFI in Open5GS */ - qos_rule[0].code = OGS_NAS_QOS_CODE_CREATE_NEW_QOS_RULE; + if (qos_rule_code) { + memset(qos_rule, 0, sizeof(qos_rule)); + qos_rule[0].identifier = qos_flow->qfi; /* Use QFI in Open5GS */ + qos_rule[0].code = qos_rule_code; - encode_qos_rule_packet_filter(&qos_rule[0], qos_flow); + if (qos_rule_code != OGS_NAS_QOS_CODE_DELETE_EXISTING_QOS_RULE && + qos_rule_code != OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_WITHOUT_MODIFYING_PACKET_FILTERS) + encode_qos_rule_packet_filter(&qos_rule[0], qos_flow); - ogs_assert(dl_pdr->precedence > 0 && dl_pdr->precedence < 255); - qos_rule[0].precedence = dl_pdr->precedence; /* Use PCC Rule Precedence */ - qos_rule[0].flow.segregation = 0; - qos_rule[0].flow.identifier = qos_flow->qfi; + if (qos_rule_code != OGS_NAS_QOS_CODE_DELETE_EXISTING_QOS_RULE && + qos_rule_code != OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_DELETE_PACKET_FILTERS && + qos_rule_code != OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_WITHOUT_MODIFYING_PACKET_FILTERS) { + ogs_assert(dl_pdr->precedence > 0 && dl_pdr->precedence < 255); + /* Use PCC Rule Precedence */ + qos_rule[0].precedence = dl_pdr->precedence; - pdu_session_modification_command->presencemask |= - OGS_NAS_5GS_PDU_SESSION_MODIFICATION_COMMAND_AUTHORIZED_QOS_RULES_PRESENT; - rv = ogs_nas_build_qos_rules(authorized_qos_rules, qos_rule, 1); - ogs_expect_or_return_val(rv == OGS_OK, NULL); - ogs_expect_or_return_val(authorized_qos_rules->length, NULL); + qos_rule[0].flow.segregation = 0; + qos_rule[0].flow.identifier = qos_flow->qfi; + } + + rv = ogs_nas_build_qos_rules(authorized_qos_rules, qos_rule, 1); + ogs_expect_or_return_val(rv == OGS_OK, NULL); + ogs_expect_or_return_val(authorized_qos_rules->length, NULL); + + pdu_session_modification_command->presencemask |= + OGS_NAS_5GS_PDU_SESSION_MODIFICATION_COMMAND_AUTHORIZED_QOS_RULES_PRESENT; + } /* QoS flow descriptions */ - memset(&qos_flow_description, 0, sizeof(qos_flow_description)); - qos_flow_description[0].identifier = qos_flow->qfi; - qos_flow_description[0].code = OGS_NAS_CREATE_NEW_QOS_FLOW_DESCRIPTION; - qos_flow_description[0].E_bit = 1; + if (qos_flow_description_code) { + memset(&qos_flow_description, 0, sizeof(qos_flow_description)); + qos_flow_description[0].identifier = qos_flow->qfi; + qos_flow_description[0].code = qos_flow_description_code; - num_of_param = 0; + num_of_param = 0; - qos_flow_description[0].param[num_of_param].identifier = - OGS_NAX_QOS_FLOW_PARAMETER_ID_5QI; - qos_flow_description[0].param[num_of_param].len = - sizeof(qos_flow_description[0].param[num_of_param].qos_index); - qos_flow_description[0].param[num_of_param].qos_index = qos_flow->qos.index; - num_of_param++; + if (qos_flow_description_code != OGS_NAS_DELETE_NEW_QOS_FLOW_DESCRIPTION) { + qos_flow_description[0].E_bit = 1; - if (qos_flow->qos.gbr.uplink) { - qos_flow_description[0].param[num_of_param].identifier = - OGS_NAX_QOS_FLOW_PARAMETER_ID_GFBR_UPLINK; - qos_flow_description[0].param[num_of_param].len = - sizeof(qos_flow_description[0].param[num_of_param].br); - ogs_nas_bitrate_from_uint64( - &qos_flow_description[0].param[num_of_param].br, - qos_flow->qos.gbr.uplink); - num_of_param++; + qos_flow_description[0].param[num_of_param].identifier = + OGS_NAX_QOS_FLOW_PARAMETER_ID_5QI; + qos_flow_description[0].param[num_of_param].len = + sizeof(qos_flow_description[0].param[num_of_param].qos_index); + qos_flow_description[0].param[num_of_param].qos_index = + qos_flow->qos.index; + num_of_param++; + + if (qos_flow->qos.gbr.uplink) { + qos_flow_description[0].param[num_of_param].identifier = + OGS_NAX_QOS_FLOW_PARAMETER_ID_GFBR_UPLINK; + qos_flow_description[0].param[num_of_param].len = + sizeof(qos_flow_description[0].param[num_of_param].br); + ogs_nas_bitrate_from_uint64( + &qos_flow_description[0].param[num_of_param].br, + qos_flow->qos.gbr.uplink); + num_of_param++; + } + if (qos_flow->qos.gbr.downlink) { + qos_flow_description[0].param[num_of_param].identifier = + OGS_NAX_QOS_FLOW_PARAMETER_ID_GFBR_DOWNLINK; + qos_flow_description[0].param[num_of_param].len = + sizeof(qos_flow_description[0].param[num_of_param].br); + ogs_nas_bitrate_from_uint64( + &qos_flow_description[0].param[num_of_param].br, + qos_flow->qos.gbr.downlink); + num_of_param++; + } + if (qos_flow->qos.mbr.uplink) { + qos_flow_description[0].param[num_of_param].identifier = + OGS_NAX_QOS_FLOW_PARAMETER_ID_MFBR_UPLINK; + qos_flow_description[0].param[num_of_param].len = + sizeof(qos_flow_description[0].param[num_of_param].br); + ogs_nas_bitrate_from_uint64( + &qos_flow_description[0].param[num_of_param].br, + qos_flow->qos.mbr.uplink); + num_of_param++; + } + if (qos_flow->qos.mbr.downlink) { + qos_flow_description[0].param[num_of_param].identifier = + OGS_NAX_QOS_FLOW_PARAMETER_ID_MFBR_DOWNLINK; + qos_flow_description[0].param[num_of_param].len = + sizeof(qos_flow_description[0].param[num_of_param].br); + ogs_nas_bitrate_from_uint64( + &qos_flow_description[0].param[num_of_param].br, + qos_flow->qos.mbr.downlink); + num_of_param++; + } + } + + qos_flow_description[0].num_of_parameter = num_of_param; + + rv = ogs_nas_build_qos_flow_descriptions( + authorized_qos_flow_descriptions, qos_flow_description, 1); + ogs_expect_or_return_val(rv == OGS_OK, NULL); + ogs_expect_or_return_val( + authorized_qos_flow_descriptions->length, NULL); + + pdu_session_modification_command->presencemask |= + OGS_NAS_5GS_PDU_SESSION_MODIFICATION_COMMAND_AUTHORIZED_QOS_FLOW_DESCRIPTIONS_PRESENT; } - if (qos_flow->qos.gbr.downlink) { - qos_flow_description[0].param[num_of_param].identifier = - OGS_NAX_QOS_FLOW_PARAMETER_ID_GFBR_DOWNLINK; - qos_flow_description[0].param[num_of_param].len = - sizeof(qos_flow_description[0].param[num_of_param].br); - ogs_nas_bitrate_from_uint64( - &qos_flow_description[0].param[num_of_param].br, - qos_flow->qos.gbr.downlink); - num_of_param++; - } - if (qos_flow->qos.mbr.uplink) { - qos_flow_description[0].param[num_of_param].identifier = - OGS_NAX_QOS_FLOW_PARAMETER_ID_MFBR_UPLINK; - qos_flow_description[0].param[num_of_param].len = - sizeof(qos_flow_description[0].param[num_of_param].br); - ogs_nas_bitrate_from_uint64( - &qos_flow_description[0].param[num_of_param].br, - qos_flow->qos.mbr.uplink); - num_of_param++; - } - if (qos_flow->qos.mbr.downlink) { - qos_flow_description[0].param[num_of_param].identifier = - OGS_NAX_QOS_FLOW_PARAMETER_ID_MFBR_DOWNLINK; - qos_flow_description[0].param[num_of_param].len = - sizeof(qos_flow_description[0].param[num_of_param].br); - ogs_nas_bitrate_from_uint64( - &qos_flow_description[0].param[num_of_param].br, - qos_flow->qos.mbr.downlink); - num_of_param++; - } - - qos_flow_description[0].num_of_parameter = num_of_param; - - pdu_session_modification_command->presencemask |= - OGS_NAS_5GS_PDU_SESSION_MODIFICATION_COMMAND_AUTHORIZED_QOS_FLOW_DESCRIPTIONS_PRESENT; - rv = ogs_nas_build_qos_flow_descriptions( - authorized_qos_flow_descriptions, qos_flow_description, 1); - ogs_expect_or_return_val(rv == OGS_OK, NULL); - ogs_expect_or_return_val(authorized_qos_flow_descriptions->length, NULL); pkbuf = ogs_nas_5gs_plain_encode(&message); ogs_assert(pkbuf); - ogs_free(authorized_qos_rules->buffer); - ogs_free(authorized_qos_flow_descriptions->buffer); + if (pdu_session_modification_command->presencemask & + OGS_NAS_5GS_PDU_SESSION_MODIFICATION_COMMAND_AUTHORIZED_QOS_RULES_PRESENT) { + ogs_free(authorized_qos_rules->buffer); + } + if (pdu_session_modification_command->presencemask & + OGS_NAS_5GS_PDU_SESSION_MODIFICATION_COMMAND_AUTHORIZED_QOS_FLOW_DESCRIPTIONS_PRESENT) { + ogs_free(authorized_qos_flow_descriptions->buffer); + } return pkbuf; } +ogs_pkbuf_t *gsm_build_pdu_session_modification_reject( + smf_sess_t *sess, ogs_nas_5gsm_cause_t gsm_cause) +{ + ogs_nas_5gs_message_t message; + ogs_nas_5gs_pdu_session_modification_reject_t * + pdu_session_modification_reject = + &message.gsm.pdu_session_modification_reject; + + ogs_assert(sess); + ogs_assert(gsm_cause); + + memset(&message, 0, sizeof(message)); + message.gsm.h.extended_protocol_discriminator = + OGS_NAS_EXTENDED_PROTOCOL_DISCRIMINATOR_5GSM; + message.gsm.h.pdu_session_identity = sess->psi; + message.gsm.h.procedure_transaction_identity = sess->pti; + message.gsm.h.message_type = OGS_NAS_5GS_PDU_SESSION_MODIFICATION_REJECT; + + pdu_session_modification_reject->gsm_cause = gsm_cause; + + return ogs_nas_5gs_plain_encode(&message); +} + ogs_pkbuf_t *gsm_build_pdu_session_release_command( smf_sess_t *sess, ogs_nas_5gsm_cause_t gsm_cause) { @@ -415,6 +478,9 @@ ogs_pkbuf_t *gsm_build_pdu_session_release_command( ogs_nas_5gs_pdu_session_release_command_t *pdu_session_release_command = &message.gsm.pdu_session_release_command; + ogs_assert(sess); + ogs_assert(gsm_cause); + memset(&message, 0, sizeof(message)); message.gsm.h.extended_protocol_discriminator = OGS_NAS_EXTENDED_PROTOCOL_DISCRIMINATOR_5GSM; @@ -434,6 +500,9 @@ ogs_pkbuf_t *gsm_build_pdu_session_release_reject( ogs_nas_5gs_pdu_session_release_reject_t * pdu_session_release_reject = &message.gsm.pdu_session_release_reject; + ogs_assert(sess); + ogs_assert(gsm_cause); + memset(&message, 0, sizeof(message)); message.gsm.h.extended_protocol_discriminator = OGS_NAS_EXTENDED_PROTOCOL_DISCRIMINATOR_5GSM; diff --git a/src/smf/gsm-build.h b/src/smf/gsm-build.h index 10368944b..7adcf2062 100644 --- a/src/smf/gsm-build.h +++ b/src/smf/gsm-build.h @@ -31,7 +31,10 @@ ogs_pkbuf_t *gsm_build_pdu_session_establishment_reject( smf_sess_t *sess, ogs_nas_5gsm_cause_t gsm_cause); ogs_pkbuf_t *gsm_build_qos_flow_modification_command( - smf_bearer_t *qos_flow, uint8_t pti); + smf_bearer_t *qos_flow, uint8_t pti, + uint8_t qos_rule_code, uint8_t qos_flow_description_code); +ogs_pkbuf_t *gsm_build_pdu_session_modification_reject( + smf_sess_t *sess, ogs_nas_5gsm_cause_t gsm_cause); ogs_pkbuf_t *gsm_build_pdu_session_release_command( smf_sess_t *sess, ogs_nas_5gsm_cause_t gsm_cause); diff --git a/src/smf/gsm-handler.c b/src/smf/gsm-handler.c index 475fb500d..f0f47fced 100644 --- a/src/smf/gsm-handler.c +++ b/src/smf/gsm-handler.c @@ -21,6 +21,8 @@ #include "sbi-path.h" #include "pfcp-path.h" +#include "ipfw/ipfw2.h" + #undef OGS_LOG_DOMAIN #define OGS_LOG_DOMAIN __gsm_log_domain @@ -71,3 +73,454 @@ int gsm_handle_pdu_session_establishment_request( return OGS_OK; } + +static int reconfigure_packet_filter( + smf_pf_t *pf, ogs_nas_qos_rule_t *qos_rule, int i) +{ + int j; + + ogs_assert(pf); + ogs_assert(qos_rule); + + memset(&pf->ipfw_rule, 0, sizeof(ogs_ipfw_rule_t)); + pf->direction = qos_rule->pf[i].direction; + for (j = 0; j < qos_rule->pf[i].content.num_of_component; j++) { + switch(qos_rule->pf[i].content.component[j].type) { + case OGS_PACKET_FILTER_PROTOCOL_IDENTIFIER_NEXT_HEADER_TYPE: + pf->ipfw_rule.proto = qos_rule->pf[i].content.component[j].proto; + break; + case OGS_PACKET_FILTER_IPV4_REMOTE_ADDRESS_TYPE: + pf->ipfw_rule.ipv4_dst = 1; + pf->ipfw_rule.ip.dst.addr[0] = + qos_rule->pf[i].content.component[j].ipv4.addr; + pf->ipfw_rule.ip.dst.mask[0] = + qos_rule->pf[i].content.component[j].ipv4.mask; + break; + case OGS_PACKET_FILTER_IPV4_LOCAL_ADDRESS_TYPE: + pf->ipfw_rule.ipv4_src = 1; + pf->ipfw_rule.ip.src.addr[0] = + qos_rule->pf[i].content.component[j].ipv4.addr; + pf->ipfw_rule.ip.src.mask[0] = + qos_rule->pf[i].content.component[j].ipv4.mask; + break; + case OGS_PACKET_FILTER_IPV6_REMOTE_ADDRESS_TYPE: + pf->ipfw_rule.ipv6_dst = 1; + memcpy(pf->ipfw_rule.ip.dst.addr, + qos_rule->pf[i].content.component[j].ipv6_mask.addr, + sizeof(pf->ipfw_rule.ip.dst.addr)); + memcpy(pf->ipfw_rule.ip.dst.mask, + qos_rule->pf[i].content.component[j].ipv6_mask.mask, + sizeof(pf->ipfw_rule.ip.dst.mask)); + break; + case OGS_PACKET_FILTER_IPV6_REMOTE_ADDRESS_PREFIX_LENGTH_TYPE: + pf->ipfw_rule.ipv6_dst = 1; + memcpy(pf->ipfw_rule.ip.dst.addr, + qos_rule->pf[i].content.component[j].ipv6_mask.addr, + sizeof(pf->ipfw_rule.ip.dst.addr)); + n2mask((struct in6_addr *)pf->ipfw_rule.ip.dst.mask, + qos_rule->pf[i].content.component[j].ipv6.prefixlen); + break; + case OGS_PACKET_FILTER_IPV6_LOCAL_ADDRESS_TYPE: + pf->ipfw_rule.ipv6_src = 1; + memcpy(pf->ipfw_rule.ip.src.addr, + qos_rule->pf[i].content.component[j].ipv6_mask.addr, + sizeof(pf->ipfw_rule.ip.src.addr)); + memcpy(pf->ipfw_rule.ip.src.mask, + qos_rule->pf[i].content.component[j].ipv6_mask.mask, + sizeof(pf->ipfw_rule.ip.src.mask)); + break; + case OGS_PACKET_FILTER_IPV6_LOCAL_ADDRESS_PREFIX_LENGTH_TYPE: + pf->ipfw_rule.ipv6_src = 1; + memcpy(pf->ipfw_rule.ip.src.addr, + qos_rule->pf[i].content.component[j].ipv6_mask.addr, + sizeof(pf->ipfw_rule.ip.src.addr)); + n2mask((struct in6_addr *)pf->ipfw_rule.ip.src.mask, + qos_rule->pf[i].content.component[j].ipv6.prefixlen); + break; + case OGS_PACKET_FILTER_SINGLE_LOCAL_PORT_TYPE: + pf->ipfw_rule.port.src.low = pf->ipfw_rule.port.src.high = + qos_rule->pf[i].content.component[j].port.low; + break; + case OGS_PACKET_FILTER_SINGLE_REMOTE_PORT_TYPE: + pf->ipfw_rule.port.dst.low = pf->ipfw_rule.port.dst.high = + qos_rule->pf[i].content.component[j].port.low; + break; + case OGS_PACKET_FILTER_LOCAL_PORT_RANGE_TYPE: + pf->ipfw_rule.port.src.low = + qos_rule->pf[i].content.component[j].port.low; + pf->ipfw_rule.port.src.high = + qos_rule->pf[i].content.component[j].port.high; + break; + case OGS_PACKET_FILTER_REMOTE_PORT_RANGE_TYPE: + pf->ipfw_rule.port.dst.low = + qos_rule->pf[i].content.component[j].port.low; + pf->ipfw_rule.port.dst.high = + qos_rule->pf[i].content.component[j].port.high; + break; + default: + ogs_error("Unknown Packet Filter Type(%d)", + qos_rule->pf[i].content.component[j].type); + return OGS_ERROR; + } + } + + return j; +} + +#define qos_flow_find_or_add(list, node, member) \ + do { \ + smf_bearer_t *iter = NULL; \ + bool found = false; \ + \ + ogs_assert(node); \ + \ + ogs_list_for_each_entry(list, iter, member) { \ + if (iter->qfi == node->qfi) { \ + found = true; \ + break; \ + } \ + } \ + if (found == false) { \ + ogs_list_add(list, &node->member); \ + } \ + } while(0); + +int gsm_handle_pdu_session_modification_request( + smf_sess_t *sess, ogs_sbi_stream_t *stream, + ogs_nas_5gs_pdu_session_modification_request_t * + pdu_session_modification_request) +{ + char *strerror = NULL; + + int i, j; + + uint64_t pfcp_flags = 0; + ogs_list_t update_list, delete_list; + smf_bearer_t *qos_flow = NULL; + smf_pf_t *pf = NULL; + + ogs_nas_qos_rule_t qos_rule[OGS_NAS_MAX_NUM_OF_QOS_RULE]; + ogs_nas_qos_flow_description_t + qos_flow_description[OGS_NAS_MAX_NUM_OF_QOS_FLOW_DESCRIPTION]; + + ogs_nas_qos_rules_t *requested_qos_rules = + &pdu_session_modification_request->requested_qos_rules; + ogs_nas_qos_flow_descriptions_t *requested_qos_flow_descriptions = + &pdu_session_modification_request->requested_qos_flow_descriptions; + + smf_ue_t *smf_ue = NULL; + ogs_pkbuf_t *n1smbuf = NULL; + + ogs_assert(sess); + smf_ue = sess->smf_ue; + ogs_assert(smf_ue); + ogs_assert(stream); + ogs_assert(pdu_session_modification_request); + + ogs_list_init(&update_list); + ogs_list_init(&delete_list); + + if (pdu_session_modification_request->presencemask & + OGS_NAS_5GS_PDU_SESSION_MODIFICATION_REQUEST_5GSM_CAUSE_PRESENT) { + /* Nothing to do */ + } + + if (pdu_session_modification_request->presencemask & + OGS_NAS_5GS_PDU_SESSION_MODIFICATION_REQUEST_REQUESTED_QOS_RULES_PRESENT) { + int num_of_rule = 0; + + num_of_rule = ogs_nas_parse_qos_rules(qos_rule, requested_qos_rules); + ogs_assert(num_of_rule > 0); + + for (i = 0; i < num_of_rule; i++) { + qos_flow = smf_qos_flow_find_by_qfi( + sess, qos_rule[i].identifier); + if (!qos_flow) { + ogs_error("No Qos Flow"); + continue; + } + + ogs_list_init(&qos_flow->pf_to_add_list); + + if (qos_rule[i].code == OGS_NAS_QOS_CODE_DELETE_EXISTING_QOS_RULE) { + smf_pf_remove_all(qos_flow); + + pfcp_flags |= OGS_PFCP_MODIFY_REMOVE; + qos_flow_find_or_add(&delete_list, qos_flow, to_delete_node); + } else if (qos_rule[i].code == + OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_REPLACE_PACKET_FILTERS) { + for (j = 0; j < qos_rule[i].num_of_packet_filter && + j < OGS_MAX_NUM_OF_FLOW_IN_NAS; j++) { + + pf = smf_pf_find_by_id( + qos_flow, qos_rule[i].pf[j].identifier+1); + if (pf) { + ogs_assert( + reconfigure_packet_filter(pf, &qos_rule[i], i) > 0); + /* + * Refer to lib/ipfw/ogs-ipfw.h + * Issue #338 + * + * + * TFT : Local REMOTE + * --> + * RULE : Source Destination + * + * + * TFT : Local REMOTE + * --> + * RULE : Source Destination + */ + if (pf->direction == OGS_FLOW_DOWNLINK_ONLY) + ogs_ipfw_rule_swap(&pf->ipfw_rule); + + if (pf->flow_description) + ogs_free(pf->flow_description); + + /* + * Issue #338 + * + * + * RULE : Source Destination + * --> + * GX : permit out from to + * PFCP : permit out from to + * + * + * RULE : Source Destination + * --> + * GX : permit out from to + * PFCP : permit out from to + */ + if (pf->direction == OGS_FLOW_UPLINK_ONLY) { + ogs_ipfw_rule_t tmp; + ogs_ipfw_copy_and_swap(&tmp, &pf->ipfw_rule); + pf->flow_description = + ogs_ipfw_encode_flow_description(&tmp); + ogs_assert(pf->flow_description); + } else { + pf->flow_description = + ogs_ipfw_encode_flow_description( + &pf->ipfw_rule); + ogs_assert(pf->flow_description); + } + + pfcp_flags |= OGS_PFCP_MODIFY_TFT_REPLACE; + qos_flow_find_or_add( + &update_list, qos_flow, to_update_node); + + ogs_list_add( + &qos_flow->pf_to_add_list, &pf->to_add_node); + } + } + } else if (qos_rule[i].code == + OGS_NAS_QOS_CODE_CREATE_NEW_QOS_RULE || + qos_rule[i].code == + OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_ADD_PACKET_FILTERS) { + + if (qos_rule[i].code == OGS_NAS_QOS_CODE_CREATE_NEW_QOS_RULE) + smf_pf_remove_all(qos_flow); + + for (j = 0; j < qos_rule[i].num_of_packet_filter && + j < OGS_MAX_NUM_OF_FLOW_IN_NAS; j++) { + + pf = smf_pf_find_by_id( + qos_flow, qos_rule[i].pf[j].identifier+1); + if (!pf) + pf = smf_pf_add(qos_flow); + ogs_assert(pf); + + ogs_assert( + reconfigure_packet_filter(pf, &qos_rule[i], i) > 0); + /* + * Refer to lib/ipfw/ogs-ipfw.h + * Issue #338 + * + * + * TFT : Local REMOTE + * --> + * RULE : Source Destination + * + * + * TFT : Local REMOTE + * --> + * RULE : Source Destination + */ + if (pf->direction == OGS_FLOW_DOWNLINK_ONLY) + ogs_ipfw_rule_swap(&pf->ipfw_rule); + + if (pf->flow_description) + ogs_free(pf->flow_description); + + /* + * Issue #338 + * + * + * RULE : Source Destination + * --> + * GX : permit out from to + * PFCP : permit out from to + * + * + * RULE : Source Destination + * --> + * GX : permit out from to + * PFCP : permit out from to + */ + if (pf->direction == OGS_FLOW_UPLINK_ONLY) { + ogs_ipfw_rule_t tmp; + ogs_ipfw_copy_and_swap(&tmp, &pf->ipfw_rule); + pf->flow_description = + ogs_ipfw_encode_flow_description(&tmp); + ogs_assert(pf->flow_description); + } else { + pf->flow_description = + ogs_ipfw_encode_flow_description(&pf->ipfw_rule); + ogs_assert(pf->flow_description); + } + + if (qos_rule[i].code == + OGS_NAS_QOS_CODE_CREATE_NEW_QOS_RULE) { + pfcp_flags |= OGS_PFCP_MODIFY_TFT_NEW; + } else if (qos_rule[i].code == + OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_ADD_PACKET_FILTERS) { + pfcp_flags |= OGS_PFCP_MODIFY_TFT_ADD; + } else + ogs_assert_if_reached(); + + qos_flow_find_or_add( + &update_list, qos_flow, to_update_node); + + ogs_list_add( + &qos_flow->pf_to_add_list, &pf->to_add_node); + } + } else if (qos_rule[i].code == + OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_DELETE_PACKET_FILTERS) { + + qos_flow->num_of_pf_to_delete = 0; + for (j = 0; j < qos_rule[i].num_of_packet_filter && + j < OGS_MAX_NUM_OF_FLOW_IN_NAS; j++) { + + pf = smf_pf_find_by_id( + qos_flow, qos_rule[i].pf[j].identifier+1); + if (pf) { + qos_flow->pf_to_delete + [qos_flow->num_of_pf_to_delete++] = + qos_rule[i].pf[j].identifier; + smf_pf_remove(pf); + } + } + + if (ogs_list_count(&qos_flow->pf_list)) { + pfcp_flags |= OGS_PFCP_MODIFY_TFT_DELETE; + qos_flow_find_or_add( + &update_list, qos_flow, to_update_node); + } else { + pfcp_flags |= OGS_PFCP_MODIFY_REMOVE; + qos_flow_find_or_add( + &delete_list, qos_flow, to_delete_node); + } + } + } + } + + if (pdu_session_modification_request->presencemask & + OGS_NAS_5GS_PDU_SESSION_MODIFICATION_REQUEST_REQUESTED_QOS_FLOW_DESCRIPTIONS_PRESENT) { + int num_of_description = 0; + + num_of_description = ogs_nas_parse_qos_flow_descriptions( + qos_flow_description, requested_qos_flow_descriptions); + ogs_assert(num_of_description > 0); + + for (i = 0; i < num_of_description; i++) { + qos_flow = smf_qos_flow_find_by_qfi( + sess, qos_flow_description[i].identifier); + if (!qos_flow) { + ogs_error("No Qos Flow"); + continue; + } + + for (j = 0; j < qos_flow_description[i].num_of_parameter; j++) { + switch(qos_flow_description[i].param[j].identifier) { + case OGS_NAX_QOS_FLOW_PARAMETER_ID_5QI: + /* Nothing */ + break; + case OGS_NAX_QOS_FLOW_PARAMETER_ID_GFBR_UPLINK: + qos_flow->qos.gbr.uplink = ogs_nas_bitrate_to_uint64( + &qos_flow_description[i].param[j].br); + break; + case OGS_NAX_QOS_FLOW_PARAMETER_ID_GFBR_DOWNLINK: + qos_flow->qos.gbr.downlink = ogs_nas_bitrate_to_uint64( + &qos_flow_description[i].param[j].br); + break; + case OGS_NAX_QOS_FLOW_PARAMETER_ID_MFBR_UPLINK: + qos_flow->qos.mbr.uplink = ogs_nas_bitrate_to_uint64( + &qos_flow_description[i].param[j].br); + break; + case OGS_NAX_QOS_FLOW_PARAMETER_ID_MFBR_DOWNLINK: + qos_flow->qos.mbr.downlink = ogs_nas_bitrate_to_uint64( + &qos_flow_description[i].param[j].br); + break; + default: + ogs_fatal("Unknown qos_flow parameter identifier [%d]", + qos_flow_description[i].param[i].identifier); + ogs_assert_if_reached(); + } + } + + pfcp_flags |= OGS_PFCP_MODIFY_QOS_MODIFY; + qos_flow_find_or_add(&update_list, qos_flow, to_update_node); + } + } + + if ((ogs_list_count(&update_list) + ogs_list_count(&delete_list)) != 1) { + strerror = ogs_msprintf("[%s:%d] Invalid modification request " + "[update:%d,delete:%d]", smf_ue->supi, sess->psi, + ogs_list_count(&update_list), ogs_list_count(&delete_list)); + ogs_assert(strerror); + + ogs_error("%s", strerror); + n1smbuf = gsm_build_pdu_session_modification_reject(sess, + OGS_5GSM_CAUSE_INVALID_MANDATORY_INFORMATION); + ogs_assert(n1smbuf); + + smf_sbi_send_sm_context_update_error(stream, + OGS_SBI_HTTP_STATUS_BAD_REQUEST, + strerror, smf_ue->supi, n1smbuf, NULL); + ogs_free(strerror); + + return OGS_ERROR; + } + + ogs_assert(qos_flow); + + if (pfcp_flags & OGS_PFCP_MODIFY_REMOVE) { + + ogs_assert(OGS_OK == + smf_5gc_pfcp_send_qos_flow_modification_request( + qos_flow, stream, + OGS_PFCP_MODIFY_UE_REQUESTED|pfcp_flags)); + + } else if (pfcp_flags & + (OGS_PFCP_MODIFY_TFT_NEW|OGS_PFCP_MODIFY_TFT_ADD| + OGS_PFCP_MODIFY_TFT_REPLACE|OGS_PFCP_MODIFY_TFT_DELETE| + OGS_PFCP_MODIFY_QOS_MODIFY)) { + + if (pfcp_flags & + (OGS_PFCP_MODIFY_TFT_NEW|OGS_PFCP_MODIFY_TFT_ADD| + OGS_PFCP_MODIFY_TFT_REPLACE|OGS_PFCP_MODIFY_TFT_DELETE)) + smf_bearer_tft_update(qos_flow); + + if (pfcp_flags & OGS_PFCP_MODIFY_QOS_MODIFY) + smf_bearer_qos_update(qos_flow); + + ogs_assert(OGS_OK == + smf_5gc_pfcp_send_qos_flow_modification_request( + qos_flow, stream, OGS_PFCP_MODIFY_UE_REQUESTED|pfcp_flags)); + } else { + ogs_fatal("Unknown PFCP-Flags : [0x%llx]", (long long)pfcp_flags); + ogs_assert_if_reached(); + } + + return OGS_OK; +} diff --git a/src/smf/gsm-handler.h b/src/smf/gsm-handler.h index 6d4c99668..15750aa93 100644 --- a/src/smf/gsm-handler.h +++ b/src/smf/gsm-handler.h @@ -31,6 +31,11 @@ int gsm_handle_pdu_session_establishment_request( ogs_nas_5gs_pdu_session_establishment_request_t * pdu_session_establishment_request); +int gsm_handle_pdu_session_modification_request( + smf_sess_t *sess, ogs_sbi_stream_t *stream, + ogs_nas_5gs_pdu_session_modification_request_t * + pdu_session_modification_request); + #ifdef __cplusplus } #endif diff --git a/src/smf/gsm-sm.c b/src/smf/gsm-sm.c index 83caedd64..d12e0655f 100644 --- a/src/smf/gsm-sm.c +++ b/src/smf/gsm-sm.c @@ -155,13 +155,12 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e) CASE(OGS_SBI_SERVICE_NAME_NPCF_SMPOLICYCONTROL) stream = e->sbi.data; - ogs_assert(stream); - state = e->sbi.state; SWITCH(sbi_message->h.resource.component[0]) CASE(OGS_SBI_RESOURCE_NAME_SM_POLICIES) if (!sbi_message->h.resource.component[1]) { + ogs_assert(stream); if (sbi_message->res_status != OGS_SBI_HTTP_STATUS_CREATED) { strerror = ogs_msprintf( @@ -193,10 +192,11 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e) ogs_assert(strerror); ogs_error("%s", strerror); - ogs_assert(true == - ogs_sbi_server_send_error(stream, - sbi_message->res_status, - sbi_message, strerror, NULL)); + if (stream) + ogs_assert(true == + ogs_sbi_server_send_error(stream, + sbi_message->res_status, + sbi_message, strerror, NULL)); ogs_free(strerror); break; } @@ -213,10 +213,11 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e) ogs_assert(strerror); ogs_error("%s", strerror); - ogs_assert(true == - ogs_sbi_server_send_error(stream, - OGS_SBI_HTTP_STATUS_BAD_REQUEST, - sbi_message, strerror, NULL)); + if (stream) + ogs_assert(true == + ogs_sbi_server_send_error(stream, + OGS_SBI_HTTP_STATUS_BAD_REQUEST, + sbi_message, strerror, NULL)); ogs_free(strerror); END } @@ -240,7 +241,7 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e) CASE(OGS_SBI_SERVICE_NAME_NAMF_COMM) SWITCH(sbi_message->h.resource.component[0]) CASE(OGS_SBI_RESOURCE_NAME_UE_CONTEXTS) - smf_namf_comm_handler_n1_n2_message_transfer( + smf_namf_comm_handle_n1_n2_message_transfer( sess, e->sbi.state, sbi_message); break; @@ -280,6 +281,16 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e) } break; + case OGS_NAS_5GS_PDU_SESSION_MODIFICATION_REQUEST: + rv = gsm_handle_pdu_session_modification_request(sess, stream, + &nas_message->gsm.pdu_session_modification_request); + if (rv != OGS_OK) { + ogs_error("[%s:%d] Cannot handle NAS message", + smf_ue->supi, sess->psi); + OGS_FSM_TRAN(s, smf_gsm_state_exception); + } + break; + case OGS_NAS_5GS_PDU_SESSION_MODIFICATION_COMPLETE: ogs_assert(true == ogs_sbi_send_http_status_no_content(stream)); break; @@ -375,7 +386,8 @@ void smf_gsm_state_operational(ogs_fsm_t *s, smf_event_t *e) case OpenAPI_n2_sm_info_type_PDU_RES_REL_RSP: ngap_state = sess->ngap_state.pdu_session_resource_release; - if (ngap_state == SMF_NGAP_STATE_DELETE_TRIGGER_UE_REQUESTED) { + if (ngap_state == SMF_NGAP_STATE_DELETE_TRIGGER_UE_REQUESTED || + ngap_state == SMF_NGAP_STATE_DELETE_TRIGGER_PCF_INITIATED) { ogs_assert(true == ogs_sbi_send_http_status_no_content(stream)); } else if (ngap_state == SMF_NGAP_STATE_ERROR_INDICATION_RECEIVED_FROM_5G_AN) { diff --git a/src/smf/gx-handler.c b/src/smf/gx-handler.c index 53acc8af1..c6d4c571b 100644 --- a/src/smf/gx-handler.c +++ b/src/smf/gx-handler.c @@ -75,9 +75,9 @@ void smf_gx_handle_cca_initial_request( return; } - sess->num_of_pcc_rule = gx_message->session_data.num_of_pcc_rule; + sess->policy.num_of_pcc_rule = gx_message->session_data.num_of_pcc_rule; for (i = 0; i < gx_message->session_data.num_of_pcc_rule; i++) - OGS_STORE_PCC_RULE(&sess->pcc_rule[i], + OGS_STORE_PCC_RULE(&sess->policy.pcc_rule[i], &gx_message->session_data.pcc_rule[i]); /* APN-AMBR @@ -298,9 +298,9 @@ void smf_gx_handle_re_auth_request( { int i; - sess->num_of_pcc_rule = gx_message->session_data.num_of_pcc_rule; + sess->policy.num_of_pcc_rule = gx_message->session_data.num_of_pcc_rule; for (i = 0; i < gx_message->session_data.num_of_pcc_rule; i++) - OGS_STORE_PCC_RULE(&sess->pcc_rule[i], + OGS_STORE_PCC_RULE(&sess->policy.pcc_rule[i], &gx_message->session_data.pcc_rule[i]); smf_bearer_binding(sess); diff --git a/src/smf/n4-build.c b/src/smf/n4-build.c index 5fb1aae7f..a9d721341 100644 --- a/src/smf/n4-build.c +++ b/src/smf/n4-build.c @@ -323,7 +323,10 @@ ogs_pkbuf_t *smf_n4_build_qos_flow_modification_request( i++; } } - if (modify_flags & OGS_PFCP_MODIFY_TFT_UPDATE) { + if (modify_flags & + (OGS_PFCP_MODIFY_TFT_NEW|OGS_PFCP_MODIFY_TFT_ADD| + OGS_PFCP_MODIFY_TFT_REPLACE|OGS_PFCP_MODIFY_TFT_DELETE| + OGS_PFCP_MODIFY_EPC_TFT_UPDATE)) { ogs_pfcp_pdrbuf_init(); /* Update PDR */ @@ -368,7 +371,9 @@ ogs_pkbuf_t *smf_n4_build_qos_flow_modification_request( i++; } } - if (modify_flags & OGS_PFCP_MODIFY_QOS_UPDATE) { + if (modify_flags & + (OGS_PFCP_MODIFY_QOS_MODIFY| + OGS_PFCP_MODIFY_EPC_QOS_UPDATE)) { /* Update QER */ i = 0; if (qos_flow->qer) { @@ -382,7 +387,11 @@ ogs_pkbuf_t *smf_n4_build_qos_flow_modification_request( pfcp_message.h.type = type; pkbuf = ogs_pfcp_build_msg(&pfcp_message); - if (modify_flags & (OGS_PFCP_MODIFY_CREATE|OGS_PFCP_MODIFY_TFT_UPDATE)) { + if (modify_flags & + (OGS_PFCP_MODIFY_CREATE| + OGS_PFCP_MODIFY_TFT_NEW|OGS_PFCP_MODIFY_TFT_ADD| + OGS_PFCP_MODIFY_TFT_REPLACE|OGS_PFCP_MODIFY_TFT_DELETE| + OGS_PFCP_MODIFY_EPC_TFT_UPDATE)) { ogs_pfcp_pdrbuf_clear(); } diff --git a/src/smf/n4-handler.c b/src/smf/n4-handler.c index 9c7f0fc72..45b293ff3 100644 --- a/src/smf/n4-handler.c +++ b/src/smf/n4-handler.c @@ -408,6 +408,49 @@ void smf_5gc_n4_handle_session_modification_response( smf_sbi_send_sm_context_updated_data_ho_state( sess, stream, OpenAPI_ho_state_CANCELLED); } + } else if (flags & OGS_PFCP_MODIFY_NETWORK_REQUESTED) { + smf_n1_n2_message_transfer_param_t param; + + memset(¶m, 0, sizeof(param)); + param.state = SMF_NETWORK_REQUESTED_QOS_FLOW_MODIFICATION; + param.n1smbuf = gsm_build_qos_flow_modification_command( + qos_flow, + OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED, + OGS_NAS_QOS_CODE_DELETE_EXISTING_QOS_RULE, + OGS_NAS_DELETE_NEW_QOS_FLOW_DESCRIPTION); + ogs_assert(param.n1smbuf); + param.n2smbuf = + ngap_build_qos_flow_resource_release_request_transfer( + qos_flow, + NGAP_Cause_PR_nas, NGAP_CauseNas_normal_release); + ogs_assert(param.n2smbuf); + + smf_namf_comm_send_n1_n2_message_transfer(sess, ¶m); + + smf_bearer_remove(qos_flow); + } else if (flags & OGS_PFCP_MODIFY_UE_REQUESTED) { + ogs_pkbuf_t *n1smbuf = NULL, *n2smbuf = NULL; + + ogs_assert(stream); + + n1smbuf = gsm_build_qos_flow_modification_command( + qos_flow, sess->pti, + OGS_NAS_QOS_CODE_DELETE_EXISTING_QOS_RULE, + OGS_NAS_DELETE_NEW_QOS_FLOW_DESCRIPTION); + ogs_assert(n1smbuf); + + n2smbuf = ngap_build_qos_flow_resource_release_request_transfer( + qos_flow, + NGAP_Cause_PR_nas, NGAP_CauseNas_normal_release); + ogs_assert(n2smbuf); + + smf_sbi_send_sm_context_updated_data_n1_n2_message(sess, stream, + n1smbuf, OpenAPI_n2_sm_info_type_PDU_RES_MOD_REQ, n2smbuf); + + smf_bearer_remove(qos_flow); + } else { + ogs_fatal("Unknown flags [0x%llx]", (long long)flags); + ogs_assert_if_reached(); } } else if (flags & OGS_PFCP_MODIFY_CREATE) { if (flags & OGS_PFCP_MODIFY_INDIRECT) { @@ -418,19 +461,89 @@ void smf_5gc_n4_handle_session_modification_response( sess, stream, 0, OpenAPI_ho_state_PREPARED, NULL, OpenAPI_n2_sm_info_type_HANDOVER_CMD, n2smbuf); - } else { + } else if (flags & OGS_PFCP_MODIFY_NETWORK_REQUESTED) { smf_n1_n2_message_transfer_param_t param; memset(¶m, 0, sizeof(param)); param.state = SMF_NETWORK_REQUESTED_QOS_FLOW_MODIFICATION; - param.n1smbuf = gsm_build_qos_flow_modification_command(qos_flow, - OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED); + param.n1smbuf = gsm_build_qos_flow_modification_command( + qos_flow, + OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED, + OGS_NAS_QOS_CODE_CREATE_NEW_QOS_RULE, + OGS_NAS_CREATE_NEW_QOS_FLOW_DESCRIPTION); ogs_assert(param.n1smbuf); param.n2smbuf = - ngap_build_qos_flow_resource_modify_request_transfer(qos_flow); + ngap_build_qos_flow_resource_modify_request_transfer( + qos_flow, true); ogs_assert(param.n2smbuf); smf_namf_comm_send_n1_n2_message_transfer(sess, ¶m); + } else { + ogs_fatal("Unknown flags [0x%llx]", (long long)flags); + ogs_assert_if_reached(); + } + } else if (flags & + (OGS_PFCP_MODIFY_TFT_NEW|OGS_PFCP_MODIFY_TFT_ADD| + OGS_PFCP_MODIFY_TFT_REPLACE|OGS_PFCP_MODIFY_TFT_DELETE| + OGS_PFCP_MODIFY_QOS_MODIFY)) { + smf_n1_n2_message_transfer_param_t param; + + uint8_t qos_rule_code = 0; + uint8_t qos_flow_description_code = 0; + + if (flags & OGS_PFCP_MODIFY_TFT_NEW) { + qos_rule_code = OGS_NAS_QOS_CODE_CREATE_NEW_QOS_RULE; + } else if (flags & OGS_PFCP_MODIFY_TFT_ADD) { + qos_rule_code = OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_ADD_PACKET_FILTERS; + } else if (flags & OGS_PFCP_MODIFY_TFT_REPLACE) { + qos_rule_code = OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_REPLACE_PACKET_FILTERS; + } else if (flags & OGS_PFCP_MODIFY_TFT_DELETE) { + qos_rule_code = OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_DELETE_PACKET_FILTERS; + } + + if (flags & OGS_PFCP_MODIFY_QOS_CREATE) { + ogs_assert_if_reached(); + } else if (flags & OGS_PFCP_MODIFY_QOS_MODIFY) { + qos_flow_description_code = OGS_NAS_MODIFY_NEW_QOS_FLOW_DESCRIPTION; + } else if (flags & OGS_PFCP_MODIFY_QOS_DELETE) { + ogs_assert_if_reached(); + } + + if (flags & OGS_PFCP_MODIFY_NETWORK_REQUESTED) { + memset(¶m, 0, sizeof(param)); + param.state = SMF_NETWORK_REQUESTED_QOS_FLOW_MODIFICATION; + param.n1smbuf = gsm_build_qos_flow_modification_command( + qos_flow, + OGS_NAS_PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED, + qos_rule_code, qos_flow_description_code); + ogs_assert(param.n1smbuf); + param.n2smbuf = + ngap_build_qos_flow_resource_modify_request_transfer( + qos_flow, + (flags & OGS_PFCP_MODIFY_QOS_MODIFY) ? true : false); + ogs_assert(param.n2smbuf); + + smf_namf_comm_send_n1_n2_message_transfer(sess, ¶m); + } else if (flags & OGS_PFCP_MODIFY_UE_REQUESTED) { + ogs_pkbuf_t *n1smbuf = NULL, *n2smbuf = NULL; + + ogs_assert(stream); + + n1smbuf = gsm_build_qos_flow_modification_command( + qos_flow, sess->pti, + qos_rule_code, qos_flow_description_code); + ogs_assert(n1smbuf); + + n2smbuf = ngap_build_qos_flow_resource_modify_request_transfer( + qos_flow, + (flags & OGS_PFCP_MODIFY_QOS_MODIFY) ? true : false); + ogs_assert(n2smbuf); + + smf_sbi_send_sm_context_updated_data_n1_n2_message(sess, stream, + n1smbuf, OpenAPI_n2_sm_info_type_PDU_RES_MOD_REQ, n2smbuf); + } else { + ogs_fatal("Unknown flags [0x%llx]", (long long)flags); + ogs_assert_if_reached(); } } } @@ -451,7 +564,6 @@ void smf_5gc_n4_handle_session_deletion_response( ogs_assert(rsp); stream = xact->assoc_stream; - ogs_assert(stream); trigger = xact->delete_trigger; ogs_assert(trigger); @@ -477,13 +589,30 @@ void smf_5gc_n4_handle_session_deletion_response( if (status != OGS_SBI_HTTP_STATUS_OK) { char *strerror = ogs_msprintf( "PFCP Cause [%d] : Not Accepted", rsp->cause.u8); - smf_sbi_send_sm_context_update_error( + + if (trigger == OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED || + trigger == OGS_PFCP_DELETE_TRIGGER_AMF_UPDATE_SM_CONTEXT) { + ogs_assert(stream); + smf_sbi_send_sm_context_update_error( stream, status, strerror, NULL, NULL, NULL); + } else if (trigger == OGS_PFCP_DELETE_TRIGGER_AMF_RELEASE_SM_CONTEXT) { + ogs_assert(stream); + ogs_assert(true == + ogs_sbi_server_send_error( + stream, status, NULL, strerror, NULL)); + } else if (trigger == OGS_PFCP_DELETE_TRIGGER_PCF_INITIATED) { + /* No stream - Nothing */ + } else { + ogs_fatal("Unknown trigger [%d]", trigger); + ogs_assert_if_reached(); + } + ogs_error("%s", strerror); ogs_free(strerror); return; } + ogs_assert(sess); if (trigger == OGS_PFCP_DELETE_TRIGGER_UE_REQUESTED) { @@ -498,17 +627,38 @@ void smf_5gc_n4_handle_session_deletion_response( NGAP_Cause_PR_nas, NGAP_CauseNas_normal_release); ogs_assert(n2smbuf); + ogs_assert(stream); smf_sbi_send_sm_context_updated_data_n1_n2_message(sess, stream, n1smbuf, OpenAPI_n2_sm_info_type_PDU_RES_REL_CMD, n2smbuf); - } else { + } else if (trigger == OGS_PFCP_DELETE_TRIGGER_AMF_UPDATE_SM_CONTEXT || + trigger == OGS_PFCP_DELETE_TRIGGER_AMF_RELEASE_SM_CONTEXT) { memset(&sendmsg, 0, sizeof(sendmsg)); response = ogs_sbi_build_response( &sendmsg, OGS_SBI_HTTP_STATUS_NO_CONTENT); ogs_assert(response); + + ogs_assert(stream); ogs_assert(true == ogs_sbi_server_send_response(stream, response)); SMF_SESS_CLEAR(sess); + } else if (trigger == OGS_PFCP_DELETE_TRIGGER_PCF_INITIATED) { + smf_n1_n2_message_transfer_param_t param; + + memset(¶m, 0, sizeof(param)); + param.state = SMF_NETWORK_REQUESTED_PDU_SESSION_RELEASE; + param.n2smbuf = + ngap_build_pdu_session_resource_release_command_transfer( + sess, SMF_NGAP_STATE_DELETE_TRIGGER_PCF_INITIATED, + NGAP_Cause_PR_nas, NGAP_CauseNas_normal_release); + ogs_assert(param.n2smbuf); + + param.skip_ind = true; + + smf_namf_comm_send_n1_n2_message_transfer(sess, ¶m); + } else { + ogs_fatal("Unknown trigger [%d]", trigger); + ogs_assert_if_reached(); } } diff --git a/src/smf/namf-build.c b/src/smf/namf-build.c index 3cfe4bd42..aee01936f 100644 --- a/src/smf/namf-build.c +++ b/src/smf/namf-build.c @@ -105,6 +105,7 @@ ogs_sbi_request_t *smf_namf_comm_build_n1_n2_message_transfer( case SMF_NETWORK_REQUESTED_QOS_FLOW_MODIFICATION: n2InfoContent.ngap_ie_type = OpenAPI_ngap_ie_type_PDU_RES_MOD_REQ; break; + case SMF_NETWORK_REQUESTED_PDU_SESSION_RELEASE: case SMF_ERROR_INDICATON_RECEIVED_FROM_5G_AN: n2InfoContent.ngap_ie_type = OpenAPI_ngap_ie_type_PDU_RES_REL_CMD; break; diff --git a/src/smf/namf-build.h b/src/smf/namf-build.h index e2ede5e72..448b596bb 100644 --- a/src/smf/namf-build.h +++ b/src/smf/namf-build.h @@ -31,8 +31,9 @@ typedef struct smf_n1_n2_message_transfer_param_s { #define SMF_UE_REQUESTED_PDU_SESSION_ESTABLISHMENT 1 #define SMF_NETWORK_REQUESTED_PDU_SESSION_MODIFICATION 2 #define SMF_NETWORK_REQUESTED_QOS_FLOW_MODIFICATION 3 -#define SMF_NETWORK_TRIGGERED_SERVICE_REQUEST 4 -#define SMF_ERROR_INDICATON_RECEIVED_FROM_5G_AN 5 +#define SMF_NETWORK_REQUESTED_PDU_SESSION_RELEASE 4 +#define SMF_NETWORK_TRIGGERED_SERVICE_REQUEST 5 +#define SMF_ERROR_INDICATON_RECEIVED_FROM_5G_AN 6 int state; ogs_pkbuf_t *n1smbuf; diff --git a/src/smf/namf-handler.c b/src/smf/namf-handler.c index 62544a207..0443ec72a 100644 --- a/src/smf/namf-handler.c +++ b/src/smf/namf-handler.c @@ -22,7 +22,7 @@ #include "binding.h" #include "namf-handler.h" -bool smf_namf_comm_handler_n1_n2_message_transfer( +bool smf_namf_comm_handle_n1_n2_message_transfer( smf_sess_t *sess, int state, ogs_sbi_message_t *recvmsg) { smf_ue_t *smf_ue = NULL; @@ -37,16 +37,7 @@ bool smf_namf_comm_handler_n1_n2_message_transfer( switch (state) { case SMF_UE_REQUESTED_PDU_SESSION_ESTABLISHMENT: if (recvmsg->res_status == OGS_SBI_HTTP_STATUS_OK) { - smf_qos_flow_binding(sess, NULL); - } else { - ogs_error("[%s:%d] HTTP response error [%d]", - smf_ue->supi, sess->psi, recvmsg->res_status); - } - break; - - case SMF_NETWORK_REQUESTED_QOS_FLOW_MODIFICATION: - if (recvmsg->res_status == OGS_SBI_HTTP_STATUS_OK) { - /* Nothing */ + smf_qos_flow_binding(sess); } else { ogs_error("[%s:%d] HTTP response error [%d]", smf_ue->supi, sess->psi, recvmsg->res_status); @@ -54,6 +45,7 @@ bool smf_namf_comm_handler_n1_n2_message_transfer( break; case SMF_NETWORK_TRIGGERED_SERVICE_REQUEST: + case SMF_NETWORK_REQUESTED_QOS_FLOW_MODIFICATION: N1N2MessageTransferRspData = recvmsg->N1N2MessageTransferRspData; if (!N1N2MessageTransferRspData) { ogs_error("No N1N2MessageTransferRspData [status:%d]", @@ -112,6 +104,7 @@ bool smf_namf_comm_handler_n1_n2_message_transfer( } break; + case SMF_NETWORK_REQUESTED_PDU_SESSION_RELEASE: case SMF_ERROR_INDICATON_RECEIVED_FROM_5G_AN: N1N2MessageTransferRspData = recvmsg->N1N2MessageTransferRspData; if (!N1N2MessageTransferRspData) { @@ -158,7 +151,7 @@ bool smf_namf_comm_handler_n1_n2_message_transfer( return true; } -bool smf_namf_comm_handler_n1_n2_message_transfer_failure_notify( +bool smf_namf_comm_handle_n1_n2_message_transfer_failure_notify( ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg) { OpenAPI_n1_n2_msg_txfr_failure_notification_t diff --git a/src/smf/namf-handler.h b/src/smf/namf-handler.h index 844ecfcec..87acf4abe 100644 --- a/src/smf/namf-handler.h +++ b/src/smf/namf-handler.h @@ -26,10 +26,10 @@ extern "C" { #include "context.h" -bool smf_namf_comm_handler_n1_n2_message_transfer( +bool smf_namf_comm_handle_n1_n2_message_transfer( smf_sess_t *sess, int state, ogs_sbi_message_t *recvmsg); -bool smf_namf_comm_handler_n1_n2_message_transfer_failure_notify( +bool smf_namf_comm_handle_n1_n2_message_transfer_failure_notify( ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg); #ifdef __cplusplus diff --git a/src/smf/ngap-build.c b/src/smf/ngap-build.c index 901624d82..e15f05f04 100644 --- a/src/smf/ngap-build.c +++ b/src/smf/ngap-build.c @@ -200,7 +200,7 @@ ogs_pkbuf_t *ngap_build_pdu_session_resource_setup_request_transfer( } ogs_pkbuf_t *ngap_build_qos_flow_resource_modify_request_transfer( - smf_bearer_t *qos_flow) + smf_bearer_t *qos_flow, bool qos_presence) { NGAP_PDUSessionResourceModifyRequestTransfer_t message; @@ -262,8 +262,9 @@ ogs_pkbuf_t *ngap_build_qos_flow_resource_modify_request_transfer( allocationAndRetentionPriority->pre_emptionVulnerability = NGAP_Pre_emptionVulnerability_pre_emptable; - if (qos_flow->qos.mbr.downlink || qos_flow->qos.mbr.uplink || - qos_flow->qos.gbr.downlink || qos_flow->qos.gbr.uplink) { + if (qos_presence == true && + (qos_flow->qos.mbr.downlink || qos_flow->qos.mbr.uplink || + qos_flow->qos.gbr.downlink || qos_flow->qos.gbr.uplink)) { ogs_assert(qos_flow->qos.mbr.downlink); ogs_assert(qos_flow->qos.mbr.uplink); ogs_assert(qos_flow->qos.gbr.downlink); @@ -286,6 +287,47 @@ ogs_pkbuf_t *ngap_build_qos_flow_resource_modify_request_transfer( &asn_DEF_NGAP_PDUSessionResourceModifyRequestTransfer, &message); } +ogs_pkbuf_t *ngap_build_qos_flow_resource_release_request_transfer( + smf_bearer_t *qos_flow, NGAP_Cause_PR group, long cause) +{ + NGAP_PDUSessionResourceModifyRequestTransfer_t message; + + NGAP_PDUSessionResourceModifyRequestTransferIEs_t *ie = NULL; + + NGAP_QosFlowListWithCause_t *QosFlowListWithCause = NULL; + NGAP_QosFlowWithCauseItem_t *QosFlowWithCauseItem = NULL; + NGAP_QosFlowIdentifier_t *qosFlowIdentifier = NULL; + NGAP_Cause_t *Cause = NULL; + + ogs_assert(qos_flow); + + ogs_debug("PDUSessionResourceModifyRequestTransfer"); + memset(&message, 0, sizeof(NGAP_PDUSessionResourceModifyRequestTransfer_t)); + + ie = CALLOC(1, sizeof(NGAP_PDUSessionResourceModifyRequestTransferIEs_t)); + ASN_SEQUENCE_ADD(&message.protocolIEs, ie); + + ie->id = NGAP_ProtocolIE_ID_id_QosFlowToReleaseList; + ie->criticality = NGAP_Criticality_reject; + ie->value.present = NGAP_PDUSessionResourceModifyRequestTransferIEs__value_PR_QosFlowListWithCause; + + QosFlowListWithCause = &ie->value.choice.QosFlowListWithCause; + + QosFlowWithCauseItem = CALLOC(1, sizeof(*QosFlowWithCauseItem)); + ASN_SEQUENCE_ADD(&QosFlowListWithCause->list, QosFlowWithCauseItem); + + qosFlowIdentifier = &QosFlowWithCauseItem->qosFlowIdentifier; + + *qosFlowIdentifier = qos_flow->qfi; + + Cause = &QosFlowWithCauseItem->cause; + Cause->present = group; + Cause->choice.radioNetwork = cause; + + return ogs_asn_encode( + &asn_DEF_NGAP_PDUSessionResourceModifyRequestTransfer, &message); +} + ogs_pkbuf_t *ngap_build_pdu_session_resource_release_command_transfer( smf_sess_t *sess, int state, NGAP_Cause_PR group, long cause) { diff --git a/src/smf/ngap-build.h b/src/smf/ngap-build.h index a9cd7821f..e6ec80e87 100644 --- a/src/smf/ngap-build.h +++ b/src/smf/ngap-build.h @@ -30,7 +30,10 @@ ogs_pkbuf_t *ngap_build_pdu_session_resource_setup_request_transfer( smf_sess_t *sess); ogs_pkbuf_t *ngap_build_qos_flow_resource_modify_request_transfer( - smf_bearer_t *qos_flow); + smf_bearer_t *qos_flow, bool qos_presence); + +ogs_pkbuf_t *ngap_build_qos_flow_resource_release_request_transfer( + smf_bearer_t *qos_flow, NGAP_Cause_PR group, long cause); ogs_pkbuf_t *ngap_build_pdu_session_resource_release_command_transfer( smf_sess_t *sess, int state, NGAP_Cause_PR group, long cause); diff --git a/src/smf/ngap-handler.c b/src/smf/ngap-handler.c index bb35d822e..369ea9975 100644 --- a/src/smf/ngap-handler.c +++ b/src/smf/ngap-handler.c @@ -192,6 +192,15 @@ int ngap_handle_pdu_session_resource_modify_response_transfer( rv = OGS_ERROR; qosFlowAddOrModifyResponseList = message.qosFlowAddOrModifyResponseList; + if (!qosFlowAddOrModifyResponseList) { + /* QosFlow Release */ + rv = OGS_OK; + + ogs_assert(true == ogs_sbi_send_http_status_no_content(stream)); + + goto cleanup; + } + if (qosFlowAddOrModifyResponseList) { for (i = 0; i < qosFlowAddOrModifyResponseList->list.count; i++) { NGAP_QosFlowAddOrModifyResponseItem_t diff --git a/src/smf/npcf-handler.c b/src/smf/npcf-handler.c index 6029955aa..12d83bab3 100644 --- a/src/smf/npcf-handler.c +++ b/src/smf/npcf-handler.c @@ -17,190 +17,88 @@ * along with this program. If not, see . */ -#include "npcf-handler.h" - #include "sbi-path.h" #include "pfcp-path.h" #include "nas-path.h" +#include "binding.h" -bool smf_npcf_smpolicycontrol_handle_create( - smf_sess_t *sess, ogs_sbi_stream_t *stream, int state, - ogs_sbi_message_t *recvmsg) +#include "npcf-handler.h" + +static void update_authorized_pcc_rule_and_qos( + smf_sess_t *sess, OpenAPI_sm_policy_decision_t *SmPolicyDecision) { - int rv; - char buf1[OGS_ADDRSTRLEN]; - char buf2[OGS_ADDRSTRLEN]; - - uint64_t supported_features; - - char *strerror = NULL; - smf_ue_t *smf_ue = NULL; - - smf_bearer_t *qos_flow = NULL; - ogs_pfcp_pdr_t *dl_pdr = NULL; - ogs_pfcp_pdr_t *ul_pdr = NULL; - ogs_pfcp_pdr_t *cp2up_pdr = NULL; - ogs_pfcp_pdr_t *up2cp_pdr = NULL; - ogs_pfcp_far_t *up2cp_far = NULL; - ogs_pfcp_qer_t *qer = NULL; - - OpenAPI_sm_policy_decision_t *SmPolicyDecision = NULL; OpenAPI_lnode_t *node = NULL, *node2 = NULL; -#define MAX_TRIGGER_ID 128 - bool trigger_results[MAX_TRIGGER_ID]; - - ogs_sbi_message_t message; - ogs_sbi_header_t header; - ogs_assert(sess); - ogs_assert(stream); - smf_ue = sess->smf_ue; - ogs_assert(smf_ue); + ogs_assert(SmPolicyDecision); - ogs_assert(recvmsg); + /* + * TS29.512 + * 4.2.6 Provisioning and Enforcement of Policy Decisions + * + * + * If no other rules are defined for specific data types + * within the SmPolicyDecision data structure, the encoding of changes + * of the policies decisions in the SmPolicyDecision data structure + * shall follow the following principles: + * + * 1) To modify an attribute with a value of type map + * (e.g. the "sessRules" attribute, the "pccRules" attribute, + * the "qosDecs" attribute, the "traffContDecs" attribute, + * the "umDecs" attribute, and the "conds" attribute) the attribute + * shall be provided with a value containing a map with entries + * according to the following principles: + * + * - A new entry shall be added by supplying a new identifier + * (e.g. rule / decision identifier) as key and the corresponding + * structured data type instance (e.g. PCC rule) with complete contents + * as value as an entry within the map. + * - An existing entry shall be modified by supplying the existing + * identifier as key and the corresponding structured data type instance + * with the same existing identifier (e.g. set the "qosId" + * to the same existing QoS data decision identifier), + * which shall describe the modifications following bullets 1 to 6, + * as value as an entry within the map. + * - An existing entry shall be deleted by supplying the existing + * identifier as key and "NULL" as value as an entry within the map. + * - For an unmodified entry, no entry needs to be provided within the map. + * + * 2) To modify an attribute with a structured data type instance as value, + * the attribute shall be provided with a value containing a structured data + * type instance with entries according to bullets 1 to 6. + * + * 3) To modify an attribute with another type than map or structured data + * type as value, the attribute shall be provided with a complete + * representation of its value that shall replace the previous value. + * + * 4) To create an attribute of any type, the attribute shall be provided + * with a complete representation of its value. + * + * 5) To delete an attribute of any type, the attribute shall be provided + * with NULL as value. + * NOTE 1: Attributes that are allowed to be deleted need to be marked as + * "nullable" within the OpenAPI file in Annex A. + * + * 6) Attributes that are not added, modified, or deleted do not need to be + * provided. + * NOTE 2: In related data structures no attrib + */ - if (!recvmsg->http.location) { - strerror = ogs_msprintf("[%s:%d] No http.location", - smf_ue->supi, sess->psi); - goto cleanup; - } - - SmPolicyDecision = recvmsg->SmPolicyDecision; - if (!SmPolicyDecision) { - strerror = ogs_msprintf("[%s:%d] No SmPolicyDecision", - smf_ue->supi, sess->psi); - goto cleanup; - } - - memset(&header, 0, sizeof(header)); - header.uri = recvmsg->http.location; - - rv = ogs_sbi_parse_header(&message, &header); - if (rv != OGS_OK) { - strerror = ogs_msprintf("[%s:%d] Cannot parse http.location [%s]", - smf_ue->supi, sess->psi, recvmsg->http.location); - goto cleanup; - } - - if (!message.h.resource.component[1]) { - strerror = ogs_msprintf("[%s:%d] No Assocication ID [%s]", - smf_ue->supi, sess->psi, recvmsg->http.location); - - ogs_sbi_header_free(&header); - goto cleanup; - } - - if (sess->policy_association_id) - ogs_free(sess->policy_association_id); - sess->policy_association_id = ogs_strdup(message.h.resource.component[1]); - ogs_assert(sess->policy_association_id); - - ogs_sbi_header_free(&header); - - /* SBI Features */ - if (SmPolicyDecision->supp_feat) { - supported_features = - ogs_uint64_from_string(SmPolicyDecision->supp_feat); - sess->smpolicycontrol_features &= supported_features; - } else { - sess->smpolicycontrol_features = 0; - } - - /********************************************************************* - * Handle Policy Control Request Triggers - *********************************************************************/ - - /* Get policy control request triggers */ - memset(&trigger_results, 0, sizeof(trigger_results)); - OpenAPI_list_for_each(SmPolicyDecision->policy_ctrl_req_triggers, node) { - if (node->data) { - OpenAPI_policy_control_request_trigger_e trigger_id = - (intptr_t)node->data; - - ogs_assert(trigger_id < MAX_TRIGGER_ID); - trigger_results[trigger_id] = true; - } - } - - /* Update authorized session-AMBR */ - if (SmPolicyDecision->sess_rules) { - OpenAPI_map_t *SessRuleMap = NULL; - OpenAPI_session_rule_t *SessionRule = NULL; - - OpenAPI_ambr_t *AuthSessAmbr = NULL; - OpenAPI_authorized_default_qos_t *AuthDefQos = NULL; - - OpenAPI_list_for_each(SmPolicyDecision->sess_rules, node) { - SessRuleMap = node->data; - if (!SessRuleMap) { - ogs_error("No SessRuleMap"); - continue; - } - - SessionRule = SessRuleMap->value; - if (!SessionRule) { - ogs_error("No SessionRule"); - continue; - } - - - AuthSessAmbr = SessionRule->auth_sess_ambr; - if (AuthSessAmbr && trigger_results[ - OpenAPI_policy_control_request_trigger_SE_AMBR_CH] == true) { - if (AuthSessAmbr->uplink) - sess->session.ambr.uplink = - ogs_sbi_bitrate_from_string(AuthSessAmbr->uplink); - if (AuthSessAmbr->downlink) - sess->session.ambr.downlink = - ogs_sbi_bitrate_from_string(AuthSessAmbr->downlink); - } - - AuthDefQos = SessionRule->auth_def_qos; - if (AuthDefQos && trigger_results[ - OpenAPI_policy_control_request_trigger_DEF_QOS_CH] == true) { - sess->session.qos.index = AuthDefQos->_5qi; - sess->session.qos.arp.priority_level = - AuthDefQos->priority_level; - if (AuthDefQos->arp) { - sess->session.qos.arp.priority_level = - AuthDefQos->arp->priority_level; - if (AuthDefQos->arp->preempt_cap == - OpenAPI_preemption_capability_NOT_PREEMPT) - sess->session.qos.arp.pre_emption_capability = - OGS_5GC_PRE_EMPTION_DISABLED; - else if (AuthDefQos->arp->preempt_cap == - OpenAPI_preemption_capability_MAY_PREEMPT) - sess->session.qos.arp.pre_emption_capability = - OGS_5GC_PRE_EMPTION_ENABLED; - ogs_assert(sess->session.qos.arp.pre_emption_capability); - - if (AuthDefQos->arp->preempt_vuln == - OpenAPI_preemption_vulnerability_NOT_PREEMPTABLE) - sess->session.qos.arp.pre_emption_vulnerability = - OGS_5GC_PRE_EMPTION_DISABLED; - else if (AuthDefQos->arp->preempt_vuln == - OpenAPI_preemption_vulnerability_PREEMPTABLE) - sess->session.qos.arp.pre_emption_vulnerability = - OGS_5GC_PRE_EMPTION_ENABLED; - ogs_assert(sess->session.qos.arp.pre_emption_vulnerability); - } - } - } - } - - /* Update authorized PCC rule & QoS */ if (SmPolicyDecision->pcc_rules) { OpenAPI_map_t *PccRuleMap = NULL; OpenAPI_pcc_rule_t *PccRule = NULL; OpenAPI_flow_information_t *FlowInformation = NULL; OpenAPI_qos_data_t *QosData = NULL; char *QosId = NULL; + int i; + + for (i = 0; i < sess->policy.num_of_pcc_rule; i++) + OGS_PCC_RULE_FREE(&sess->policy.pcc_rule[i]); + sess->policy.num_of_pcc_rule = 0; - ogs_assert(sess->num_of_pcc_rule == 0); OpenAPI_list_for_each(SmPolicyDecision->pcc_rules, node) { - ogs_pcc_rule_t *pcc_rule = &sess->pcc_rule[sess->num_of_pcc_rule]; - + ogs_pcc_rule_t *pcc_rule = + &sess->policy.pcc_rule[sess->policy.num_of_pcc_rule]; ogs_assert(pcc_rule); PccRuleMap = node->data; @@ -209,9 +107,18 @@ bool smf_npcf_smpolicycontrol_handle_create( continue; } + if (!PccRuleMap->key) { + ogs_error("No PccRule->id"); + continue; + } + PccRule = PccRuleMap->value; if (!PccRule) { - ogs_error("No PccRule"); + pcc_rule->type = OGS_PCC_RULE_TYPE_REMOVE; + pcc_rule->id = ogs_strdup(PccRuleMap->key); + ogs_assert(pcc_rule->id); + + sess->policy.num_of_pcc_rule++; continue; } @@ -356,9 +263,179 @@ bool smf_npcf_smpolicycontrol_handle_create( pcc_rule->qos.gbr.uplink = MAX_BIT_RATE; } - sess->num_of_pcc_rule++; + sess->policy.num_of_pcc_rule++; } } +} + +bool smf_npcf_smpolicycontrol_handle_create( + smf_sess_t *sess, ogs_sbi_stream_t *stream, int state, + ogs_sbi_message_t *recvmsg) +{ + int rv; + char buf1[OGS_ADDRSTRLEN]; + char buf2[OGS_ADDRSTRLEN]; + + uint64_t supported_features; + + char *strerror = NULL; + smf_ue_t *smf_ue = NULL; + + smf_bearer_t *qos_flow = NULL; + ogs_pfcp_pdr_t *dl_pdr = NULL; + ogs_pfcp_pdr_t *ul_pdr = NULL; + ogs_pfcp_pdr_t *cp2up_pdr = NULL; + ogs_pfcp_pdr_t *up2cp_pdr = NULL; + ogs_pfcp_far_t *up2cp_far = NULL; + ogs_pfcp_qer_t *qer = NULL; + + OpenAPI_sm_policy_decision_t *SmPolicyDecision = NULL; + OpenAPI_lnode_t *node = NULL; + +#define MAX_TRIGGER_ID 128 + bool trigger_results[MAX_TRIGGER_ID]; + + ogs_sbi_message_t message; + ogs_sbi_header_t header; + + ogs_assert(sess); + ogs_assert(stream); + smf_ue = sess->smf_ue; + ogs_assert(smf_ue); + + ogs_assert(recvmsg); + + if (!recvmsg->http.location) { + strerror = ogs_msprintf("[%s:%d] No http.location", + smf_ue->supi, sess->psi); + goto cleanup; + } + + SmPolicyDecision = recvmsg->SmPolicyDecision; + if (!SmPolicyDecision) { + strerror = ogs_msprintf("[%s:%d] No SmPolicyDecision", + smf_ue->supi, sess->psi); + goto cleanup; + } + + memset(&header, 0, sizeof(header)); + header.uri = recvmsg->http.location; + + rv = ogs_sbi_parse_header(&message, &header); + if (rv != OGS_OK) { + strerror = ogs_msprintf("[%s:%d] Cannot parse http.location [%s]", + smf_ue->supi, sess->psi, recvmsg->http.location); + goto cleanup; + } + + if (!message.h.resource.component[1]) { + strerror = ogs_msprintf("[%s:%d] No Assocication ID [%s]", + smf_ue->supi, sess->psi, recvmsg->http.location); + + ogs_sbi_header_free(&header); + goto cleanup; + } + + if (sess->policy_association_id) + ogs_free(sess->policy_association_id); + sess->policy_association_id = ogs_strdup(message.h.resource.component[1]); + ogs_assert(sess->policy_association_id); + + ogs_sbi_header_free(&header); + + /* SBI Features */ + if (SmPolicyDecision->supp_feat) { + supported_features = + ogs_uint64_from_string(SmPolicyDecision->supp_feat); + sess->smpolicycontrol_features &= supported_features; + } else { + sess->smpolicycontrol_features = 0; + } + + /********************************************************************* + * Handle Policy Control Request Triggers + *********************************************************************/ + + /* Get policy control request triggers */ + memset(&trigger_results, 0, sizeof(trigger_results)); + OpenAPI_list_for_each(SmPolicyDecision->policy_ctrl_req_triggers, node) { + if (node->data) { + OpenAPI_policy_control_request_trigger_e trigger_id = + (intptr_t)node->data; + + ogs_assert(trigger_id < MAX_TRIGGER_ID); + trigger_results[trigger_id] = true; + } + } + + /* Update authorized session-AMBR */ + if (SmPolicyDecision->sess_rules) { + OpenAPI_map_t *SessRuleMap = NULL; + OpenAPI_session_rule_t *SessionRule = NULL; + + OpenAPI_ambr_t *AuthSessAmbr = NULL; + OpenAPI_authorized_default_qos_t *AuthDefQos = NULL; + + OpenAPI_list_for_each(SmPolicyDecision->sess_rules, node) { + SessRuleMap = node->data; + if (!SessRuleMap) { + ogs_error("No SessRuleMap"); + continue; + } + + SessionRule = SessRuleMap->value; + if (!SessionRule) { + ogs_error("No SessionRule"); + continue; + } + + + AuthSessAmbr = SessionRule->auth_sess_ambr; + if (AuthSessAmbr && trigger_results[ + OpenAPI_policy_control_request_trigger_SE_AMBR_CH] == true) { + if (AuthSessAmbr->uplink) + sess->session.ambr.uplink = + ogs_sbi_bitrate_from_string(AuthSessAmbr->uplink); + if (AuthSessAmbr->downlink) + sess->session.ambr.downlink = + ogs_sbi_bitrate_from_string(AuthSessAmbr->downlink); + } + + AuthDefQos = SessionRule->auth_def_qos; + if (AuthDefQos && trigger_results[ + OpenAPI_policy_control_request_trigger_DEF_QOS_CH] == true) { + sess->session.qos.index = AuthDefQos->_5qi; + sess->session.qos.arp.priority_level = + AuthDefQos->priority_level; + if (AuthDefQos->arp) { + sess->session.qos.arp.priority_level = + AuthDefQos->arp->priority_level; + if (AuthDefQos->arp->preempt_cap == + OpenAPI_preemption_capability_NOT_PREEMPT) + sess->session.qos.arp.pre_emption_capability = + OGS_5GC_PRE_EMPTION_DISABLED; + else if (AuthDefQos->arp->preempt_cap == + OpenAPI_preemption_capability_MAY_PREEMPT) + sess->session.qos.arp.pre_emption_capability = + OGS_5GC_PRE_EMPTION_ENABLED; + ogs_assert(sess->session.qos.arp.pre_emption_capability); + + if (AuthDefQos->arp->preempt_vuln == + OpenAPI_preemption_vulnerability_NOT_PREEMPTABLE) + sess->session.qos.arp.pre_emption_vulnerability = + OGS_5GC_PRE_EMPTION_DISABLED; + else if (AuthDefQos->arp->preempt_vuln == + OpenAPI_preemption_vulnerability_PREEMPTABLE) + sess->session.qos.arp.pre_emption_vulnerability = + OGS_5GC_PRE_EMPTION_ENABLED; + ogs_assert(sess->session.qos.arp.pre_emption_vulnerability); + } + } + } + } + + /* Update authorized PCC rule & QoS */ + update_authorized_pcc_rule_and_qos(sess, SmPolicyDecision); /********************************************************************* * Send PFCP Session Establiashment Request to the UPF @@ -533,3 +610,78 @@ bool smf_npcf_smpolicycontrol_handle_delete( return true; } + +bool smf_npcf_smpolicycontrol_handle_update_notify( + smf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg) +{ + char *strerror = NULL; + smf_ue_t *smf_ue = NULL; + + OpenAPI_sm_policy_notification_t *SmPolicyNotification = NULL; + OpenAPI_sm_policy_decision_t *SmPolicyDecision = NULL; + + ogs_assert(sess); + ogs_assert(stream); + smf_ue = sess->smf_ue; + ogs_assert(smf_ue); + + ogs_assert(recvmsg); + + SmPolicyNotification = recvmsg->SmPolicyNotification; + if (!SmPolicyNotification) { + strerror = ogs_msprintf("[%s:%d] No SmPolicyNotification", + smf_ue->supi, sess->psi); + goto cleanup; + } + + SmPolicyDecision = SmPolicyNotification->sm_policy_decision; + if (!SmPolicyDecision) { + strerror = ogs_msprintf("[%s:%d] No SmPolicyDecision", + smf_ue->supi, sess->psi); + goto cleanup; + } + + /* Update authorized PCC rule & QoS */ + update_authorized_pcc_rule_and_qos(sess, SmPolicyDecision); + + ogs_assert(true == ogs_sbi_send_http_status_no_content(stream)); + + smf_qos_flow_binding(sess); + + return true; + +cleanup: + ogs_assert(strerror); + + ogs_error("%s", strerror); + ogs_assert(true == + ogs_sbi_server_send_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, + recvmsg, strerror, NULL)); + ogs_free(strerror); + + return false; +} + +bool smf_npcf_smpolicycontrol_handle_terminate_notify( + smf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg) +{ + smf_ue_t *smf_ue = NULL; + smf_npcf_smpolicycontrol_param_t param; + + ogs_assert(sess); + ogs_assert(stream); + smf_ue = sess->smf_ue; + ogs_assert(smf_ue); + + ogs_assert(recvmsg); + + ogs_assert(true == ogs_sbi_send_http_status_no_content(stream)); + + memset(¶m, 0, sizeof(param)); + ogs_assert(true == + smf_sbi_discover_and_send(OpenAPI_nf_type_PCF, sess, NULL, + OGS_PFCP_DELETE_TRIGGER_PCF_INITIATED, ¶m, + smf_npcf_smpolicycontrol_build_delete)); + + return true; +} diff --git a/src/smf/npcf-handler.h b/src/smf/npcf-handler.h index 961f49a74..babe698b1 100644 --- a/src/smf/npcf-handler.h +++ b/src/smf/npcf-handler.h @@ -32,6 +32,10 @@ bool smf_npcf_smpolicycontrol_handle_create( bool smf_npcf_smpolicycontrol_handle_delete( smf_sess_t *sess, ogs_sbi_stream_t *stream, int state, ogs_sbi_message_t *recvmsg); +bool smf_npcf_smpolicycontrol_handle_update_notify( + smf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg); +bool smf_npcf_smpolicycontrol_handle_terminate_notify( + smf_sess_t *sess, ogs_sbi_stream_t *stream, ogs_sbi_message_t *recvmsg); #ifdef __cplusplus } diff --git a/src/smf/pfcp-path.c b/src/smf/pfcp-path.c index 07e6ee407..c55302b22 100644 --- a/src/smf/pfcp-path.c +++ b/src/smf/pfcp-path.c @@ -400,7 +400,6 @@ int smf_5gc_pfcp_send_session_deletion_request( ogs_pfcp_xact_t *xact = NULL; ogs_assert(sess); - ogs_assert(stream); ogs_assert(trigger); memset(&h, 0, sizeof(ogs_pfcp_header_t)); diff --git a/src/smf/s5c-build.c b/src/smf/s5c-build.c index 5cff6df7d..7217ee7aa 100644 --- a/src/smf/s5c-build.c +++ b/src/smf/s5c-build.c @@ -356,7 +356,7 @@ ogs_pkbuf_t *smf_s5c_build_create_bearer_request( ogs_pkbuf_t *smf_s5c_build_update_bearer_request( uint8_t type, smf_bearer_t *bearer, uint8_t pti, - ogs_gtp_tft_t *tft, int qos_presence) + ogs_gtp_tft_t *tft, bool qos_presence) { smf_sess_t *sess = NULL; @@ -406,7 +406,7 @@ ogs_pkbuf_t *smf_s5c_build_update_bearer_request( } /* Bearer QoS */ - if (qos_presence == 1) { + if (qos_presence == true) { memset(&bearer_qos, 0, sizeof(bearer_qos)); bearer_qos.qci = bearer->qos.index; bearer_qos.priority_level = bearer->qos.arp.priority_level; diff --git a/src/smf/s5c-build.h b/src/smf/s5c-build.h index 4497630cf..eae4d095a 100644 --- a/src/smf/s5c-build.h +++ b/src/smf/s5c-build.h @@ -39,7 +39,7 @@ ogs_pkbuf_t *smf_s5c_build_create_bearer_request( uint8_t type, smf_bearer_t *bearer, ogs_gtp_tft_t *tft); ogs_pkbuf_t *smf_s5c_build_update_bearer_request( uint8_t type, smf_bearer_t *bearer, uint8_t pti, - ogs_gtp_tft_t *tft, int qos_presence); + ogs_gtp_tft_t *tft, bool qos_presence); ogs_pkbuf_t *smf_s5c_build_delete_bearer_request( uint8_t type, smf_bearer_t *bearer, uint8_t pti, uint8_t cause_value); #ifdef __cplusplus diff --git a/src/smf/s5c-handler.c b/src/smf/s5c-handler.c index 4753288af..99273c4cf 100644 --- a/src/smf/s5c-handler.c +++ b/src/smf/s5c-handler.c @@ -663,48 +663,13 @@ void smf_s5c_handle_update_bearer_response( sess->sgw_s5c_teid, sess->smf_n4_teid); if (gtp_flags & OGS_GTP_MODIFY_TFT_UPDATE) { - smf_pf_t *pf = NULL; - ogs_pfcp_pdr_t *dl_pdr = NULL, *ul_pdr = NULL; - - dl_pdr = bearer->dl_pdr; - ogs_assert(dl_pdr); - ul_pdr = bearer->ul_pdr; - ogs_assert(ul_pdr); - - dl_pdr->num_of_flow = 0; - ul_pdr->num_of_flow = 0; - - ogs_list_for_each(&bearer->pf_list, pf) { - if (pf->direction == OGS_FLOW_DOWNLINK_ONLY) { - dl_pdr->flow_description[dl_pdr->num_of_flow++] = - pf->flow_description; - - } else if (pf->direction == OGS_FLOW_UPLINK_ONLY) { - ul_pdr->flow_description[ul_pdr->num_of_flow++] = - pf->flow_description; - } else { - ogs_error("Flow Bidirectional is not supported[%d]", - pf->direction); - } - } - - pfcp_flags |= OGS_PFCP_MODIFY_TFT_UPDATE; + pfcp_flags |= OGS_PFCP_MODIFY_EPC_TFT_UPDATE; + smf_bearer_tft_update(bearer); } if (gtp_flags & OGS_GTP_MODIFY_QOS_UPDATE) { - ogs_pfcp_qer_t *qer = NULL; - - /* Only 1 QER is used per bearer */ - qer = bearer->qer; - if (qer) { - qer->mbr.uplink = bearer->qos.mbr.uplink; - qer->mbr.downlink = bearer->qos.mbr.downlink; - qer->gbr.uplink = bearer->qos.gbr.uplink; - qer->gbr.downlink = bearer->qos.gbr.downlink; - - } - - pfcp_flags |= OGS_PFCP_MODIFY_QOS_UPDATE; + pfcp_flags |= OGS_PFCP_MODIFY_EPC_QOS_UPDATE; + smf_bearer_qos_update(bearer); } if (pfcp_flags) @@ -1058,9 +1023,9 @@ void smf_s5c_handle_bearer_resource_command( ogs_ipfw_encode_flow_description(&pf->ipfw_rule); ogs_assert(pf->flow_description); } - } - tft_update = 1; + tft_update = 1; + } } } else if (tft.code == OGS_GTP_TFT_CODE_ADD_PACKET_FILTERS_TO_EXISTING_TFT || @@ -1138,12 +1103,12 @@ void smf_s5c_handle_bearer_resource_command( pf = smf_pf_find_by_id(bearer, tft.pf[i].identifier+1); if (pf) smf_pf_remove(pf); - - if (ogs_list_count(&bearer->pf_list)) - tft_update = 1; - else - tft_delete = 1; } + + if (ogs_list_count(&bearer->pf_list)) + tft_update = 1; + else + tft_delete = 1; } if (cmd->flow_quality_of_service.presence) { diff --git a/src/smf/sbi-path.c b/src/smf/sbi-path.c index 251ceaa9f..4b40acd1e 100644 --- a/src/smf/sbi-path.c +++ b/src/smf/sbi-path.c @@ -151,7 +151,6 @@ bool smf_sbi_discover_and_send(OpenAPI_nf_type_e target_nf_type, smf_ue = sess->smf_ue; ogs_assert(smf_ue); - ogs_assert(stream); ogs_assert(build); xact = ogs_sbi_xact_add(target_nf_type, &sess->sbi, @@ -173,10 +172,12 @@ bool smf_sbi_discover_and_send(OpenAPI_nf_type_e target_nf_type, (ogs_fsm_handler_t)smf_nf_state_registered, client_cb) != true) { ogs_error("smf_sbi_discover_and_send() failed"); ogs_sbi_xact_remove(xact); - ogs_assert(true == - ogs_sbi_server_send_error(stream, - OGS_SBI_HTTP_STATUS_GATEWAY_TIMEOUT, NULL, - "Cannot discover", smf_ue->supi)); + + if (stream) + ogs_assert(true == + ogs_sbi_server_send_error(stream, + OGS_SBI_HTTP_STATUS_GATEWAY_TIMEOUT, NULL, + "Cannot discover", smf_ue->supi)); return false; } diff --git a/src/smf/smf-sm.c b/src/smf/smf-sm.c index 792a79a56..677e2d642 100644 --- a/src/smf/smf-sm.c +++ b/src/smf/smf-sm.c @@ -26,6 +26,7 @@ #include "gx-handler.h" #include "nnrf-handler.h" #include "namf-handler.h" +#include "npcf-handler.h" void smf_state_initial(ogs_fsm_t *s, smf_event_t *e) { @@ -319,11 +320,11 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) CASE(OGS_SBI_RESOURCE_NAME_RELEASE) if (!sbi_message.h.resource.component[1]) { ogs_error("No smContextRef [%s]", - sbi_message.h.resource.component[2]); + sbi_message.h.resource.component[1]); smf_sbi_send_sm_context_update_error(stream, OGS_SBI_HTTP_STATUS_BAD_REQUEST, "No smContextRef", - sbi_message.h.resource.component[2], + sbi_message.h.resource.component[1], NULL, NULL); break; } @@ -383,11 +384,52 @@ void smf_state_operational(ogs_fsm_t *s, smf_event_t *e) CASE(OGS_SBI_SERVICE_NAME_NSMF_CALLBACK) SWITCH(sbi_message.h.resource.component[0]) CASE(OGS_SBI_RESOURCE_NAME_N1_N2_FAILURE_NOTIFY) - smf_namf_comm_handler_n1_n2_message_transfer_failure_notify( + smf_namf_comm_handle_n1_n2_message_transfer_failure_notify( stream, &sbi_message); break; CASE(OGS_SBI_RESOURCE_NAME_SM_POLICY_NOTIFY) - ogs_assert(true == ogs_sbi_send_http_status_no_content(stream)); + if (!sbi_message.h.resource.component[1]) { + ogs_error("No smContextRef [%s]", + sbi_message.h.resource.component[1]); + ogs_assert(true == + ogs_sbi_server_send_error(stream, + OGS_SBI_HTTP_STATUS_BAD_REQUEST, &sbi_message, + "No smContextRef", + sbi_message.h.resource.component[1])); + break; + } + + sess = smf_sess_find_by_sm_context_ref( + sbi_message.h.resource.component[1]); + + if (!sess) { + ogs_warn("Not found [%s]", sbi_message.h.uri); + ogs_assert(true == + ogs_sbi_server_send_error(stream, + OGS_SBI_HTTP_STATUS_NOT_FOUND, &sbi_message, + "Not found", + sbi_message.h.resource.component[1])); + break; + } + + SWITCH(sbi_message.h.resource.component[2]) + CASE(OGS_SBI_RESOURCE_NAME_UPDATE) + smf_npcf_smpolicycontrol_handle_update_notify( + sess, stream, &sbi_message); + break; + CASE(OGS_SBI_RESOURCE_NAME_TERMINATE) + smf_npcf_smpolicycontrol_handle_terminate_notify( + sess, stream, &sbi_message); + break; + DEFAULT + ogs_error("Invalid resource name [%s]", + sbi_message.h.resource.component[0]); + ogs_assert(true == + ogs_sbi_server_send_error(stream, + OGS_SBI_HTTP_STATUS_BAD_REQUEST, &sbi_message, + "Invalid resource name", + sbi_message.h.resource.component[0])); + END break; DEFAULT ogs_error("Invalid resource name [%s]", diff --git a/tests/af/af-sm.c b/tests/af/af-sm.c index 2ec316739..7af30e6a3 100644 --- a/tests/af/af-sm.c +++ b/tests/af/af-sm.c @@ -121,6 +121,62 @@ void af_state_operational(ogs_fsm_t *s, af_event_t *e) END break; + CASE(OGS_SBI_SERVICE_NAME_NPCF_POLICYAUTHORIZATION) + SWITCH(message.h.resource.component[0]) + CASE(OGS_SBI_RESOURCE_NAME_APP_SESSIONS) + af_sess_t *app_session = NULL; + + if (!message.h.resource.component[1]) { + ogs_error("[%s] Unknown app session id", + message.h.resource.component[1]); + ogs_assert(true == + ogs_sbi_server_send_error(stream, + OGS_SBI_HTTP_STATUS_NOT_FOUND, + &message, "Not found", + message.h.resource.component[1])); + break; + } + + app_session = af_sess_find_by_af_app_session_id( + message.h.resource.component[1]); + if (!app_session) { + ogs_error("[%s] Unknown app session id", + message.h.resource.component[1]); + ogs_assert(true == + ogs_sbi_server_send_error(stream, + OGS_SBI_HTTP_STATUS_NOT_FOUND, + &message, "Not found", + message.h.resource.component[1])); + break; + } + + SWITCH(message.h.resource.component[2]) + CASE(OGS_SBI_RESOURCE_NAME_TERMINATE) + ogs_assert(true == + ogs_sbi_send_http_status_no_content(stream)); + af_sess_remove(app_session); + break; + DEFAULT + ogs_error("Invalid resource name [%s]", + message.h.resource.component[2]); + ogs_assert(true == + ogs_sbi_server_send_error(stream, + OGS_SBI_HTTP_STATUS_BAD_REQUEST, &message, + "Invalid resource name", + message.h.resource.component[2])); + END + break; + DEFAULT + ogs_error("Invalid resource name [%s]", + message.h.resource.component[0]); + ogs_assert(true == + ogs_sbi_server_send_error(stream, + OGS_SBI_HTTP_STATUS_BAD_REQUEST, &message, + "Invalid resource name", + message.h.resource.component[0])); + END + break; + DEFAULT ogs_error("Invalid API name [%s]", message.h.service.name); ogs_assert(true == @@ -270,10 +326,48 @@ void af_state_operational(ogs_fsm_t *s, af_event_t *e) sess = e->sbi.data; ogs_assert(sess); - if (message.res_status == OGS_SBI_HTTP_STATUS_CREATED) - af_npcf_policyauthorization_handle_create(sess, &message); - else - ogs_error("HTTP response error [%d]", message.res_status); + if (message.h.resource.component[1]) { + if (message.h.resource.component[2]) { + SWITCH(message.h.resource.component[2]) + CASE(OGS_SBI_RESOURCE_NAME_DELETE) + af_sess_remove(sess); + break; + DEFAULT + ogs_error("Invalid resource name [%s]", + message.h.resource.component[2]); + ogs_assert_if_reached(); + END + } else { + SWITCH(message.h.method) + CASE(OGS_SBI_HTTP_METHOD_PATCH) + if (message.res_status == OGS_SBI_HTTP_STATUS_OK) + af_npcf_policyauthorization_handle_update( + sess, &message); + else + ogs_error("HTTP response error [%d]", + message.res_status); + break; + DEFAULT + ogs_error("Invalid HTTP method [%s]", + message.h.method); + ogs_assert_if_reached(); + END + } + } else { + SWITCH(message.h.method) + CASE(OGS_SBI_HTTP_METHOD_POST) + if (message.res_status == OGS_SBI_HTTP_STATUS_CREATED) + af_npcf_policyauthorization_handle_create( + sess, &message); + else + ogs_error("HTTP response error [%d]", + message.res_status); + break; + DEFAULT + ogs_error("Invalid HTTP method [%s]", message.h.method); + ogs_assert_if_reached(); + END + } break; DEFAULT ogs_error("Invalid resource name [%s]", diff --git a/tests/af/context.c b/tests/af/context.c index d76ba6de8..58816a70d 100644 --- a/tests/af/context.c +++ b/tests/af/context.c @@ -241,7 +241,7 @@ bool af_sess_set_pcf_app_session_id(af_sess_t *sess, char *pcf_app_session_id) ogs_expect_or_return_val(sess->pcf_app_session_id, false); ogs_hash_set(self.pcf_app_session_id_hash, - &sess->pcf_app_session_id, sizeof(sess->pcf_app_session_id), sess); + &sess->pcf_app_session_id, strlen(sess->pcf_app_session_id), sess); return true; } @@ -257,6 +257,13 @@ af_sess_t *af_sess_find_by_af_app_session_id(char *af_app_session_id) return af_sess_find(atoll(af_app_session_id)); } +af_sess_t *af_sess_find_by_pcf_app_session_id(char *pcf_app_session_id) +{ + ogs_assert(pcf_app_session_id); + return (af_sess_t *)ogs_hash_get(self.pcf_app_session_id_hash, + pcf_app_session_id, strlen(pcf_app_session_id)); +} + void af_sess_select_nf(af_sess_t *sess, OpenAPI_nf_type_e nf_type) { ogs_assert(sess); diff --git a/tests/af/npcf-build.c b/tests/af/npcf-build.c index 6cb19e0b8..a2a1ad0cf 100644 --- a/tests/af/npcf-build.c +++ b/tests/af/npcf-build.c @@ -47,12 +47,19 @@ ogs_sbi_request_t *af_npcf_policyauthorization_build_create( OpenAPI_list_t *fDescList = NULL; OpenAPI_list_t *codecList = NULL; - int i, j; OpenAPI_lnode_t *node = NULL, *node2 = NULL, *node3 = NULL; + int i = 0, j = 0; + + af_npcf_policyauthorization_param_t *af_param; + ogs_assert(sess); ogs_assert(sess->af_app_session_id); + af_param = data; + ogs_assert(af_param); + ogs_assert(af_param->med_type); + memset(&message, 0, sizeof(message)); message.h.method = (char *)OGS_SBI_HTTP_METHOD_POST; message.h.service.name = @@ -76,7 +83,6 @@ ogs_sbi_request_t *af_npcf_policyauthorization_build_create( header.api.version = (char *)OGS_SBI_API_V1; header.resource.component[0] = (char *)OGS_SBI_RESOURCE_NAME_APP_SESSIONS; header.resource.component[1] = (char *)sess->af_app_session_id; - header.resource.component[2] = (char *)OGS_SBI_RESOURCE_NAME_NOTIFY; AscReqData.notif_uri = ogs_sbi_server_uri(server, &header); ogs_expect_or_return_val(AscReqData.notif_uri, NULL); @@ -123,9 +129,6 @@ ogs_sbi_request_t *af_npcf_policyauthorization_build_create( AscReqData.af_app_id = (char *)"IMS Services"; AscReqData.res_prio = OpenAPI_reserv_priority_PRIO_1; - /* Media Component */ - i = 0, j = 0; - MediaComponentList = OpenAPI_list_create(); ogs_assert(MediaComponentList); @@ -134,15 +137,26 @@ ogs_sbi_request_t *af_npcf_policyauthorization_build_create( MediaComponent->med_comp_n = (i++); MediaComponent->f_status = OpenAPI_flow_status_ENABLED; - MediaComponent->mar_bw_dl = ogs_sbi_bitrate_to_string( - 41000, OGS_SBI_BITRATE_KBPS); - MediaComponent->mar_bw_ul = ogs_sbi_bitrate_to_string( - 41000, OGS_SBI_BITRATE_KBPS); - MediaComponent->med_type = OpenAPI_media_type_AUDIO; - MediaComponent->rr_bw = ogs_sbi_bitrate_to_string( - 2000, OGS_SBI_BITRATE_BPS); - MediaComponent->rs_bw = ogs_sbi_bitrate_to_string( - 600, OGS_SBI_BITRATE_BPS); + MediaComponent->med_type = af_param->med_type; + if (af_param->qos_type == 1) { + MediaComponent->mar_bw_dl = ogs_sbi_bitrate_to_string( + 96000, OGS_SBI_BITRATE_BPS); + MediaComponent->mar_bw_ul = ogs_sbi_bitrate_to_string( + 96000, OGS_SBI_BITRATE_BPS); + MediaComponent->rr_bw = ogs_sbi_bitrate_to_string( + 2400, OGS_SBI_BITRATE_BPS); + MediaComponent->rs_bw = ogs_sbi_bitrate_to_string( + 2400, OGS_SBI_BITRATE_BPS); + } else if (af_param->qos_type == 2) { + MediaComponent->mar_bw_dl = ogs_sbi_bitrate_to_string( + 96000, OGS_SBI_BITRATE_BPS); + MediaComponent->mar_bw_ul = ogs_sbi_bitrate_to_string( + 96000, OGS_SBI_BITRATE_BPS); + MediaComponent->rr_bw = ogs_sbi_bitrate_to_string( + 88000, OGS_SBI_BITRATE_BPS); + MediaComponent->rs_bw = ogs_sbi_bitrate_to_string( + 88000, OGS_SBI_BITRATE_BPS); + } /* Codec */ codecList = OpenAPI_list_create(); @@ -168,9 +182,6 @@ ogs_sbi_request_t *af_npcf_policyauthorization_build_create( OpenAPI_list_add(MediaComponentList, MediaComponentMap); - ogs_assert(MediaComponentList->count); - AscReqData.med_components = MediaComponentList; - /* Sub Component */ SubComponentList = OpenAPI_list_create(); ogs_assert(SubComponentList); @@ -192,19 +203,37 @@ ogs_sbi_request_t *af_npcf_policyauthorization_build_create( /* Flow Description */ fDescList = OpenAPI_list_create(); ogs_assert(fDescList); - OpenAPI_list_add(fDescList, - ogs_strdup("permit out 17 from 172.20.166.84 to 10.45.0.2 20001")); - OpenAPI_list_add(fDescList, - ogs_strdup("permit in 17 from 10.45.0.2 to 172.20.166.84 20360")); - ogs_assert(fDescList->count); - SubComponent->f_descs = fDescList; + if (af_param->flow_type == 0) { + /* Nothing */ + } else if (af_param->flow_type == 1) { + OpenAPI_list_add(fDescList, + ogs_strdup("permit out 17 from 172.20.166.84 to 10.45.0.2 20001")); + OpenAPI_list_add(fDescList, + ogs_strdup("permit in 17 from 10.45.0.2 to 172.20.166.84 20360")); + } else if (af_param->flow_type == 2) { + OpenAPI_list_add(fDescList, + ogs_strdup("permit out 17 from 172.20.166.84 to 10.45.0.2 30001")); + OpenAPI_list_add(fDescList, + ogs_strdup("permit in 17 from 10.45.0.2 to 172.20.166.84 30360")); + } else if (af_param->flow_type == 99) { + OpenAPI_list_add(fDescList, + ogs_strdup("permit out icmp from any to any")); + OpenAPI_list_add(fDescList, + ogs_strdup("permit in icmp from any to any")); + } else { + ogs_assert_if_reached(); + } + if (fDescList->count) + SubComponent->f_descs = fDescList; + else + OpenAPI_list_free(fDescList); /* Sub Component #2 */ SubComponent = ogs_calloc(1, sizeof(*SubComponent)); ogs_expect_or_return_val(SubComponent, NULL); SubComponent->f_num = (j++); - SubComponent->flow_usage = OpenAPI_flow_usage_NO_INFO; + SubComponent->flow_usage = OpenAPI_flow_usage_RTCP; SubComponentMap = OpenAPI_map_create( ogs_msprintf("%d", SubComponent->f_num), SubComponent); @@ -216,16 +245,33 @@ ogs_sbi_request_t *af_npcf_policyauthorization_build_create( /* Flow Description */ fDescList = OpenAPI_list_create(); ogs_assert(fDescList); - OpenAPI_list_add(fDescList, - ogs_strdup("permit out 17 from 172.20.166.84 to 10.45.0.2 20002")); - OpenAPI_list_add(fDescList, - ogs_strdup("permit in 17 from 10.45.0.2 to 172.20.166.84 20361")); - ogs_assert(fDescList->count); - SubComponent->f_descs = fDescList; + if (af_param->flow_type == 0) { + /* Nothing */ + } else if (af_param->flow_type == 1 || af_param->flow_type == 99) { + OpenAPI_list_add(fDescList, + ogs_strdup("permit out 17 from 172.20.166.84 to 10.45.0.2 20002")); + OpenAPI_list_add(fDescList, + ogs_strdup("permit in 17 from 10.45.0.2 to 172.20.166.84 20361")); + } else if (af_param->flow_type == 2) { + OpenAPI_list_add(fDescList, + ogs_strdup("permit out 17 from 172.20.166.84 to 10.45.0.2 30002")); + OpenAPI_list_add(fDescList, + ogs_strdup("permit in 17 from 10.45.0.2 to 172.20.166.84 30361")); + } else { + ogs_assert_if_reached(); + } + + if (fDescList->count) + SubComponent->f_descs = fDescList; + else + OpenAPI_list_free(fDescList); ogs_assert(SubComponentList->count); MediaComponent->med_sub_comps = SubComponentList; + ogs_assert(MediaComponentList->count); + AscReqData.med_components = MediaComponentList; + request = ogs_sbi_build_request(&message); ogs_expect_or_return_val(request, NULL); @@ -244,7 +290,6 @@ ogs_sbi_request_t *af_npcf_policyauthorization_build_create( if (sNssai.sd) ogs_free(sNssai.sd); - MediaComponentList = AscReqData.med_components; OpenAPI_list_for_each(MediaComponentList, node) { MediaComponentMap = node->data; if (MediaComponentMap) { @@ -255,6 +300,729 @@ ogs_sbi_request_t *af_npcf_policyauthorization_build_create( ogs_free(MediaComponent->mar_bw_dl); if (MediaComponent->mar_bw_ul) ogs_free(MediaComponent->mar_bw_ul); + if (MediaComponent->mir_bw_dl) + ogs_free(MediaComponent->mir_bw_dl); + if (MediaComponent->mir_bw_ul) + ogs_free(MediaComponent->mir_bw_ul); + if (MediaComponent->rr_bw) + ogs_free(MediaComponent->rr_bw); + if (MediaComponent->rs_bw) + ogs_free(MediaComponent->rs_bw); + + codecList = MediaComponent->codecs; + OpenAPI_list_for_each(codecList, node2) { + if (node2->data) ogs_free(node2->data); + } + OpenAPI_list_free(codecList); + + SubComponentList = MediaComponent->med_sub_comps; + OpenAPI_list_for_each(SubComponentList, node2) { + SubComponentMap = node2->data; + if (SubComponentMap) { + SubComponent = SubComponentMap->value; + if (SubComponent) { + + fDescList = SubComponent->f_descs; + OpenAPI_list_for_each(fDescList, node3) { + if (node3->data) ogs_free(node3->data); + } + OpenAPI_list_free(fDescList); + + ogs_free(SubComponent); + } + if (SubComponentMap->key) + ogs_free(SubComponentMap->key); + ogs_free(SubComponentMap); + } + } + OpenAPI_list_free(SubComponentList); + + ogs_free(MediaComponent); + } + if (MediaComponentMap->key) + ogs_free(MediaComponentMap->key); + ogs_free(MediaComponentMap); + } + } + OpenAPI_list_free(MediaComponentList); + + return request; +} + +ogs_sbi_request_t *af_npcf_policyauthorization_build_update( + af_sess_t *sess, void *data) +{ + ogs_sbi_message_t message; + ogs_sbi_request_t *request = NULL; + + OpenAPI_app_session_context_update_data_patch_t + AppSessionContextUpdateDataPatch; + OpenAPI_app_session_context_update_data_t AscUpdateData; + + OpenAPI_list_t *MediaComponentList = NULL; + OpenAPI_map_t *MediaComponentMap = NULL; + OpenAPI_media_component_rm_t *MediaComponent = NULL; + + OpenAPI_list_t *SubComponentList = NULL; + OpenAPI_map_t *SubComponentMap = NULL; + OpenAPI_media_sub_component_t *SubComponent = NULL; + + OpenAPI_list_t *fDescList = NULL; + OpenAPI_list_t *codecList = NULL; + + OpenAPI_lnode_t *node = NULL, *node2 = NULL, *node3 = NULL; + + int i = 0, j = 0; + + af_npcf_policyauthorization_param_t *af_param; + + ogs_assert(sess); + ogs_assert(sess->pcf_app_session_id); + + af_param = data; + ogs_assert(af_param); + + memset(&message, 0, sizeof(message)); + message.h.method = (char *)OGS_SBI_HTTP_METHOD_PATCH; + message.h.service.name = + (char *)OGS_SBI_SERVICE_NAME_NPCF_POLICYAUTHORIZATION; + message.h.api.version = (char *)OGS_SBI_API_V1; + message.h.resource.component[0] = + (char *)OGS_SBI_RESOURCE_NAME_APP_SESSIONS; + message.h.resource.component[1] = sess->pcf_app_session_id; + + message.AppSessionContextUpdateDataPatch = + &AppSessionContextUpdateDataPatch; + + memset(&AppSessionContextUpdateDataPatch, 0, + sizeof(AppSessionContextUpdateDataPatch)); + AppSessionContextUpdateDataPatch.asc_req_data = &AscUpdateData; + + memset(&AscUpdateData, 0, sizeof(AscUpdateData)); + + AscUpdateData.spon_status = OpenAPI_sponsoring_status_SPONSOR_DISABLED; + + AscUpdateData.af_app_id = (char *)"IMS Services"; + AscUpdateData.res_prio = OpenAPI_reserv_priority_PRIO_1; + + MediaComponentList = OpenAPI_list_create(); + ogs_assert(MediaComponentList); + + MediaComponent = ogs_calloc(1, sizeof(*MediaComponent)); + ogs_expect_or_return_val(MediaComponent, NULL); + + MediaComponent->med_comp_n = (i++); + MediaComponent->f_status = OpenAPI_flow_status_ENABLED; + MediaComponent->med_type = OpenAPI_media_type_AUDIO; + if (af_param->qos_type == 1) { + MediaComponent->mar_bw_dl = ogs_sbi_bitrate_to_string( + 96000, OGS_SBI_BITRATE_BPS); + MediaComponent->mar_bw_ul = ogs_sbi_bitrate_to_string( + 96000, OGS_SBI_BITRATE_BPS); + MediaComponent->rr_bw = ogs_sbi_bitrate_to_string( + 2400, OGS_SBI_BITRATE_BPS); + MediaComponent->rs_bw = ogs_sbi_bitrate_to_string( + 2400, OGS_SBI_BITRATE_BPS); + } else if (af_param->qos_type == 2) { + MediaComponent->mar_bw_dl = ogs_sbi_bitrate_to_string( + 96000, OGS_SBI_BITRATE_BPS); + MediaComponent->mar_bw_ul = ogs_sbi_bitrate_to_string( + 96000, OGS_SBI_BITRATE_BPS); + MediaComponent->mir_bw_dl = ogs_sbi_bitrate_to_string( + 88000, OGS_SBI_BITRATE_BPS); + MediaComponent->mir_bw_ul = ogs_sbi_bitrate_to_string( + 88000, OGS_SBI_BITRATE_BPS); + } + + /* Codec */ + codecList = OpenAPI_list_create(); + ogs_assert(codecList); + OpenAPI_list_add(codecList, + ogs_strdup("downlink\noffer\n" + "m=audio 49000 RTP/AVP 116 99 97 105 100\r\nb=AS:41\r\n" + "b=RS:512\r\nb=RR:1537\r\na=maxptime:240\r\n" + "a=des:qos mandatory local sendrecv\r\na=curr:qos local none\r\n" + "a=des:qos option")); + OpenAPI_list_add(codecList, + ogs_strdup("uplink\nanswer\nm=audio 50020 RTP/AVP 99 105\r\n" + "b=AS:41\r\nb=RS:600\r\nb=RR:2000\r\na=rtpmap:99 AMR-WB/16000/1\r\n" + "a=fmtp:99 mode-change-capability=2;max-red=0\r\n" + "a=rtpmap:105 telephone-event/16")); + ogs_assert(codecList->count); + MediaComponent->codecs = codecList; + + MediaComponentMap = OpenAPI_map_create( + ogs_msprintf("%d", MediaComponent->med_comp_n), MediaComponent); + ogs_assert(MediaComponentMap); + ogs_assert(MediaComponentMap->key); + + OpenAPI_list_add(MediaComponentList, MediaComponentMap); + + /* Sub Component */ + SubComponentList = OpenAPI_list_create(); + ogs_assert(SubComponentList); + + /* Sub Component #1 */ + SubComponent = ogs_calloc(1, sizeof(*SubComponent)); + ogs_expect_or_return_val(SubComponent, NULL); + + SubComponent->f_num = (j++); + SubComponent->flow_usage = OpenAPI_flow_usage_NO_INFO; + + SubComponentMap = OpenAPI_map_create( + ogs_msprintf("%d", SubComponent->f_num), SubComponent); + ogs_assert(SubComponentMap); + ogs_assert(SubComponentMap->key); + + OpenAPI_list_add(SubComponentList, SubComponentMap); + + /* Flow Description */ + fDescList = OpenAPI_list_create(); + ogs_assert(fDescList); + if (af_param->flow_type == 0) { + /* Nothing */ + } else if (af_param->flow_type == 1) { + OpenAPI_list_add(fDescList, + ogs_strdup("permit out 17 from 172.20.166.84 to 10.45.0.2 20001")); + OpenAPI_list_add(fDescList, + ogs_strdup("permit in 17 from 10.45.0.2 to 172.20.166.84 20360")); + } else if (af_param->flow_type == 99) { + OpenAPI_list_add(fDescList, + ogs_strdup("permit out icmp from any to any")); + OpenAPI_list_add(fDescList, + ogs_strdup("permit in icmp from any to any")); + } else { + ogs_assert_if_reached(); + } + if (fDescList->count) + SubComponent->f_descs = fDescList; + else + OpenAPI_list_free(fDescList); + + /* Sub Component #2 */ + SubComponent = ogs_calloc(1, sizeof(*SubComponent)); + ogs_expect_or_return_val(SubComponent, NULL); + + SubComponent->f_num = (j++); + SubComponent->flow_usage = OpenAPI_flow_usage_RTCP; + + SubComponentMap = OpenAPI_map_create( + ogs_msprintf("%d", SubComponent->f_num), SubComponent); + ogs_assert(SubComponentMap); + ogs_assert(SubComponentMap->key); + + OpenAPI_list_add(SubComponentList, SubComponentMap); + + /* Flow Description */ + fDescList = OpenAPI_list_create(); + ogs_assert(fDescList); + if (af_param->flow_type) { + OpenAPI_list_add(fDescList, + ogs_strdup("permit out 17 from 172.20.166.84 to 10.45.0.2 20002")); + OpenAPI_list_add(fDescList, + ogs_strdup("permit in 17 from 10.45.0.2 to 172.20.166.84 20361")); + } + if (fDescList->count) + SubComponent->f_descs = fDescList; + else + OpenAPI_list_free(fDescList); + + ogs_assert(SubComponentList->count); + MediaComponent->med_sub_comps = SubComponentList; + + ogs_assert(MediaComponentList->count); + AscUpdateData.med_components = MediaComponentList; + + request = ogs_sbi_build_request(&message); + ogs_expect_or_return_val(request, NULL); + + OpenAPI_list_for_each(MediaComponentList, node) { + MediaComponentMap = node->data; + if (MediaComponentMap) { + MediaComponent = MediaComponentMap->value; + if (MediaComponent) { + + if (MediaComponent->mar_bw_dl) + ogs_free(MediaComponent->mar_bw_dl); + if (MediaComponent->mar_bw_ul) + ogs_free(MediaComponent->mar_bw_ul); + if (MediaComponent->mir_bw_dl) + ogs_free(MediaComponent->mir_bw_dl); + if (MediaComponent->mir_bw_ul) + ogs_free(MediaComponent->mir_bw_ul); + if (MediaComponent->rr_bw) + ogs_free(MediaComponent->rr_bw); + if (MediaComponent->rs_bw) + ogs_free(MediaComponent->rs_bw); + + codecList = MediaComponent->codecs; + OpenAPI_list_for_each(codecList, node2) { + if (node2->data) ogs_free(node2->data); + } + OpenAPI_list_free(codecList); + + SubComponentList = MediaComponent->med_sub_comps; + OpenAPI_list_for_each(SubComponentList, node2) { + SubComponentMap = node2->data; + if (SubComponentMap) { + SubComponent = SubComponentMap->value; + if (SubComponent) { + + fDescList = SubComponent->f_descs; + OpenAPI_list_for_each(fDescList, node3) { + if (node3->data) ogs_free(node3->data); + } + OpenAPI_list_free(fDescList); + + ogs_free(SubComponent); + } + if (SubComponentMap->key) + ogs_free(SubComponentMap->key); + ogs_free(SubComponentMap); + } + } + OpenAPI_list_free(SubComponentList); + + ogs_free(MediaComponent); + } + if (MediaComponentMap->key) + ogs_free(MediaComponentMap->key); + ogs_free(MediaComponentMap); + } + } + OpenAPI_list_free(MediaComponentList); + + return request; +} + +ogs_sbi_request_t *af_npcf_policyauthorization_build_delete( + af_sess_t *sess, void *data) +{ + ogs_sbi_message_t message; + ogs_sbi_request_t *request = NULL; + + ogs_assert(sess); + ogs_assert(sess->pcf_app_session_id); + + memset(&message, 0, sizeof(message)); + message.h.method = (char *)OGS_SBI_HTTP_METHOD_POST; + message.h.service.name = + (char *)OGS_SBI_SERVICE_NAME_NPCF_POLICYAUTHORIZATION; + message.h.api.version = (char *)OGS_SBI_API_V1; + message.h.resource.component[0] = + (char *)OGS_SBI_RESOURCE_NAME_APP_SESSIONS; + message.h.resource.component[1] = sess->pcf_app_session_id; + message.h.resource.component[2] = + (char *)OGS_SBI_RESOURCE_NAME_DELETE; + + request = ogs_sbi_build_request(&message); + ogs_expect_or_return_val(request, NULL); + + return request; +} + +ogs_sbi_request_t *af_npcf_policyauthorization_build_create_video( + af_sess_t *sess, void *data) +{ + ogs_sbi_message_t message; + ogs_sbi_request_t *request = NULL; + ogs_sbi_server_t *server = NULL; + ogs_sbi_header_t header; + + OpenAPI_app_session_context_t AppSessionContext; + OpenAPI_app_session_context_req_data_t AscReqData; + + OpenAPI_events_subsc_req_data_t evSubsc; + OpenAPI_list_t *EventList = NULL; + OpenAPI_af_event_subscription_t *Event = NULL; + + OpenAPI_snssai_t sNssai; + + OpenAPI_list_t *MediaComponentList = NULL; + OpenAPI_map_t *MediaComponentMap = NULL; + OpenAPI_media_component_t *MediaComponent = NULL; + + OpenAPI_list_t *SubComponentList = NULL; + OpenAPI_map_t *SubComponentMap = NULL; + OpenAPI_media_sub_component_t *SubComponent = NULL; + + OpenAPI_list_t *fDescList = NULL; + OpenAPI_list_t *codecList = NULL; + + OpenAPI_lnode_t *node = NULL, *node2 = NULL, *node3 = NULL; + + int i = 0, j = 0; + + af_npcf_policyauthorization_param_t *af_param; + + ogs_assert(sess); + ogs_assert(sess->af_app_session_id); + + af_param = data; + ogs_assert(af_param); + + memset(&message, 0, sizeof(message)); + message.h.method = (char *)OGS_SBI_HTTP_METHOD_POST; + message.h.service.name = + (char *)OGS_SBI_SERVICE_NAME_NPCF_POLICYAUTHORIZATION; + message.h.api.version = (char *)OGS_SBI_API_V1; + message.h.resource.component[0] = + (char *)OGS_SBI_RESOURCE_NAME_APP_SESSIONS; + + message.AppSessionContext = &AppSessionContext; + + memset(&AppSessionContext, 0, sizeof(AppSessionContext)); + AppSessionContext.asc_req_data = &AscReqData; + + memset(&AscReqData, 0, sizeof(AscReqData)); + + server = ogs_list_first(&ogs_sbi_self()->server_list); + ogs_expect_or_return_val(server, NULL); + + memset(&header, 0, sizeof(header)); + header.service.name = (char *)OGS_SBI_SERVICE_NAME_NPCF_POLICYAUTHORIZATION; + header.api.version = (char *)OGS_SBI_API_V1; + header.resource.component[0] = (char *)OGS_SBI_RESOURCE_NAME_APP_SESSIONS; + header.resource.component[1] = (char *)sess->af_app_session_id; + AscReqData.notif_uri = ogs_sbi_server_uri(server, &header); + ogs_expect_or_return_val(AscReqData.notif_uri, NULL); + + AscReqData.supp_feat = + ogs_uint64_to_string(sess->policyauthorization_features); + ogs_assert(AscReqData.supp_feat); + + AscReqData.ue_ipv4 = sess->ipv4addr; + AscReqData.ue_ipv6 = sess->ipv6addr; + + AscReqData.dnn = sess->dnn; + + memset(&evSubsc, 0, sizeof(evSubsc)); + + EventList = OpenAPI_list_create(); + ogs_assert(EventList); + + Event = ogs_calloc(1, sizeof(*Event)); + ogs_expect_or_return_val(Event, NULL); + Event->event = OpenAPI_af_event_CHARGING_CORRELATION; + OpenAPI_list_add(EventList, Event); + + Event = ogs_calloc(1, sizeof(*Event)); + ogs_expect_or_return_val(Event, NULL); + Event->event = OpenAPI_af_event_ANI_REPORT; + Event->notif_method = OpenAPI_af_notif_method_ONE_TIME; + OpenAPI_list_add(EventList, Event); + + evSubsc.events = EventList; + AscReqData.ev_subsc = &evSubsc; + + memset(&sNssai, 0, sizeof(sNssai)); + if (sess->s_nssai.sst) { + sNssai.sst = sess->s_nssai.sst; + sNssai.sd = ogs_s_nssai_sd_to_string(sess->s_nssai.sd); + AscReqData.slice_info = &sNssai; + } + + AscReqData.spon_status = OpenAPI_sponsoring_status_SPONSOR_DISABLED; + + AscReqData.supi = sess->supi; + AscReqData.gpsi = sess->gpsi; + + AscReqData.af_app_id = (char *)"IMS Services"; + AscReqData.res_prio = OpenAPI_reserv_priority_PRIO_1; + + MediaComponentList = OpenAPI_list_create(); + ogs_assert(MediaComponentList); + + MediaComponent = ogs_calloc(1, sizeof(*MediaComponent)); + ogs_expect_or_return_val(MediaComponent, NULL); + + MediaComponent->med_comp_n = (i++); + MediaComponent->f_status = OpenAPI_flow_status_ENABLED; + MediaComponent->med_type = OpenAPI_media_type_AUDIO; + MediaComponent->mar_bw_dl = ogs_sbi_bitrate_to_string( + 41000, OGS_SBI_BITRATE_BPS); + MediaComponent->mar_bw_ul = ogs_sbi_bitrate_to_string( + 41000, OGS_SBI_BITRATE_BPS); + MediaComponent->rr_bw = ogs_sbi_bitrate_to_string( + 2000, OGS_SBI_BITRATE_BPS); + MediaComponent->rs_bw = ogs_sbi_bitrate_to_string( + 600, OGS_SBI_BITRATE_BPS); + + /* Codec */ + codecList = OpenAPI_list_create(); + ogs_assert(codecList); + OpenAPI_list_add(codecList, + ogs_strdup("downlink\noffer\nm=audio 50026 RTP/AVP 104 102 96 97\r\n" \ + "b=AS:41\r\n" \ + "b=RS:600\r\n" \ + "b=RR:2000\r\n" \ + "a=rtpmap:104 AMR-WB/16000/1\r\n" \ + "a=fmtp:104 mode-change-capability=2;max-red=0\r\n" \ + "a=rtpmap:102 AMR/8000/1\r\n" \ + "a=fmtp:102 mode-change-capability=2;max-red=0\r\n" \ + "a=rtpmap:96 telephone-event/16000\r\n" \ + "a=fmtp:96 0-15\r\n" \ + "a=rtpmap:97 telephone-event/8000\r\n" \ + "a=fmtp:97 0-15\r\n" \ + "a=curr:qos local none\r\n" \ + "a=curr:qos remote none\r\n" \ + "a=des:qos mandatory local sendrecv\r\n" \ + "a=des:qos optional remote sendrecv\r\n" \ + "a=sendrecv\r\n" \ + "a=maxptime:240\r\n" \ + "a=ptime:20\r\n")); + OpenAPI_list_add(codecList, + ogs_strdup("uplink\nanswer\nm=audio 50022 RTP/AVP 104 96\r\n" \ + "b=AS:41\r\n" \ + "b=RS:600\r\n" \ + "b=RR:2000\r\n" \ + "a=rtpmap:104 AMR-WB/16000/1\r\n" \ + "a=fmtp:104 mode-change-capability=2;max-red=0\r\n" \ + "a=rtpmap:96 telephone-event/16000\r\n" \ + "a=fmtp:96 0-15\r\n" \ + "a=curr:qos local none\r\n" \ + "a=curr:qos remote none\r\n" \ + "a=des:qos mandatory local sendrecv\r\n" \ + "a=des:qos mandatory remote sendrecv\r\n" \ + "a=conf:qos remote sendrecv\r\n" \ + "a=sendrecv\r\n" \ + "a=maxptime:240\r\n" \ + "a=ptime:20\r\n")); + ogs_assert(codecList->count); + MediaComponent->codecs = codecList; + + MediaComponentMap = OpenAPI_map_create( + ogs_msprintf("%d", MediaComponent->med_comp_n), MediaComponent); + ogs_assert(MediaComponentMap); + ogs_assert(MediaComponentMap->key); + + OpenAPI_list_add(MediaComponentList, MediaComponentMap); + + /* Sub Component */ + SubComponentList = OpenAPI_list_create(); + ogs_assert(SubComponentList); + + j = 0; + + /* Sub Component #1 */ + SubComponent = ogs_calloc(1, sizeof(*SubComponent)); + ogs_expect_or_return_val(SubComponent, NULL); + + SubComponent->f_num = (j++); + SubComponent->flow_usage = OpenAPI_flow_usage_NO_INFO; + + SubComponentMap = OpenAPI_map_create( + ogs_msprintf("%d", SubComponent->f_num), SubComponent); + ogs_assert(SubComponentMap); + ogs_assert(SubComponentMap->key); + + OpenAPI_list_add(SubComponentList, SubComponentMap); + + /* Flow Description */ + fDescList = OpenAPI_list_create(); + ogs_assert(fDescList); + OpenAPI_list_add(fDescList, + ogs_strdup("permit out 17 from 10.45.0.5 50026 to 10.45.0.3 50022")); + OpenAPI_list_add(fDescList, + ogs_strdup("permit in 17 from 10.45.0.3 50022 to 10.45.0.5 50026")); + if (fDescList->count) + SubComponent->f_descs = fDescList; + else + OpenAPI_list_free(fDescList); + + /* Sub Component #2 */ + SubComponent = ogs_calloc(1, sizeof(*SubComponent)); + ogs_expect_or_return_val(SubComponent, NULL); + + SubComponent->f_num = (j++); + SubComponent->flow_usage = OpenAPI_flow_usage_NO_INFO; + + SubComponentMap = OpenAPI_map_create( + ogs_msprintf("%d", SubComponent->f_num), SubComponent); + ogs_assert(SubComponentMap); + ogs_assert(SubComponentMap->key); + + OpenAPI_list_add(SubComponentList, SubComponentMap); + + /* Flow Description */ + fDescList = OpenAPI_list_create(); + ogs_assert(fDescList); + OpenAPI_list_add(fDescList, + ogs_strdup("permit out 17 from 10.45.0.5 50027 to 10.45.0.3 50023")); + OpenAPI_list_add(fDescList, + ogs_strdup("permit in 17 from 10.45.0.3 50023 to 10.45.0.5 50027")); + if (fDescList->count) + SubComponent->f_descs = fDescList; + else + OpenAPI_list_free(fDescList); + + ogs_assert(SubComponentList->count); + MediaComponent->med_sub_comps = SubComponentList; + + MediaComponent = ogs_calloc(1, sizeof(*MediaComponent)); + ogs_expect_or_return_val(MediaComponent, NULL); + + MediaComponent->med_comp_n = (i++); + MediaComponent->f_status = OpenAPI_flow_status_ENABLED; + MediaComponent->med_type = OpenAPI_media_type_VIDEO; + MediaComponent->mar_bw_dl = ogs_sbi_bitrate_to_string( + 401000, OGS_SBI_BITRATE_BPS); + MediaComponent->mar_bw_ul = ogs_sbi_bitrate_to_string( + 401000, OGS_SBI_BITRATE_BPS); + MediaComponent->rr_bw = ogs_sbi_bitrate_to_string( + 2000, OGS_SBI_BITRATE_BPS); + MediaComponent->rs_bw = ogs_sbi_bitrate_to_string( + 600, OGS_SBI_BITRATE_BPS); + + /* Codec */ + codecList = OpenAPI_list_create(); + ogs_assert(codecList); + OpenAPI_list_add(codecList, + ogs_strdup("downlink\noffer\nm=video 60010 RTP/AVP 114 113\r\n" \ + "b=AS:401\r\n" \ + "b=RS:600\r\n" \ + "b=RR:2000\r\n" \ + "a=rtpmap:114 H264/90000\r\n" \ + "a=fmtp:114 profile-level-id=42C00C;packetization-mode=1;sar-understood=16;sar-supported=1;sprop-parameter-sets=Z0LADNoPCmgG0KE1,aM4G4g==\r\n" \ + "a=rtpmap:113 H264/90000\r\n" \ + "a=fmtp:113 profile-level-id=42C00C;packetization-mode=0;sar-understood=16;sar-supported=1;sprop-parameter-sets=Z0LADNoPCmgG0KE1,aM4G4g==\r\n" \ + "a=curr:qos local none\r\n" \ + "a=curr:qos remote none\r\n" \ + "a=des:qos mandatory local sendrecv\r\n" \ + "a=des:qos optional remote sendrecv\r\n" \ + "a=rtcp-fb:* nack\r\n" \ + "a=rtcp-fb:* nack pli\r\n" \ + "a=rtcp-fb:* ccm fir\r\n" \ + "a=rtcp-fb:* ccm tmmbr\r\n" \ + "a=sendrecv\r\n" \ + "a=tcap:1 RTP/AVPF\r\n" \ + "a=pcfg:1 t=1\r\n" \ + "a=extmap:2 urn:3gpp:video-orientation\r\n")); + OpenAPI_list_add(codecList, + ogs_strdup("uplink\nanswer\nm=video 60010 RTP/AVPF 114\r\n" \ + "b=AS:401\r\n" \ + "b=RS:600\r\n" \ + "b=RR:2000\r\n" \ + "a=rtpmap:114 H264/90000\r\n" \ + "a=fmtp:114 profile-level-id=42C00C;packetization-mode=1;sar-understood=16;sar-supported=1;sprop-parameter-sets=Z0LADNoPCmgG0KE1,aM4G4g==\r\n" \ + "a=curr:qos local none\r\n" \ + "a=curr:qos remote none\r\n" \ + "a=des:qos mandatory local sendrecv\r\n" \ + "a=des:qos mandatory remote sendrecv\r\n" \ + "a=conf:qos remote sendrecv\r\n" \ + "a=rtcp-fb:* nack\r\n" \ + "a=rtcp-fb:* nack pli\r\n" \ + "a=rtcp-fb:* ccm fir\r\n" \ + "a=rtcp-fb:* ccm tmmbr\r\n" \ + "a=sendrecv\r\n" \ + "a=extmap:2 urn:3gpp:video-orientation\r\n" \ + "a=acfg:1 t=1\r\n")); + ogs_assert(codecList->count); + MediaComponent->codecs = codecList; + + MediaComponentMap = OpenAPI_map_create( + ogs_msprintf("%d", MediaComponent->med_comp_n), MediaComponent); + ogs_assert(MediaComponentMap); + ogs_assert(MediaComponentMap->key); + + OpenAPI_list_add(MediaComponentList, MediaComponentMap); + + /* Sub Component */ + SubComponentList = OpenAPI_list_create(); + ogs_assert(SubComponentList); + + j = 0; + + /* Sub Component #1 */ + SubComponent = ogs_calloc(1, sizeof(*SubComponent)); + ogs_expect_or_return_val(SubComponent, NULL); + + SubComponent->f_num = (j++); + SubComponent->flow_usage = OpenAPI_flow_usage_NO_INFO; + + SubComponentMap = OpenAPI_map_create( + ogs_msprintf("%d", SubComponent->f_num), SubComponent); + ogs_assert(SubComponentMap); + ogs_assert(SubComponentMap->key); + + OpenAPI_list_add(SubComponentList, SubComponentMap); + + /* Flow Description */ + fDescList = OpenAPI_list_create(); + ogs_assert(fDescList); + OpenAPI_list_add(fDescList, + ogs_strdup("permit out 17 from 10.45.0.5 60010 to 10.45.0.3 60010")); + OpenAPI_list_add(fDescList, + ogs_strdup("permit in 17 from 10.45.0.3 60010 to 10.45.0.5 60010")); + if (fDescList->count) + SubComponent->f_descs = fDescList; + else + OpenAPI_list_free(fDescList); + + /* Sub Component #2 */ + SubComponent = ogs_calloc(1, sizeof(*SubComponent)); + ogs_expect_or_return_val(SubComponent, NULL); + + SubComponent->f_num = (j++); + SubComponent->flow_usage = OpenAPI_flow_usage_NO_INFO; + + SubComponentMap = OpenAPI_map_create( + ogs_msprintf("%d", SubComponent->f_num), SubComponent); + ogs_assert(SubComponentMap); + ogs_assert(SubComponentMap->key); + + OpenAPI_list_add(SubComponentList, SubComponentMap); + + /* Flow Description */ + fDescList = OpenAPI_list_create(); + ogs_assert(fDescList); + OpenAPI_list_add(fDescList, + ogs_strdup("permit out 17 from 10.45.0.5 60011 to 10.45.0.3 60011")); + OpenAPI_list_add(fDescList, + ogs_strdup("permit in 17 from 10.45.0.3 60011 to 10.45.0.5 60011")); + if (fDescList->count) + SubComponent->f_descs = fDescList; + else + OpenAPI_list_free(fDescList); + + ogs_assert(SubComponentList->count); + MediaComponent->med_sub_comps = SubComponentList; + + ogs_assert(MediaComponentList->count); + AscReqData.med_components = MediaComponentList; + + request = ogs_sbi_build_request(&message); + ogs_expect_or_return_val(request, NULL); + + ogs_free(AscReqData.notif_uri); + + ogs_free(AscReqData.supp_feat); + + EventList = evSubsc.events; + OpenAPI_list_for_each(EventList, node) { + Event = node->data; + if (Event) + ogs_free(Event); + } + OpenAPI_list_free(EventList); + + if (sNssai.sd) + ogs_free(sNssai.sd); + + OpenAPI_list_for_each(MediaComponentList, node) { + MediaComponentMap = node->data; + if (MediaComponentMap) { + MediaComponent = MediaComponentMap->value; + if (MediaComponent) { + + if (MediaComponent->mar_bw_dl) + ogs_free(MediaComponent->mar_bw_dl); + if (MediaComponent->mar_bw_ul) + ogs_free(MediaComponent->mar_bw_ul); + if (MediaComponent->mir_bw_dl) + ogs_free(MediaComponent->mir_bw_dl); + if (MediaComponent->mir_bw_ul) + ogs_free(MediaComponent->mir_bw_ul); if (MediaComponent->rr_bw) ogs_free(MediaComponent->rr_bw); if (MediaComponent->rs_bw) diff --git a/tests/af/npcf-build.h b/tests/af/npcf-build.h index 8243551b8..b31bc9b08 100644 --- a/tests/af/npcf-build.h +++ b/tests/af/npcf-build.h @@ -26,8 +26,21 @@ extern "C" { #endif +typedef struct af_npcf_policyauthorization_param_s { + OpenAPI_media_type_e med_type; + int flow_type; + int qos_type; +} af_npcf_policyauthorization_param_t; + ogs_sbi_request_t *af_npcf_policyauthorization_build_create( af_sess_t *sess, void *data); +ogs_sbi_request_t *af_npcf_policyauthorization_build_update( + af_sess_t *sess, void *data); +ogs_sbi_request_t *af_npcf_policyauthorization_build_delete( + af_sess_t *sess, void *data); + +ogs_sbi_request_t *af_npcf_policyauthorization_build_create_video( + af_sess_t *sess, void *data); #ifdef __cplusplus } diff --git a/tests/af/npcf-handler.c b/tests/af/npcf-handler.c index cdcb270f4..b7ceda162 100644 --- a/tests/af/npcf-handler.c +++ b/tests/af/npcf-handler.c @@ -91,3 +91,39 @@ void af_npcf_policyauthorization_handle_create( cleanup: ogs_sbi_header_free(&header); } + +void af_npcf_policyauthorization_handle_update( + af_sess_t *sess, ogs_sbi_message_t *recvmsg) +{ + OpenAPI_app_session_context_update_data_patch_t + *AppSessionContextUpdateDataPatch = NULL; + OpenAPI_app_session_context_update_data_t *AscUpdateData = NULL; + + ogs_assert(sess); + ogs_assert(recvmsg); + + if (!recvmsg->h.resource.component[1]) { + ogs_error("[%s:%s] No AppSessionId[%s]", + sess->ipv4addr ? sess->ipv4addr : "Unknown", + sess->ipv6addr ? sess->ipv6addr : "Unknown", + recvmsg->http.location); + return; + } + + AppSessionContextUpdateDataPatch = + recvmsg->AppSessionContextUpdateDataPatch; + if (!AppSessionContextUpdateDataPatch) { + ogs_error("[%s:%s] No AppSessionContextUpdateDataPatch", + sess->ipv4addr ? sess->ipv4addr : "Unknown", + sess->ipv6addr ? sess->ipv6addr : "Unknown"); + return; + } + + AscUpdateData = AppSessionContextUpdateDataPatch->asc_req_data; + if (!AscUpdateData) { + ogs_error("[%s:%s] No AscUpdateData", + sess->ipv4addr ? sess->ipv4addr : "Unknown", + sess->ipv6addr ? sess->ipv6addr : "Unknown"); + return; + } +} diff --git a/tests/af/npcf-handler.h b/tests/af/npcf-handler.h index d7251b311..f26821132 100644 --- a/tests/af/npcf-handler.h +++ b/tests/af/npcf-handler.h @@ -28,6 +28,8 @@ extern "C" { void af_npcf_policyauthorization_handle_create( af_sess_t *sess, ogs_sbi_message_t *recvmsg); +void af_npcf_policyauthorization_handle_update( + af_sess_t *sess, ogs_sbi_message_t *recvmsg); #ifdef __cplusplus } diff --git a/tests/common/gsm-build.c b/tests/common/gsm-build.c index 9b222b27a..692d81ef4 100644 --- a/tests/common/gsm-build.c +++ b/tests/common/gsm-build.c @@ -84,6 +84,190 @@ ogs_pkbuf_t *testgsm_build_pdu_session_establishment_request( return ogs_nas_5gs_plain_encode(&message); } +ogs_pkbuf_t *testgsm_build_pdu_session_modification_request( + test_bearer_t *qos_flow, uint8_t gsm_cause, + uint8_t qos_rule_code, uint8_t qos_flow_description_code) +{ + int num_of_param, rv; + + ogs_nas_5gs_message_t message; + ogs_nas_5gs_pdu_session_modification_request_t + *pdu_session_modification_request = + &message.gsm.pdu_session_modification_request; + + ogs_nas_qos_rule_t qos_rule[OGS_NAS_MAX_NUM_OF_QOS_RULE]; + ogs_nas_qos_flow_description_t + qos_flow_description[OGS_NAS_MAX_NUM_OF_QOS_FLOW_DESCRIPTION]; + + ogs_nas_qos_rules_t *requested_qos_rules = + &pdu_session_modification_request->requested_qos_rules; + ogs_nas_qos_flow_descriptions_t *requested_qos_flow_descriptions = + &pdu_session_modification_request->requested_qos_flow_descriptions; + + test_ue_t *test_ue = NULL; + test_sess_t *test_sess = NULL; + ogs_pkbuf_t *pkbuf = NULL; + + ogs_ipsubnet_t ipsubnet; + + ogs_assert(qos_flow); + test_sess = qos_flow->sess; + ogs_assert(test_sess); + test_ue = test_sess; + ogs_assert(test_ue); + + memset(&message, 0, sizeof(message)); + + message.gsm.h.extended_protocol_discriminator = + OGS_NAS_EXTENDED_PROTOCOL_DISCRIMINATOR_5GSM; + message.gsm.h.pdu_session_identity = test_sess->psi; + message.gsm.h.procedure_transaction_identity = test_sess->pti; + message.gsm.h.message_type = OGS_NAS_5GS_PDU_SESSION_MODIFICATION_REQUEST; + + if (gsm_cause) { + pdu_session_modification_request->presencemask |= + OGS_NAS_5GS_PDU_SESSION_MODIFICATION_REQUEST_5GSM_CAUSE_PRESENT; + pdu_session_modification_request->gsm_cause = gsm_cause; + } + if (qos_rule_code) { + pdu_session_modification_request->presencemask |= + OGS_NAS_5GS_PDU_SESSION_MODIFICATION_REQUEST_REQUESTED_QOS_RULES_PRESENT; + + memset(qos_rule, 0, sizeof(qos_rule)); + qos_rule[0].identifier = qos_flow->qfi; /* Use QFI in Open5GS */ + qos_rule[0].code = qos_rule_code; + + if (qos_rule_code == + OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_ADD_PACKET_FILTERS) { + qos_rule[0].DQR_bit = 0; + qos_rule[0].num_of_packet_filter = 1; + + qos_rule[0].pf[0].direction = OGS_NAS_QOS_DIRECTION_UPLINK; + qos_rule[0].pf[0].identifier = 4; + + qos_rule[0].pf[0].content.length = 18; + qos_rule[0].pf[0].content.num_of_component = 1; + qos_rule[0].pf[0].content.component[0].type = + OGS_PACKET_FILTER_IPV6_LOCAL_ADDRESS_PREFIX_LENGTH_TYPE; + + rv = ogs_ipsubnet(&ipsubnet, "2001:230:cafe::9", "120"); + ogs_assert(rv == OGS_OK); + + memcpy(qos_rule[0].pf[0].content.component[0].ipv6.addr, + ipsubnet.sub, + sizeof(qos_rule[0].pf[0].content.component[0].ipv6.addr)); + qos_rule[0].pf[0].content.component[0].ipv6.prefixlen = 120; + + } else if (qos_rule_code == + OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_REPLACE_PACKET_FILTERS) { + qos_rule[0].DQR_bit = 0; + qos_rule[0].num_of_packet_filter = 1; + + qos_rule[0].pf[0].direction = OGS_NAS_QOS_DIRECTION_DOWNLINK; + qos_rule[0].pf[0].identifier = 0; + + qos_rule[0].pf[0].content.length = 9; + qos_rule[0].pf[0].content.num_of_component = 1; + qos_rule[0].pf[0].content.component[0].type = + OGS_PACKET_FILTER_IPV4_REMOTE_ADDRESS_TYPE; + + rv = ogs_ipsubnet(&ipsubnet, "201.20.2.5", NULL); + ogs_assert(rv == OGS_OK); + + qos_rule[0].pf[0].content.component[0].ipv4.addr = ipsubnet.sub[0]; + qos_rule[0].pf[0].content.component[0].ipv4.mask = ipsubnet.mask[0]; + + } else if (qos_rule_code == + OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_DELETE_PACKET_FILTERS) { + qos_rule[0].DQR_bit = 0; + qos_rule[0].num_of_packet_filter = 4; + + qos_rule[0].pf[0].identifier = 0; + qos_rule[0].pf[1].identifier = 1; + qos_rule[0].pf[2].identifier = 2; + qos_rule[0].pf[3].identifier = 3; + + } else { + ogs_fatal("Unknown qos_rule_code[%d]", qos_rule_code); + ogs_assert_if_reached(); + } + + qos_rule[0].precedence = 0x0f; /* lowest precedence */ + qos_rule[0].flow.segregation = 0; + qos_rule[0].flow.identifier = qos_flow->qfi; + + rv = ogs_nas_build_qos_rules(requested_qos_rules, qos_rule, 1); + ogs_assert(rv == OGS_OK); + } + if (qos_flow_description_code) { + pdu_session_modification_request->presencemask |= + OGS_NAS_5GS_PDU_SESSION_MODIFICATION_REQUEST_REQUESTED_QOS_FLOW_DESCRIPTIONS_PRESENT; + + memset(&qos_flow_description, 0, sizeof(qos_flow_description)); + qos_flow_description[0].identifier = qos_flow->qfi; + qos_flow_description[0].code = qos_flow_description_code; + + num_of_param = 0; + + if (qos_flow_description_code != + OGS_NAS_DELETE_NEW_QOS_FLOW_DESCRIPTION) { + qos_flow_description[0].E_bit = 1; + + qos_flow_description[0].param[num_of_param].identifier = + OGS_NAX_QOS_FLOW_PARAMETER_ID_5QI; + qos_flow_description[0].param[num_of_param].len = + sizeof(qos_flow_description[0].param[num_of_param].qos_index); + qos_flow_description[0].param[num_of_param].qos_index = 5; + num_of_param++; + + qos_flow_description[0].param[num_of_param].identifier = + OGS_NAX_QOS_FLOW_PARAMETER_ID_GFBR_UPLINK; + qos_flow_description[0].param[num_of_param].len = + sizeof(qos_flow_description[0].param[num_of_param].br); + ogs_nas_bitrate_from_uint64( + &qos_flow_description[0].param[num_of_param].br, + 32*1024); + num_of_param++; + qos_flow_description[0].param[num_of_param].identifier = + OGS_NAX_QOS_FLOW_PARAMETER_ID_GFBR_DOWNLINK; + qos_flow_description[0].param[num_of_param].len = + sizeof(qos_flow_description[0].param[num_of_param].br); + ogs_nas_bitrate_from_uint64( + &qos_flow_description[0].param[num_of_param].br, + 48*1024); + num_of_param++; + qos_flow_description[0].param[num_of_param].identifier = + OGS_NAX_QOS_FLOW_PARAMETER_ID_MFBR_UPLINK; + qos_flow_description[0].param[num_of_param].len = + sizeof(qos_flow_description[0].param[num_of_param].br); + ogs_nas_bitrate_from_uint64( + &qos_flow_description[0].param[num_of_param].br, + 16*1024); + num_of_param++; + qos_flow_description[0].param[num_of_param].identifier = + OGS_NAX_QOS_FLOW_PARAMETER_ID_MFBR_DOWNLINK; + qos_flow_description[0].param[num_of_param].len = + sizeof(qos_flow_description[0].param[num_of_param].br); + ogs_nas_bitrate_from_uint64( + &qos_flow_description[0].param[num_of_param].br, + 64*1024); + num_of_param++; + } + + qos_flow_description[0].num_of_parameter = num_of_param; + + rv = ogs_nas_build_qos_flow_descriptions( + requested_qos_flow_descriptions, qos_flow_description, 1); + } + + pkbuf = ogs_nas_5gs_plain_encode(&message); + + ogs_free(requested_qos_rules->buffer); + ogs_free(requested_qos_flow_descriptions->buffer); + + return pkbuf; +} + ogs_pkbuf_t *testgsm_build_pdu_session_modification_complete( test_sess_t *test_sess) { diff --git a/tests/common/gsm-build.h b/tests/common/gsm-build.h index 495ee983c..a48479e24 100644 --- a/tests/common/gsm-build.h +++ b/tests/common/gsm-build.h @@ -26,6 +26,9 @@ extern "C" { ogs_pkbuf_t *testgsm_build_pdu_session_establishment_request( test_sess_t *test_sess); +ogs_pkbuf_t *testgsm_build_pdu_session_modification_request( + test_bearer_t *bearer, uint8_t gsm_cause, + uint8_t qos_rule_code, uint8_t qos_flow_description_code); ogs_pkbuf_t *testgsm_build_pdu_session_modification_complete( test_sess_t *test_sess); ogs_pkbuf_t *testgsm_build_pdu_session_release_request(test_sess_t *test_sess); diff --git a/tests/common/ngap-build.c b/tests/common/ngap-build.c index ddbdb3030..e63ebe116 100644 --- a/tests/common/ngap-build.c +++ b/tests/common/ngap-build.c @@ -21,7 +21,9 @@ static ogs_pkbuf_t *testngap_build_pdu_session_resource_setup_response_trasfer( test_sess_t *sess); -static ogs_pkbuf_t *testngap_build_pdu_session_resource_modify_response_trasfer( +static ogs_pkbuf_t *testngap_build_qos_flow_resource_modify_response_trasfer( + test_bearer_t *qos_flow); +static ogs_pkbuf_t *testngap_build_qos_flow_resource_release_response_trasfer( test_bearer_t *qos_flow); static ogs_pkbuf_t *testngap_build_path_switch_request_trasfer( test_sess_t *sess); @@ -1067,7 +1069,7 @@ ogs_pkbuf_t *testngap_sess_build_pdu_session_resource_setup_response( return ogs_ngap_encode(&pdu); } -ogs_pkbuf_t *testngap_build_pdu_session_resource_modify_response( +ogs_pkbuf_t *testngap_build_qos_flow_resource_modify_response( test_bearer_t *qos_flow) { int rv; @@ -1147,7 +1149,100 @@ ogs_pkbuf_t *testngap_build_pdu_session_resource_modify_response( PDUSessionItem->pDUSessionID = sess->psi; - n2smbuf = testngap_build_pdu_session_resource_modify_response_trasfer( + n2smbuf = testngap_build_qos_flow_resource_modify_response_trasfer( + qos_flow); + ogs_assert(n2smbuf); + transfer = &PDUSessionItem->pDUSessionResourceModifyResponseTransfer; + + transfer->size = n2smbuf->len; + transfer->buf = CALLOC(transfer->size, sizeof(uint8_t)); + memcpy(transfer->buf, n2smbuf->data, transfer->size); + ogs_pkbuf_free(n2smbuf); + + return ogs_ngap_encode(&pdu); +} + +ogs_pkbuf_t *testngap_build_qos_flow_resource_release_response( + test_bearer_t *qos_flow) +{ + int rv; + + test_ue_t *test_ue = NULL; + test_sess_t *sess = NULL; + + ogs_pkbuf_t *n2smbuf = NULL; + ogs_pkbuf_t *ngapbuf = NULL; + + NGAP_NGAP_PDU_t pdu; + NGAP_SuccessfulOutcome_t *successfulOutcome = NULL; + NGAP_PDUSessionResourceModifyResponse_t *PDUSessionResourceModifyResponse; + + NGAP_PDUSessionResourceModifyResponseIEs_t *ie = NULL; + NGAP_AMF_UE_NGAP_ID_t *AMF_UE_NGAP_ID = NULL; + NGAP_RAN_UE_NGAP_ID_t *RAN_UE_NGAP_ID = NULL; + NGAP_PDUSessionResourceModifyListModRes_t *PDUSessionList = NULL; + NGAP_PDUSessionResourceModifyItemModRes_t *PDUSessionItem = NULL; + OCTET_STRING_t *transfer = NULL; + + ogs_assert(qos_flow); + sess = qos_flow->sess; + ogs_assert(sess); + test_ue = sess->test_ue; + ogs_assert(test_ue); + + memset(&pdu, 0, sizeof (NGAP_NGAP_PDU_t)); + pdu.present = NGAP_NGAP_PDU_PR_successfulOutcome; + pdu.choice.successfulOutcome = CALLOC(1, sizeof(NGAP_SuccessfulOutcome_t)); + + successfulOutcome = pdu.choice.successfulOutcome; + successfulOutcome->procedureCode = + NGAP_ProcedureCode_id_PDUSessionResourceModify; + successfulOutcome->criticality = NGAP_Criticality_reject; + successfulOutcome->value.present = + NGAP_SuccessfulOutcome__value_PR_PDUSessionResourceModifyResponse; + + PDUSessionResourceModifyResponse = + &successfulOutcome->value.choice.PDUSessionResourceModifyResponse; + + ie = CALLOC(1, sizeof(NGAP_PDUSessionResourceModifyResponseIEs_t)); + ASN_SEQUENCE_ADD(&PDUSessionResourceModifyResponse->protocolIEs, ie); + + ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = + NGAP_PDUSessionResourceModifyResponseIEs__value_PR_AMF_UE_NGAP_ID; + + AMF_UE_NGAP_ID = &ie->value.choice.AMF_UE_NGAP_ID; + + ie = CALLOC(1, sizeof(NGAP_PDUSessionResourceModifyResponseIEs_t)); + ASN_SEQUENCE_ADD(&PDUSessionResourceModifyResponse->protocolIEs, ie); + + ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_ignore; + ie->value.present = + NGAP_PDUSessionResourceModifyResponseIEs__value_PR_RAN_UE_NGAP_ID; + + RAN_UE_NGAP_ID = &ie->value.choice.RAN_UE_NGAP_ID; + + ie = CALLOC(1, sizeof(NGAP_PDUSessionResourceModifyResponseIEs_t)); + ASN_SEQUENCE_ADD(&PDUSessionResourceModifyResponse->protocolIEs, ie); + + ie->id = NGAP_ProtocolIE_ID_id_PDUSessionResourceModifyListModRes; + ie->criticality = NGAP_Criticality_reject; + ie->value.present = NGAP_PDUSessionResourceModifyResponseIEs__value_PR_PDUSessionResourceModifyListModRes; + + PDUSessionList = &ie->value.choice.PDUSessionResourceModifyListModRes; + + asn_uint642INTEGER(AMF_UE_NGAP_ID, test_ue->amf_ue_ngap_id); + *RAN_UE_NGAP_ID = test_ue->ran_ue_ngap_id; + + PDUSessionItem = + CALLOC(1, sizeof(struct NGAP_PDUSessionResourceModifyItemModRes)); + ASN_SEQUENCE_ADD(&PDUSessionList->list, PDUSessionItem); + + PDUSessionItem->pDUSessionID = sess->psi; + + n2smbuf = testngap_build_qos_flow_resource_release_response_trasfer( qos_flow); ogs_assert(n2smbuf); transfer = &PDUSessionItem->pDUSessionResourceModifyResponseTransfer; @@ -2165,7 +2260,7 @@ static ogs_pkbuf_t *testngap_build_pdu_session_resource_setup_response_trasfer( &asn_DEF_NGAP_PDUSessionResourceSetupResponseTransfer, &message); } -static ogs_pkbuf_t *testngap_build_pdu_session_resource_modify_response_trasfer( +static ogs_pkbuf_t *testngap_build_qos_flow_resource_modify_response_trasfer( test_bearer_t *qos_flow) { ogs_assert(qos_flow); @@ -2191,6 +2286,18 @@ static ogs_pkbuf_t *testngap_build_pdu_session_resource_modify_response_trasfer( &asn_DEF_NGAP_PDUSessionResourceModifyResponseTransfer, &message); } +static ogs_pkbuf_t *testngap_build_qos_flow_resource_release_response_trasfer( + test_bearer_t *qos_flow) +{ + ogs_assert(qos_flow); + + NGAP_PDUSessionResourceModifyResponseTransfer_t message; + memset(&message, 0, sizeof(message)); + + return ogs_asn_encode( + &asn_DEF_NGAP_PDUSessionResourceModifyResponseTransfer, &message); +} + static ogs_pkbuf_t *testngap_build_path_switch_request_trasfer( test_sess_t *sess) { diff --git a/tests/common/ngap-build.h b/tests/common/ngap-build.h index 1bb69c011..50f3fff4f 100644 --- a/tests/common/ngap-build.h +++ b/tests/common/ngap-build.h @@ -49,7 +49,9 @@ ogs_pkbuf_t *testngap_ue_build_pdu_session_resource_setup_response( test_ue_t *test_ue); ogs_pkbuf_t *testngap_sess_build_pdu_session_resource_setup_response( test_sess_t *sess); -ogs_pkbuf_t *testngap_build_pdu_session_resource_modify_response( +ogs_pkbuf_t *testngap_build_qos_flow_resource_modify_response( + test_bearer_t *qos_flow); +ogs_pkbuf_t *testngap_build_qos_flow_resource_release_response( test_bearer_t *qos_flow); ogs_pkbuf_t *testngap_build_pdu_session_resource_release_response( test_sess_t *sess); diff --git a/tests/handover/5gc-n2-test.c b/tests/handover/5gc-n2-test.c index 46b5d82e7..6637b77f7 100644 --- a/tests/handover/5gc-n2-test.c +++ b/tests/handover/5gc-n2-test.c @@ -304,7 +304,7 @@ static void failure_func(abts_case *tc, void *data) qos_flow = test_qos_flow_find_by_qfi(sess, 2); ogs_assert(qos_flow); - sendbuf = testngap_build_pdu_session_resource_modify_response(qos_flow); + sendbuf = testngap_build_qos_flow_resource_modify_response(qos_flow); ABTS_PTR_NOTNULL(tc, sendbuf); rv = testgnb_ngap_send(ngap1, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); @@ -706,7 +706,7 @@ static void direct_complete_func(abts_case *tc, void *data) qos_flow = test_qos_flow_find_by_qfi(sess, 2); ogs_assert(qos_flow); - sendbuf = testngap_build_pdu_session_resource_modify_response(qos_flow); + sendbuf = testngap_build_qos_flow_resource_modify_response(qos_flow); ABTS_PTR_NOTNULL(tc, sendbuf); rv = testgnb_ngap_send(ngap1, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); @@ -1324,7 +1324,7 @@ static void direct_cancel_func(abts_case *tc, void *data) qos_flow = test_qos_flow_find_by_qfi(sess, 2); ogs_assert(qos_flow); - sendbuf = testngap_build_pdu_session_resource_modify_response(qos_flow); + sendbuf = testngap_build_qos_flow_resource_modify_response(qos_flow); ABTS_PTR_NOTNULL(tc, sendbuf); rv = testgnb_ngap_send(ngap1, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); @@ -1742,7 +1742,7 @@ static void indirect_complete_func(abts_case *tc, void *data) qos_flow = test_qos_flow_find_by_qfi(sess, 2); ogs_assert(qos_flow); - sendbuf = testngap_build_pdu_session_resource_modify_response(qos_flow); + sendbuf = testngap_build_qos_flow_resource_modify_response(qos_flow); ABTS_PTR_NOTNULL(tc, sendbuf); rv = testgnb_ngap_send(ngap1, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); @@ -2396,7 +2396,7 @@ static void indirect_cancel_func(abts_case *tc, void *data) qos_flow = test_qos_flow_find_by_qfi(sess, 2); ogs_assert(qos_flow); - sendbuf = testngap_build_pdu_session_resource_modify_response(qos_flow); + sendbuf = testngap_build_qos_flow_resource_modify_response(qos_flow); ABTS_PTR_NOTNULL(tc, sendbuf); rv = testgnb_ngap_send(ngap1, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); diff --git a/tests/handover/5gc-xn-test.c b/tests/handover/5gc-xn-test.c index 4b2ffe18d..ea6b10c6b 100644 --- a/tests/handover/5gc-xn-test.c +++ b/tests/handover/5gc-xn-test.c @@ -271,7 +271,7 @@ static void test1_func(abts_case *tc, void *data) qos_flow = test_qos_flow_find_by_qfi(sess, 2); ogs_assert(qos_flow); - sendbuf = testngap_build_pdu_session_resource_modify_response(qos_flow); + sendbuf = testngap_build_qos_flow_resource_modify_response(qos_flow); ABTS_PTR_NOTNULL(tc, sendbuf); rv = testgnb_ngap_send(ngap1, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); diff --git a/tests/registration/paging-test.c b/tests/registration/paging-test.c index 17c4eec44..a410b5420 100644 --- a/tests/registration/paging-test.c +++ b/tests/registration/paging-test.c @@ -1444,7 +1444,7 @@ static void vonr_qos_flow_test1_func(abts_case *tc, void *data) qos_flow = test_qos_flow_find_by_qfi(sess, 2); ogs_assert(qos_flow); - sendbuf = testngap_build_pdu_session_resource_modify_response(qos_flow); + sendbuf = testngap_build_qos_flow_resource_modify_response(qos_flow); ABTS_PTR_NOTNULL(tc, sendbuf); rv = testgnb_ngap_send(ngap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); @@ -1877,7 +1877,7 @@ static void vonr_session_test2_func(abts_case *tc, void *data) qos_flow = test_qos_flow_find_by_qfi(sess, 2); ogs_assert(qos_flow); - sendbuf = testngap_build_pdu_session_resource_modify_response(qos_flow); + sendbuf = testngap_build_qos_flow_resource_modify_response(qos_flow); ABTS_PTR_NOTNULL(tc, sendbuf); rv = testgnb_ngap_send(ngap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); diff --git a/tests/vonr/abts-main.c b/tests/vonr/abts-main.c index e48fa8611..f55790039 100644 --- a/tests/vonr/abts-main.c +++ b/tests/vonr/abts-main.c @@ -23,6 +23,7 @@ abts_suite *test_qos_flow(abts_suite *suite); abts_suite *test_session(abts_suite *suite); abts_suite *test_af(abts_suite *suite); +abts_suite *test_video(abts_suite *suite); const struct testlist { abts_suite *(*func)(abts_suite *suite); @@ -30,6 +31,7 @@ const struct testlist { {test_qos_flow}, {test_session}, {test_af}, + {test_video}, {NULL}, }; diff --git a/tests/vonr/af-test.c b/tests/vonr/af-test.c index 789bf1a20..30db2e10c 100644 --- a/tests/vonr/af-test.c +++ b/tests/vonr/af-test.c @@ -44,6 +44,7 @@ static void test1_func(abts_case *tc, void *data) test_bearer_t *qos_flow = NULL; af_sess_t *af_sess = NULL; + af_npcf_policyauthorization_param_t af_param; bson_t *doc = NULL; @@ -258,7 +259,6 @@ static void test1_func(abts_case *tc, void *data) ABTS_PTR_NOTNULL(tc, recvbuf); testgtpu_recv(test_ue, recvbuf); -#if 0 /* Send PDU session establishment request */ sess = test_sess_add_by_dnn_and_psi(test_ue, "ims", 6); ogs_assert(sess); @@ -291,27 +291,3622 @@ static void test1_func(abts_case *tc, void *data) ABTS_PTR_NOTNULL(tc, sendbuf); rv = testgnb_ngap_send(ngap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); -#endif /* Add AF-Session */ af_sess = af_sess_add_by_ue_address(&sess->ue_ip); ogs_assert(af_sess); + af_sess->supi = ogs_strdup(test_ue->supi); + ogs_assert(af_sess->supi); + af_sess->dnn = ogs_strdup(sess->dnn); ogs_assert(af_sess->dnn); -#if 0 af_local_discover_and_send(OpenAPI_nf_type_BSF, af_sess, NULL, af_nbsf_management_build_discover); /* Wait for PCF-Discovery */ ogs_msleep(100); - af_local_send_to_pcf(af_sess, NULL, + /* Send AF-Session : CREATE */ + memset(&af_param, 0, sizeof(af_param)); + af_param.med_type = OpenAPI_media_type_AUDIO; + af_param.qos_type = 1; + af_param.flow_type = 99; /* For ping test */ + + af_local_send_to_pcf(af_sess, &af_param, af_npcf_policyauthorization_build_create); + /* Receive PDUSessionResourceModifyRequest + + * DL NAS transport + + * PDU session modification command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceModify, + test_ue->ngap_procedure_code); + + /* Send PDU session resource modify response */ + qos_flow = test_qos_flow_find_by_qfi(sess, 2); + ogs_assert(qos_flow); + + sendbuf = testngap_build_qos_flow_resource_modify_response(qos_flow); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDU session resource modify complete */ + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_MODIFICATION_REQUEST; + sess->ul_nas_transport_param.dnn = 0; + sess->ul_nas_transport_param.s_nssai = 0; + + sess->pdu_session_establishment_param.ssc_mode = 0; + sess->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_modification_complete(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Wait for PDU session resource modify complete */ + ogs_msleep(100); + + /* Send GTP-U ICMP Packet */ + qos_flow = test_qos_flow_find_by_qfi(sess, 2); + ogs_assert(qos_flow); + rv = test_gtpu_send_ping(gtpu, qos_flow, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = testgnb_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Waiting for creating dedicated QoS flow in PFCP protocol */ + ogs_msleep(100); + + /* Send AF-Session : UPDATE */ + memset(&af_param, 0, sizeof(af_param)); + af_param.med_type = OpenAPI_media_type_AUDIO; + af_param.qos_type = 2; + af_param.flow_type = 99; + + af_local_send_to_pcf(af_sess, &af_param, + af_npcf_policyauthorization_build_update); + + /* Receive PDUSessionResourceModifyRequest + + * DL NAS transport + + * PDU session modification command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceModify, + test_ue->ngap_procedure_code); + + /* Send PDU session resource modify response */ + qos_flow = test_qos_flow_find_by_qfi(sess, 2); + ogs_assert(qos_flow); + + sendbuf = testngap_build_qos_flow_resource_modify_response(qos_flow); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDU session resource modify complete */ + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_MODIFICATION_REQUEST; + sess->ul_nas_transport_param.dnn = 0; + sess->ul_nas_transport_param.s_nssai = 0; + + sess->pdu_session_establishment_param.ssc_mode = 0; + sess->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_modification_complete(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Wait for PDU session resource modify complete */ + ogs_msleep(100); + + /* Send PDU session modification request */ + sess->pti = 8; + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_MODIFICATION_REQUEST; + sess->ul_nas_transport_param.dnn = 1; + sess->ul_nas_transport_param.s_nssai = 1; + + sess->pdu_session_establishment_param.ssc_mode = 1; + sess->pdu_session_establishment_param.epco = 1; + + gsmbuf = testgsm_build_pdu_session_modification_request( + qos_flow, + 0, + OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_ADD_PACKET_FILTERS, + OGS_NAS_MODIFY_NEW_QOS_FLOW_DESCRIPTION); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDUSessionResourceModifyRequest + + * DL NAS transport + + * PDU session modification command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceModify, + test_ue->ngap_procedure_code); + + /* Send PDU session resource modify response */ + qos_flow = test_qos_flow_find_by_qfi(sess, 2); + ogs_assert(qos_flow); + + sendbuf = testngap_build_qos_flow_resource_modify_response(qos_flow); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDU session resource modify complete */ + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_MODIFICATION_REQUEST; + sess->ul_nas_transport_param.dnn = 0; + sess->ul_nas_transport_param.s_nssai = 0; + + sess->pdu_session_establishment_param.ssc_mode = 0; + sess->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_modification_complete(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Wait for PDU session resource modify complete */ + ogs_msleep(100); + + /* Send PDU session modification request */ + sess->pti = 9; + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_MODIFICATION_REQUEST; + sess->ul_nas_transport_param.dnn = 1; + sess->ul_nas_transport_param.s_nssai = 1; + + sess->pdu_session_establishment_param.ssc_mode = 1; + sess->pdu_session_establishment_param.epco = 1; + + gsmbuf = testgsm_build_pdu_session_modification_request( + qos_flow, + 0, + OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_REPLACE_PACKET_FILTERS, + 0); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDUSessionResourceModifyRequest + + * DL NAS transport + + * PDU session modification command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceModify, + test_ue->ngap_procedure_code); + + /* Send PDU session resource modify response */ + qos_flow = test_qos_flow_find_by_qfi(sess, 2); + ogs_assert(qos_flow); + + sendbuf = testngap_build_qos_flow_resource_modify_response(qos_flow); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDU session resource modify complete */ + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_MODIFICATION_REQUEST; + sess->ul_nas_transport_param.dnn = 0; + sess->ul_nas_transport_param.s_nssai = 0; + + sess->pdu_session_establishment_param.ssc_mode = 0; + sess->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_modification_complete(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Wait for PDU session resource modify complete */ + ogs_msleep(100); + + /* Send PDU session modification request */ + sess->pti = 10; + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_MODIFICATION_REQUEST; + sess->ul_nas_transport_param.dnn = 1; + sess->ul_nas_transport_param.s_nssai = 1; + + sess->pdu_session_establishment_param.ssc_mode = 1; + sess->pdu_session_establishment_param.epco = 1; + + gsmbuf = testgsm_build_pdu_session_modification_request( + qos_flow, + OGS_5GSM_CAUSE_REGULAR_DEACTIVATION, + OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_DELETE_PACKET_FILTERS, + 0); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDUSessionResourceModifyRequest + + * DL NAS transport + + * PDU session modification command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceModify, + test_ue->ngap_procedure_code); + + /* Send PDU session resource modify response */ + qos_flow = test_qos_flow_find_by_qfi(sess, 2); + ogs_assert(qos_flow); + + sendbuf = testngap_build_qos_flow_resource_modify_response(qos_flow); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDU session resource modify complete */ + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_MODIFICATION_REQUEST; + sess->ul_nas_transport_param.dnn = 0; + sess->ul_nas_transport_param.s_nssai = 0; + + sess->pdu_session_establishment_param.ssc_mode = 0; + sess->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_modification_complete(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send AF-Session : DELETE */ + af_local_send_to_pcf(af_sess, NULL, + af_npcf_policyauthorization_build_delete); + + /* Receive PDUSessionResourceModifyRequest + + * DL NAS transport + + * PDU session modification command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceModify, + test_ue->ngap_procedure_code); + + /* Send PDU session resource modify response */ + qos_flow = test_qos_flow_find_by_qfi(sess, 2); + ogs_assert(qos_flow); + + sendbuf = testngap_build_qos_flow_resource_release_response(qos_flow); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDU session resource modify complete */ + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_MODIFICATION_REQUEST; + sess->ul_nas_transport_param.dnn = 0; + sess->ul_nas_transport_param.s_nssai = 0; + + sess->pdu_session_establishment_param.ssc_mode = 0; + sess->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_modification_complete(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Wait for PDU session resource modify complete */ + ogs_msleep(100); + + /* Test Bearer Remove */ + test_bearer_remove(qos_flow); + + /* Send De-registration request */ + gmmbuf = testgmm_build_de_registration_request(test_ue, 1); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive UEContextReleaseCommand */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_UEContextRelease, + test_ue->ngap_procedure_code); + + /* Send UEContextReleaseComplete */ + sendbuf = testngap_build_ue_context_release_complete(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + ogs_msleep(300); -#endif + + /********** Remove Subscriber in Database */ + ABTS_INT_EQUAL(tc, OGS_OK, test_db_remove_ue(test_ue)); + + /* gNB disonncect from UPF */ + testgnb_gtpu_close(gtpu); + + /* gNB disonncect from AMF */ + testgnb_ngap_close(ngap); + + /* Clear Test UE Context */ + test_ue_remove(test_ue); +} + +static void test2_func(abts_case *tc, void *data) +{ + int rv; + ogs_socknode_t *ngap; + ogs_socknode_t *gtpu; + ogs_pkbuf_t *gmmbuf; + ogs_pkbuf_t *gsmbuf; + ogs_pkbuf_t *nasbuf; + ogs_pkbuf_t *sendbuf; + ogs_pkbuf_t *recvbuf; + ogs_ngap_message_t message; + int i; + + uint8_t tmp[OGS_MAX_SDU_LEN]; + char *_gtp_payload = "34ff0024" + "0000000100000085 010002004500001c 0c0b000040015a7a 0a2d00010a2d0002" + "00000964cd7c291f"; + + ogs_nas_5gs_mobile_identity_suci_t mobile_identity_suci; + test_ue_t *test_ue = NULL; + test_sess_t *sess = NULL; + test_bearer_t *qos_flow = NULL; + + af_sess_t *af_sess = NULL; + af_npcf_policyauthorization_param_t af_param; + + bson_t *doc = NULL; + + /* Setup Test UE & Session Context */ + memset(&mobile_identity_suci, 0, sizeof(mobile_identity_suci)); + + mobile_identity_suci.h.supi_format = OGS_NAS_5GS_SUPI_FORMAT_IMSI; + mobile_identity_suci.h.type = OGS_NAS_5GS_MOBILE_IDENTITY_SUCI; + mobile_identity_suci.routing_indicator1 = 0; + mobile_identity_suci.routing_indicator2 = 0xf; + mobile_identity_suci.routing_indicator3 = 0xf; + mobile_identity_suci.routing_indicator4 = 0xf; + mobile_identity_suci.protection_scheme_id = OGS_NAS_5GS_NULL_SCHEME; + mobile_identity_suci.home_network_pki_value = 0; + mobile_identity_suci.scheme_output[0] = 0; + mobile_identity_suci.scheme_output[1] = 0; + mobile_identity_suci.scheme_output[2] = 0x20; + mobile_identity_suci.scheme_output[3] = 0x31; + mobile_identity_suci.scheme_output[4] = 0x90; + + test_ue = test_ue_add_by_suci(&mobile_identity_suci, 13); + ogs_assert(test_ue); + + test_ue->nr_cgi.cell_id = 0x40001; + + test_ue->nas.registration.tsc = 0; + test_ue->nas.registration.ksi = OGS_NAS_KSI_NO_KEY_IS_AVAILABLE; + test_ue->nas.registration.follow_on_request = 1; + test_ue->nas.registration.value = OGS_NAS_5GS_REGISTRATION_TYPE_INITIAL; + + test_ue->k_string = "465b5ce8b199b49faa5f0a2ee238a6bc"; + test_ue->opc_string = "e8ed289deba952e4283b54e88e6183ca"; + + /* gNB connects to AMF */ + ngap = testngap_client(AF_INET); + ABTS_PTR_NOTNULL(tc, ngap); + + /* gNB connects to UPF */ + gtpu = test_gtpu_server(1, AF_INET); + ABTS_PTR_NOTNULL(tc, gtpu); + + /* Send NG-Setup Reqeust */ + sendbuf = testngap_build_ng_setup_request(0x4000, 22); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive NG-Setup Response */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /********** Insert Subscriber in Database */ + doc = test_db_new_session(test_ue); + ABTS_PTR_NOTNULL(tc, doc); + ABTS_INT_EQUAL(tc, OGS_OK, test_db_insert_ue(test_ue, doc)); + + /* Send Registration request */ + test_ue->registration_request_param.guti = 1; + gmmbuf = testgmm_build_registration_request(test_ue, NULL); + ABTS_PTR_NOTNULL(tc, gmmbuf); + + test_ue->registration_request_param.gmm_capability = 1; + test_ue->registration_request_param.requested_nssai = 1; + test_ue->registration_request_param.last_visited_registered_tai = 1; + test_ue->registration_request_param.ue_usage_setting = 1; + nasbuf = testgmm_build_registration_request(test_ue, NULL); + ABTS_PTR_NOTNULL(tc, nasbuf); + + sendbuf = testngap_build_initial_ue_message(test_ue, gmmbuf, false, true); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Identity request */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Identity response */ + gmmbuf = testgmm_build_identity_response(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Authentication request */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Authentication response */ + gmmbuf = testgmm_build_authentication_response(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Security mode command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Security mode complete */ + gmmbuf = testgmm_build_security_mode_complete(test_ue, nasbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive InitialContextSetupRequest + + * Registration accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_InitialContextSetup, + test_ue->ngap_procedure_code); + + /* Send UERadioCapabilityInfoIndication */ + sendbuf = testngap_build_ue_radio_capability_info_indication(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send InitialContextSetupResponse */ + sendbuf = testngap_build_initial_context_setup_response(test_ue, false); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Registration complete */ + gmmbuf = testgmm_build_registration_complete(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Configuration update command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send PDU session establishment request */ + sess = test_sess_add_by_dnn_and_psi(test_ue, "internet", 5); + ogs_assert(sess); + + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_INITIAL; + sess->ul_nas_transport_param.dnn = 1; + sess->ul_nas_transport_param.s_nssai = 1; + + sess->pdu_session_establishment_param.ssc_mode = 1; + sess->pdu_session_establishment_param.epco = 1; + + gsmbuf = testgsm_build_pdu_session_establishment_request(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDUSessionResourceSetupRequest + + * DL NAS transport + + * PDU session establishment accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceSetup, + test_ue->ngap_procedure_code); + + /* Send GTP-U ICMP Packet */ + qos_flow = test_qos_flow_find_by_qfi(sess, 1); + ogs_assert(qos_flow); + rv = test_gtpu_send_ping(gtpu, qos_flow, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDUSessionResourceSetupResponse */ + sendbuf = testngap_sess_build_pdu_session_resource_setup_response(sess); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = testgnb_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send GTP-U ICMP Packet */ + rv = test_gtpu_send_ping(gtpu, qos_flow, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = testgnb_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send PDU session establishment request */ + sess = test_sess_add_by_dnn_and_psi(test_ue, "ims", 6); + ogs_assert(sess); + + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_INITIAL; + sess->ul_nas_transport_param.dnn = 1; + sess->ul_nas_transport_param.s_nssai = 1; + + sess->pdu_session_establishment_param.ssc_mode = 1; + sess->pdu_session_establishment_param.epco = 1; + + gsmbuf = testgsm_build_pdu_session_establishment_request(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDU session establishment accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send PDUSessionResourceSetupResponse */ + sendbuf = testngap_sess_build_pdu_session_resource_setup_response(sess); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDUSessionResourceModifyRequest + + * DL NAS transport + + * PDU session modification command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceModify, + test_ue->ngap_procedure_code); + + /* Send PDU session resource modify response */ + qos_flow = test_qos_flow_find_by_qfi(sess, 2); + ogs_assert(qos_flow); + + sendbuf = testngap_build_qos_flow_resource_modify_response(qos_flow); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDU session resource modify complete */ + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_MODIFICATION_REQUEST; + sess->ul_nas_transport_param.dnn = 0; + sess->ul_nas_transport_param.s_nssai = 0; + + sess->pdu_session_establishment_param.ssc_mode = 0; + sess->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_modification_complete(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Wait for PDU session resource modify complete */ + ogs_msleep(100); + + /* Send GTP-U ICMP Packet */ + rv = test_gtpu_send_ping(gtpu, qos_flow, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = testgnb_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Add AF-Session */ + af_sess = af_sess_add_by_ue_address(&sess->ue_ip); + ogs_assert(af_sess); + + af_sess->supi = ogs_strdup(test_ue->supi); + ogs_assert(af_sess->supi); + + af_sess->dnn = ogs_strdup(sess->dnn); + ogs_assert(af_sess->dnn); + + af_local_discover_and_send(OpenAPI_nf_type_BSF, af_sess, NULL, + af_nbsf_management_build_discover); + + /* Wait for PCF-Discovery */ + ogs_msleep(100); + + /* Send AF-Session : CREATE */ + memset(&af_param, 0, sizeof(af_param)); + af_param.med_type = OpenAPI_media_type_AUDIO; + af_param.qos_type = 0; + af_param.flow_type = 1; + + af_local_send_to_pcf(af_sess, &af_param, + af_npcf_policyauthorization_build_create); + + /* Receive PDUSessionResourceModifyRequest + + * DL NAS transport + + * PDU session modification command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceModify, + test_ue->ngap_procedure_code); + + /* Send PDU session resource modify response */ + qos_flow = test_qos_flow_find_by_qfi(sess, 2); + ogs_assert(qos_flow); + + sendbuf = testngap_build_qos_flow_resource_modify_response(qos_flow); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDU session resource modify complete */ + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_MODIFICATION_REQUEST; + sess->ul_nas_transport_param.dnn = 0; + sess->ul_nas_transport_param.s_nssai = 0; + + sess->pdu_session_establishment_param.ssc_mode = 0; + sess->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_modification_complete(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Wait for PDU session resource modify complete */ + ogs_msleep(100); + + /* Send PDU Session release request */ + sess->pti = 9; + sess->ul_nas_transport_param.request_type = 0; + sess->ul_nas_transport_param.dnn = 0; + sess->ul_nas_transport_param.s_nssai = 0; + + sess->pdu_session_establishment_param.ssc_mode = 0; + sess->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_release_request(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDUSessionResourceReleaseCommand + + * DL NAS transport + + * PDU session release command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send PDUSessionResourceReleaseResponse */ + sendbuf = testngap_build_pdu_session_resource_release_response(sess); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send UplinkNASTransport + + * UL NAS trasnport + + * PDU session resource release complete */ + sess->ul_nas_transport_param.request_type = 0; + sess->ul_nas_transport_param.dnn = 0; + sess->ul_nas_transport_param.s_nssai = 0; + + sess->pdu_session_establishment_param.ssc_mode = 0; + sess->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_release_complete(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Wait for PDU session resource release complete */ + ogs_msleep(100); + + /* Test Session Remove */ + test_sess_remove(sess); + + /* Send UEContextReleaseRequest */ + sendbuf = testngap_build_ue_context_release_request(test_ue, + NGAP_Cause_PR_radioNetwork, NGAP_CauseRadioNetwork_user_inactivity, + true); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive UEContextReleaseCommand */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_UEContextRelease, + test_ue->ngap_procedure_code); + + /* Send UEContextReleaseComplete */ + sendbuf = testngap_build_ue_context_release_complete(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + ogs_msleep(300); + + /********** Remove Subscriber in Database */ + ABTS_INT_EQUAL(tc, OGS_OK, test_db_remove_ue(test_ue)); + + /* gNB disonncect from UPF */ + testgnb_gtpu_close(gtpu); + + /* gNB disonncect from AMF */ + testgnb_ngap_close(ngap); + + /* Clear Test UE Context */ + test_ue_remove(test_ue); +} + +static void test3_func(abts_case *tc, void *data) +{ + int rv; + ogs_socknode_t *ngap; + ogs_socknode_t *gtpu; + ogs_pkbuf_t *gmmbuf; + ogs_pkbuf_t *gsmbuf; + ogs_pkbuf_t *nasbuf; + ogs_pkbuf_t *sendbuf; + ogs_pkbuf_t *recvbuf; + ogs_ngap_message_t message; + int i; + + uint8_t tmp[OGS_MAX_SDU_LEN]; + char *_gtp_payload = "34ff0024" + "0000000100000085 010002004500001c 0c0b000040015a7a 0a2d00010a2d0002" + "00000964cd7c291f"; + + ogs_nas_5gs_mobile_identity_suci_t mobile_identity_suci; + test_ue_t *test_ue = NULL; + test_sess_t *sess = NULL; + test_bearer_t *qos_flow = NULL; + + af_sess_t *af_sess = NULL; + af_npcf_policyauthorization_param_t af_param; + + bson_t *doc = NULL; + + /* Setup Test UE & Session Context */ + memset(&mobile_identity_suci, 0, sizeof(mobile_identity_suci)); + + mobile_identity_suci.h.supi_format = OGS_NAS_5GS_SUPI_FORMAT_IMSI; + mobile_identity_suci.h.type = OGS_NAS_5GS_MOBILE_IDENTITY_SUCI; + mobile_identity_suci.routing_indicator1 = 0; + mobile_identity_suci.routing_indicator2 = 0xf; + mobile_identity_suci.routing_indicator3 = 0xf; + mobile_identity_suci.routing_indicator4 = 0xf; + mobile_identity_suci.protection_scheme_id = OGS_NAS_5GS_NULL_SCHEME; + mobile_identity_suci.home_network_pki_value = 0; + mobile_identity_suci.scheme_output[0] = 0; + mobile_identity_suci.scheme_output[1] = 0; + mobile_identity_suci.scheme_output[2] = 0x20; + mobile_identity_suci.scheme_output[3] = 0x31; + mobile_identity_suci.scheme_output[4] = 0x90; + + test_ue = test_ue_add_by_suci(&mobile_identity_suci, 13); + ogs_assert(test_ue); + + test_ue->nr_cgi.cell_id = 0x40001; + + test_ue->nas.registration.tsc = 0; + test_ue->nas.registration.ksi = OGS_NAS_KSI_NO_KEY_IS_AVAILABLE; + test_ue->nas.registration.follow_on_request = 1; + test_ue->nas.registration.value = OGS_NAS_5GS_REGISTRATION_TYPE_INITIAL; + + test_ue->k_string = "465b5ce8b199b49faa5f0a2ee238a6bc"; + test_ue->opc_string = "e8ed289deba952e4283b54e88e6183ca"; + + /* gNB connects to AMF */ + ngap = testngap_client(AF_INET); + ABTS_PTR_NOTNULL(tc, ngap); + + /* gNB connects to UPF */ + gtpu = test_gtpu_server(1, AF_INET); + ABTS_PTR_NOTNULL(tc, gtpu); + + /* Send NG-Setup Reqeust */ + sendbuf = testngap_build_ng_setup_request(0x4000, 22); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive NG-Setup Response */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /********** Insert Subscriber in Database */ + doc = test_db_new_ims(test_ue); + ABTS_PTR_NOTNULL(tc, doc); + ABTS_INT_EQUAL(tc, OGS_OK, test_db_insert_ue(test_ue, doc)); + + /* Send Registration request */ + test_ue->registration_request_param.guti = 1; + gmmbuf = testgmm_build_registration_request(test_ue, NULL); + ABTS_PTR_NOTNULL(tc, gmmbuf); + + test_ue->registration_request_param.gmm_capability = 1; + test_ue->registration_request_param.requested_nssai = 1; + test_ue->registration_request_param.last_visited_registered_tai = 1; + test_ue->registration_request_param.ue_usage_setting = 1; + nasbuf = testgmm_build_registration_request(test_ue, NULL); + ABTS_PTR_NOTNULL(tc, nasbuf); + + sendbuf = testngap_build_initial_ue_message(test_ue, gmmbuf, false, true); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Identity request */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Identity response */ + gmmbuf = testgmm_build_identity_response(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Authentication request */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Authentication response */ + gmmbuf = testgmm_build_authentication_response(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Security mode command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Security mode complete */ + gmmbuf = testgmm_build_security_mode_complete(test_ue, nasbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive InitialContextSetupRequest + + * Registration accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_InitialContextSetup, + test_ue->ngap_procedure_code); + + /* Send UERadioCapabilityInfoIndication */ + sendbuf = testngap_build_ue_radio_capability_info_indication(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send InitialContextSetupResponse */ + sendbuf = testngap_build_initial_context_setup_response(test_ue, false); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Registration complete */ + gmmbuf = testgmm_build_registration_complete(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Configuration update command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send PDU session establishment request */ + sess = test_sess_add_by_dnn_and_psi(test_ue, "internet", 5); + ogs_assert(sess); + + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_INITIAL; + sess->ul_nas_transport_param.dnn = 1; + sess->ul_nas_transport_param.s_nssai = 1; + + sess->pdu_session_establishment_param.ssc_mode = 1; + sess->pdu_session_establishment_param.epco = 1; + + gsmbuf = testgsm_build_pdu_session_establishment_request(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDUSessionResourceSetupRequest + + * DL NAS transport + + * PDU session establishment accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceSetup, + test_ue->ngap_procedure_code); + + /* Send GTP-U ICMP Packet */ + qos_flow = test_qos_flow_find_by_qfi(sess, 1); + ogs_assert(qos_flow); + rv = test_gtpu_send_ping(gtpu, qos_flow, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDUSessionResourceSetupResponse */ + sendbuf = testngap_sess_build_pdu_session_resource_setup_response(sess); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = testgnb_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send GTP-U ICMP Packet */ + rv = test_gtpu_send_ping(gtpu, qos_flow, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = testgnb_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send GTP-U Router Solicitation */ + rv = test_gtpu_send_slacc_rs(gtpu, qos_flow); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U Router Advertisement */ + recvbuf = test_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + testgtpu_recv(test_ue, recvbuf); + + /* Send PDU session establishment request */ + sess = test_sess_add_by_dnn_and_psi(test_ue, "ims", 6); + ogs_assert(sess); + + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_INITIAL; + sess->ul_nas_transport_param.dnn = 1; + sess->ul_nas_transport_param.s_nssai = 1; + + sess->pdu_session_establishment_param.ssc_mode = 1; + sess->pdu_session_establishment_param.epco = 1; + + gsmbuf = testgsm_build_pdu_session_establishment_request(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDU session establishment accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send PDUSessionResourceSetupResponse */ + sendbuf = testngap_sess_build_pdu_session_resource_setup_response(sess); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Add AF-Session */ + af_sess = af_sess_add_by_ue_address(&sess->ue_ip); + ogs_assert(af_sess); + + af_sess->supi = ogs_strdup(test_ue->supi); + ogs_assert(af_sess->supi); + + af_sess->dnn = ogs_strdup(sess->dnn); + ogs_assert(af_sess->dnn); + + af_local_discover_and_send(OpenAPI_nf_type_BSF, af_sess, NULL, + af_nbsf_management_build_discover); + + /* Wait for PCF-Discovery */ + ogs_msleep(100); + + /* Send AF-Session : CREATE */ + memset(&af_param, 0, sizeof(af_param)); + af_param.med_type = OpenAPI_media_type_CONTROL; + af_param.qos_type = 0; + af_param.flow_type = 1; + + af_local_send_to_pcf(af_sess, &af_param, + af_npcf_policyauthorization_build_create); + + /* Wait for AF-Session */ + ogs_msleep(100); + + /* Send AF-Session : DELETE */ + af_local_send_to_pcf(af_sess, NULL, + af_npcf_policyauthorization_build_delete); + + /* Wait for AF-Session */ + ogs_msleep(100); + + /* Send PDU Session release request */ + sess->pti = 38; + sess->ul_nas_transport_param.request_type = 0; + sess->ul_nas_transport_param.dnn = 0; + sess->ul_nas_transport_param.s_nssai = 0; + + sess->pdu_session_establishment_param.ssc_mode = 0; + sess->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_release_request(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDUSessionResourceReleaseCommand + + * DL NAS transport + + * PDU session release command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send PDUSessionResourceReleaseResponse */ + sendbuf = testngap_build_pdu_session_resource_release_response(sess); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send UplinkNASTransport + + * UL NAS trasnport + + * PDU session resource release complete */ + sess->ul_nas_transport_param.request_type = 0; + sess->ul_nas_transport_param.dnn = 0; + sess->ul_nas_transport_param.s_nssai = 0; + + sess->pdu_session_establishment_param.ssc_mode = 0; + sess->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_release_complete(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Wait for PDU session resource release complete */ + ogs_msleep(100); + + /* Test Session Remove */ + test_sess_remove(sess); + + /* Send PDU session establishment request */ + sess = test_sess_add_by_dnn_and_psi(test_ue, "ims", 7); + ogs_assert(sess); + sess->pti = 39; + + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_INITIAL; + sess->ul_nas_transport_param.dnn = 1; + sess->ul_nas_transport_param.s_nssai = 1; + + sess->pdu_session_establishment_param.ssc_mode = 1; + sess->pdu_session_establishment_param.epco = 1; + + gsmbuf = testgsm_build_pdu_session_establishment_request(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDU session establishment accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send PDUSessionResourceSetupResponse */ + sendbuf = testngap_sess_build_pdu_session_resource_setup_response(sess); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send De-registration request */ + gmmbuf = testgmm_build_de_registration_request(test_ue, 1); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive UEContextReleaseCommand */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_UEContextRelease, + test_ue->ngap_procedure_code); + + /* Send UEContextReleaseComplete */ + sendbuf = testngap_build_ue_context_release_complete(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + ogs_msleep(300); + + /********** Remove Subscriber in Database */ + ABTS_INT_EQUAL(tc, OGS_OK, test_db_remove_ue(test_ue)); + + /* gNB disonncect from UPF */ + testgnb_gtpu_close(gtpu); + + /* gNB disonncect from AMF */ + testgnb_ngap_close(ngap); + + /* Clear Test UE Context */ + test_ue_remove(test_ue); +} + +static void test4_func(abts_case *tc, void *data) +{ + int rv; + ogs_socknode_t *ngap; + ogs_socknode_t *gtpu; + ogs_pkbuf_t *gmmbuf; + ogs_pkbuf_t *gsmbuf; + ogs_pkbuf_t *nasbuf; + ogs_pkbuf_t *sendbuf; + ogs_pkbuf_t *recvbuf; + ogs_ngap_message_t message; + int i; + + uint8_t tmp[OGS_MAX_SDU_LEN]; + char *_gtp_payload = "34ff0024" + "0000000100000085 010002004500001c 0c0b000040015a7a 0a2d00010a2d0002" + "00000964cd7c291f"; + + ogs_nas_5gs_mobile_identity_suci_t mobile_identity_suci; + test_ue_t *test_ue = NULL; + test_sess_t *sess = NULL; + test_bearer_t *qos_flow = NULL; + + af_sess_t *af_sess = NULL; + af_npcf_policyauthorization_param_t af_param; + + bson_t *doc = NULL; + + /* Setup Test UE & Session Context */ + memset(&mobile_identity_suci, 0, sizeof(mobile_identity_suci)); + + mobile_identity_suci.h.supi_format = OGS_NAS_5GS_SUPI_FORMAT_IMSI; + mobile_identity_suci.h.type = OGS_NAS_5GS_MOBILE_IDENTITY_SUCI; + mobile_identity_suci.routing_indicator1 = 0; + mobile_identity_suci.routing_indicator2 = 0xf; + mobile_identity_suci.routing_indicator3 = 0xf; + mobile_identity_suci.routing_indicator4 = 0xf; + mobile_identity_suci.protection_scheme_id = OGS_NAS_5GS_NULL_SCHEME; + mobile_identity_suci.home_network_pki_value = 0; + mobile_identity_suci.scheme_output[0] = 0; + mobile_identity_suci.scheme_output[1] = 0; + mobile_identity_suci.scheme_output[2] = 0x20; + mobile_identity_suci.scheme_output[3] = 0x31; + mobile_identity_suci.scheme_output[4] = 0x90; + + test_ue = test_ue_add_by_suci(&mobile_identity_suci, 13); + ogs_assert(test_ue); + + test_ue->nr_cgi.cell_id = 0x40001; + + test_ue->nas.registration.tsc = 0; + test_ue->nas.registration.ksi = OGS_NAS_KSI_NO_KEY_IS_AVAILABLE; + test_ue->nas.registration.follow_on_request = 1; + test_ue->nas.registration.value = OGS_NAS_5GS_REGISTRATION_TYPE_INITIAL; + + test_ue->k_string = "465b5ce8b199b49faa5f0a2ee238a6bc"; + test_ue->opc_string = "e8ed289deba952e4283b54e88e6183ca"; + + /* gNB connects to AMF */ + ngap = testngap_client(AF_INET); + ABTS_PTR_NOTNULL(tc, ngap); + + /* gNB connects to UPF */ + gtpu = test_gtpu_server(1, AF_INET); + ABTS_PTR_NOTNULL(tc, gtpu); + + /* Send NG-Setup Reqeust */ + sendbuf = testngap_build_ng_setup_request(0x4000, 22); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive NG-Setup Response */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /********** Insert Subscriber in Database */ + doc = test_db_new_ims(test_ue); + ABTS_PTR_NOTNULL(tc, doc); + ABTS_INT_EQUAL(tc, OGS_OK, test_db_insert_ue(test_ue, doc)); + + /* Send Registration request */ + test_ue->registration_request_param.guti = 1; + gmmbuf = testgmm_build_registration_request(test_ue, NULL); + ABTS_PTR_NOTNULL(tc, gmmbuf); + + test_ue->registration_request_param.gmm_capability = 1; + test_ue->registration_request_param.requested_nssai = 1; + test_ue->registration_request_param.last_visited_registered_tai = 1; + test_ue->registration_request_param.ue_usage_setting = 1; + nasbuf = testgmm_build_registration_request(test_ue, NULL); + ABTS_PTR_NOTNULL(tc, nasbuf); + + sendbuf = testngap_build_initial_ue_message(test_ue, gmmbuf, false, true); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Identity request */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Identity response */ + gmmbuf = testgmm_build_identity_response(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Authentication request */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Authentication response */ + gmmbuf = testgmm_build_authentication_response(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Security mode command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Security mode complete */ + gmmbuf = testgmm_build_security_mode_complete(test_ue, nasbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive InitialContextSetupRequest + + * Registration accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_InitialContextSetup, + test_ue->ngap_procedure_code); + + /* Send UERadioCapabilityInfoIndication */ + sendbuf = testngap_build_ue_radio_capability_info_indication(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send InitialContextSetupResponse */ + sendbuf = testngap_build_initial_context_setup_response(test_ue, false); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Registration complete */ + gmmbuf = testgmm_build_registration_complete(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Configuration update command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send PDU session establishment request */ + sess = test_sess_add_by_dnn_and_psi(test_ue, "internet", 5); + ogs_assert(sess); + sess->pti = 6; + + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_INITIAL; + sess->ul_nas_transport_param.dnn = 1; + sess->ul_nas_transport_param.s_nssai = 1; + + sess->pdu_session_establishment_param.ssc_mode = 1; + sess->pdu_session_establishment_param.epco = 1; + + gsmbuf = testgsm_build_pdu_session_establishment_request(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDUSessionResourceSetupRequest + + * DL NAS transport + + * PDU session establishment accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceSetup, + test_ue->ngap_procedure_code); + + /* Send PDUSessionResourceSetupResponse */ + sendbuf = testngap_sess_build_pdu_session_resource_setup_response(sess); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDU session establishment request */ + sess = test_sess_add_by_dnn_and_psi(test_ue, "ims", 6); + ogs_assert(sess); + sess->pti = 7; + + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_INITIAL; + sess->ul_nas_transport_param.dnn = 1; + sess->ul_nas_transport_param.s_nssai = 1; + + sess->pdu_session_establishment_param.ssc_mode = 1; + sess->pdu_session_establishment_param.epco = 1; + + gsmbuf = testgsm_build_pdu_session_establishment_request(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDU session establishment accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send PDUSessionResourceSetupResponse */ + sendbuf = testngap_sess_build_pdu_session_resource_setup_response(sess); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDU Session release request */ + sess = test_sess_find_by_psi(test_ue, 5); + sess->pti = 8; + + sess->ul_nas_transport_param.request_type = 0; + sess->ul_nas_transport_param.dnn = 0; + sess->ul_nas_transport_param.s_nssai = 0; + + sess->pdu_session_establishment_param.ssc_mode = 0; + sess->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_release_request(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDUSessionResourceReleaseCommand + + * DL NAS transport + + * PDU session release command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send PDUSessionResourceReleaseResponse */ + sendbuf = testngap_build_pdu_session_resource_release_response(sess); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Wait for PDU session resource release complete */ + ogs_msleep(100); + + /* Test Session Remove */ + test_sess_remove(sess); + + /* Send PDU session establishment request */ + sess = test_sess_add_by_dnn_and_psi(test_ue, "internet", 5); + ogs_assert(sess); + sess->pti = 9; + + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_INITIAL; + sess->ul_nas_transport_param.dnn = 1; + sess->ul_nas_transport_param.s_nssai = 1; + + sess->pdu_session_establishment_param.ssc_mode = 1; + sess->pdu_session_establishment_param.epco = 1; + + gsmbuf = testgsm_build_pdu_session_establishment_request(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDUSessionResourceSetupRequest + + * DL NAS transport + + * PDU session establishment accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceSetup, + test_ue->ngap_procedure_code); + + /* Send PDUSessionResourceSetupResponse */ + sendbuf = testngap_sess_build_pdu_session_resource_setup_response(sess); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Add AF-Session */ + sess = test_sess_find_by_psi(test_ue, 6); + + af_sess = af_sess_add_by_ue_address(&sess->ue_ip); + ogs_assert(af_sess); + + af_sess->supi = ogs_strdup(test_ue->supi); + ogs_assert(af_sess->supi); + + af_sess->dnn = ogs_strdup(sess->dnn); + ogs_assert(af_sess->dnn); + + af_local_discover_and_send(OpenAPI_nf_type_BSF, af_sess, NULL, + af_nbsf_management_build_discover); + + /* Wait for PCF-Discovery */ + ogs_msleep(100); + + /* Send AF-Session : CREATE */ + memset(&af_param, 0, sizeof(af_param)); + af_param.med_type = OpenAPI_media_type_AUDIO; + af_param.qos_type = 1; + af_param.flow_type = 1; + + af_local_send_to_pcf(af_sess, &af_param, + af_npcf_policyauthorization_build_create); + + /* Receive PDUSessionResourceModifyRequest + + * DL NAS transport + + * PDU session modification command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceModify, + test_ue->ngap_procedure_code); + + /* Send PDU session resource modify response */ + qos_flow = test_qos_flow_find_by_qfi(sess, 2); + ogs_assert(qos_flow); + + sendbuf = testngap_build_qos_flow_resource_modify_response(qos_flow); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDU session resource modify complete */ + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_MODIFICATION_REQUEST; + sess->ul_nas_transport_param.dnn = 0; + sess->ul_nas_transport_param.s_nssai = 0; + + sess->pdu_session_establishment_param.ssc_mode = 0; + sess->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_modification_complete(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Wait for PDU session resource modify complete */ + ogs_msleep(100); + + /* Send AF-Session : DELETE */ + af_local_send_to_pcf(af_sess, NULL, + af_npcf_policyauthorization_build_delete); + + /* Receive PDUSessionResourceModifyRequest + + * DL NAS transport + + * PDU session modification command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceModify, + test_ue->ngap_procedure_code); + + /* Send PDU session resource modify response */ + qos_flow = test_qos_flow_find_by_qfi(sess, 2); + ogs_assert(qos_flow); + + sendbuf = testngap_build_qos_flow_resource_release_response(qos_flow); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDU session resource modify complete */ + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_MODIFICATION_REQUEST; + sess->ul_nas_transport_param.dnn = 0; + sess->ul_nas_transport_param.s_nssai = 0; + + sess->pdu_session_establishment_param.ssc_mode = 0; + sess->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_modification_complete(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Test Bearer Remove */ + test_bearer_remove(qos_flow); + + /* Wait for PDU session resource modify complete */ + ogs_msleep(100); + + /* Send UEContextReleaseRequest */ + sendbuf = testngap_build_ue_context_release_request(test_ue, + NGAP_Cause_PR_radioNetwork, NGAP_CauseRadioNetwork_user_inactivity, + true); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive UEContextReleaseCommand */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_UEContextRelease, + test_ue->ngap_procedure_code); + + /* Send UEContextReleaseComplete */ + sendbuf = testngap_build_ue_context_release_complete(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + sess = test_sess_find_by_psi(test_ue, 5); + ogs_assert(sess); + test_sess_remove(sess); + sess = test_sess_find_by_psi(test_ue, 6); + ogs_assert(sess); + test_sess_remove(sess); + + /* Send Registration request */ + memset(&test_ue->registration_request_param, 0, + sizeof(test_ue->registration_request_param)); + test_ue->registration_request_param.guti = 1; + gmmbuf = testgmm_build_registration_request(test_ue, NULL); + ABTS_PTR_NOTNULL(tc, gmmbuf); + + test_ue->registration_request_param.gmm_capability = 1; + test_ue->registration_request_param.requested_nssai = 1; + test_ue->registration_request_param.last_visited_registered_tai = 1; + test_ue->registration_request_param.ue_usage_setting = 1; + nasbuf = testgmm_build_registration_request(test_ue, NULL); + ABTS_PTR_NOTNULL(tc, nasbuf); + + sendbuf = testngap_build_initial_ue_message(test_ue, gmmbuf, false, true); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Authentication request */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Authentication response */ + gmmbuf = testgmm_build_authentication_response(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Security mode command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Security mode complete */ + gmmbuf = testgmm_build_security_mode_complete(test_ue, nasbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive InitialContextSetupRequest + + * Registration accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_InitialContextSetup, + test_ue->ngap_procedure_code); + + /* Send UERadioCapabilityInfoIndication */ + sendbuf = testngap_build_ue_radio_capability_info_indication(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send InitialContextSetupResponse */ + sendbuf = testngap_build_initial_context_setup_response(test_ue, false); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Registration complete */ + gmmbuf = testgmm_build_registration_complete(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Configuration update command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send PDU session establishment request */ + sess = test_sess_add_by_dnn_and_psi(test_ue, "internet", 5); + ogs_assert(sess); + sess->pti = 9; + + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_INITIAL; + sess->ul_nas_transport_param.dnn = 1; + sess->ul_nas_transport_param.s_nssai = 1; + + sess->pdu_session_establishment_param.ssc_mode = 1; + sess->pdu_session_establishment_param.epco = 1; + + gsmbuf = testgsm_build_pdu_session_establishment_request(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDUSessionResourceSetupRequest + + * DL NAS transport + + * PDU session establishment accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceSetup, + test_ue->ngap_procedure_code); + + /* Send PDUSessionResourceSetupResponse */ + sendbuf = testngap_sess_build_pdu_session_resource_setup_response(sess); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + + /* Send De-registration request */ + gmmbuf = testgmm_build_de_registration_request(test_ue, 1); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive UEContextReleaseCommand */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_UEContextRelease, + test_ue->ngap_procedure_code); + + /* Send UEContextReleaseComplete */ + sendbuf = testngap_build_ue_context_release_complete(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + ogs_msleep(300); + + /********** Remove Subscriber in Database */ + ABTS_INT_EQUAL(tc, OGS_OK, test_db_remove_ue(test_ue)); + + /* gNB disonncect from UPF */ + testgnb_gtpu_close(gtpu); + + /* gNB disonncect from AMF */ + testgnb_ngap_close(ngap); + + /* Clear Test UE Context */ + test_ue_remove(test_ue); +} + +static void test5_func(abts_case *tc, void *data) +{ + int rv; + ogs_socknode_t *ngap; + ogs_socknode_t *gtpu; + ogs_pkbuf_t *gmmbuf; + ogs_pkbuf_t *gsmbuf; + ogs_pkbuf_t *nasbuf; + ogs_pkbuf_t *sendbuf; + ogs_pkbuf_t *recvbuf; + ogs_ngap_message_t message; + int i; + + uint8_t tmp[OGS_MAX_SDU_LEN]; + char *_gtp_payload = "34ff0024" + "0000000100000085 010002004500001c 0c0b000040015a7a 0a2d00010a2d0002" + "00000964cd7c291f"; + + ogs_nas_5gs_mobile_identity_suci_t mobile_identity_suci; + test_ue_t *test_ue = NULL; + test_sess_t *sess = NULL; + test_bearer_t *qos_flow = NULL; + + af_sess_t *af_sess = NULL; + af_npcf_policyauthorization_param_t af_param; + + bson_t *doc = NULL; + + /* Setup Test UE & Session Context */ + memset(&mobile_identity_suci, 0, sizeof(mobile_identity_suci)); + + mobile_identity_suci.h.supi_format = OGS_NAS_5GS_SUPI_FORMAT_IMSI; + mobile_identity_suci.h.type = OGS_NAS_5GS_MOBILE_IDENTITY_SUCI; + mobile_identity_suci.routing_indicator1 = 0; + mobile_identity_suci.routing_indicator2 = 0xf; + mobile_identity_suci.routing_indicator3 = 0xf; + mobile_identity_suci.routing_indicator4 = 0xf; + mobile_identity_suci.protection_scheme_id = OGS_NAS_5GS_NULL_SCHEME; + mobile_identity_suci.home_network_pki_value = 0; + mobile_identity_suci.scheme_output[0] = 0; + mobile_identity_suci.scheme_output[1] = 0; + mobile_identity_suci.scheme_output[2] = 0x20; + mobile_identity_suci.scheme_output[3] = 0x31; + mobile_identity_suci.scheme_output[4] = 0x90; + + test_ue = test_ue_add_by_suci(&mobile_identity_suci, 13); + ogs_assert(test_ue); + + test_ue->nr_cgi.cell_id = 0x40001; + + test_ue->nas.registration.tsc = 0; + test_ue->nas.registration.ksi = OGS_NAS_KSI_NO_KEY_IS_AVAILABLE; + test_ue->nas.registration.follow_on_request = 1; + test_ue->nas.registration.value = OGS_NAS_5GS_REGISTRATION_TYPE_INITIAL; + + test_ue->k_string = "465b5ce8b199b49faa5f0a2ee238a6bc"; + test_ue->opc_string = "e8ed289deba952e4283b54e88e6183ca"; + + /* gNB connects to AMF */ + ngap = testngap_client(AF_INET); + ABTS_PTR_NOTNULL(tc, ngap); + + /* gNB connects to UPF */ + gtpu = test_gtpu_server(1, AF_INET); + ABTS_PTR_NOTNULL(tc, gtpu); + + /* Send NG-Setup Reqeust */ + sendbuf = testngap_build_ng_setup_request(0x4000, 22); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive NG-Setup Response */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /********** Insert Subscriber in Database */ + doc = test_db_new_ims(test_ue); + ABTS_PTR_NOTNULL(tc, doc); + ABTS_INT_EQUAL(tc, OGS_OK, test_db_insert_ue(test_ue, doc)); + + /* Send Registration request */ + test_ue->registration_request_param.guti = 1; + gmmbuf = testgmm_build_registration_request(test_ue, NULL); + ABTS_PTR_NOTNULL(tc, gmmbuf); + + test_ue->registration_request_param.gmm_capability = 1; + test_ue->registration_request_param.requested_nssai = 1; + test_ue->registration_request_param.last_visited_registered_tai = 1; + test_ue->registration_request_param.ue_usage_setting = 1; + nasbuf = testgmm_build_registration_request(test_ue, NULL); + ABTS_PTR_NOTNULL(tc, nasbuf); + + sendbuf = testngap_build_initial_ue_message(test_ue, gmmbuf, false, true); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Identity request */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Identity response */ + gmmbuf = testgmm_build_identity_response(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Authentication request */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Authentication response */ + gmmbuf = testgmm_build_authentication_response(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Security mode command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Security mode complete */ + gmmbuf = testgmm_build_security_mode_complete(test_ue, nasbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive InitialContextSetupRequest + + * Registration accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_InitialContextSetup, + test_ue->ngap_procedure_code); + + /* Send UERadioCapabilityInfoIndication */ + sendbuf = testngap_build_ue_radio_capability_info_indication(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send InitialContextSetupResponse */ + sendbuf = testngap_build_initial_context_setup_response(test_ue, false); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Registration complete */ + gmmbuf = testgmm_build_registration_complete(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Configuration update command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send PDU session establishment request */ + sess = test_sess_add_by_dnn_and_psi(test_ue, "internet", 5); + ogs_assert(sess); + + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_INITIAL; + sess->ul_nas_transport_param.dnn = 1; + sess->ul_nas_transport_param.s_nssai = 1; + + sess->pdu_session_establishment_param.ssc_mode = 1; + sess->pdu_session_establishment_param.epco = 1; + + gsmbuf = testgsm_build_pdu_session_establishment_request(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDUSessionResourceSetupRequest + + * DL NAS transport + + * PDU session establishment accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceSetup, + test_ue->ngap_procedure_code); + + /* Send GTP-U ICMP Packet */ + qos_flow = test_qos_flow_find_by_qfi(sess, 1); + ogs_assert(qos_flow); + rv = test_gtpu_send_ping(gtpu, qos_flow, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDUSessionResourceSetupResponse */ + sendbuf = testngap_sess_build_pdu_session_resource_setup_response(sess); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = testgnb_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send GTP-U ICMP Packet */ + rv = test_gtpu_send_ping(gtpu, qos_flow, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = testgnb_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send GTP-U Router Solicitation */ + rv = test_gtpu_send_slacc_rs(gtpu, qos_flow); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U Router Advertisement */ + recvbuf = test_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + testgtpu_recv(test_ue, recvbuf); + + /* Send PDU session establishment request */ + sess = test_sess_add_by_dnn_and_psi(test_ue, "ims", 6); + ogs_assert(sess); + + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_INITIAL; + sess->ul_nas_transport_param.dnn = 1; + sess->ul_nas_transport_param.s_nssai = 1; + + sess->pdu_session_establishment_param.ssc_mode = 1; + sess->pdu_session_establishment_param.epco = 1; + + gsmbuf = testgsm_build_pdu_session_establishment_request(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDU session establishment accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send PDUSessionResourceSetupResponse */ + sendbuf = testngap_sess_build_pdu_session_resource_setup_response(sess); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send UEContextReleaseRequest */ + sendbuf = testngap_build_ue_context_release_request(test_ue, + NGAP_Cause_PR_radioNetwork, NGAP_CauseRadioNetwork_user_inactivity, + true); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive UEContextReleaseCommand */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_UEContextRelease, + test_ue->ngap_procedure_code); + + /* Send UEContextReleaseComplete */ + sendbuf = testngap_build_ue_context_release_complete(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Add AF-Session */ + af_sess = af_sess_add_by_ue_address(&sess->ue_ip); + ogs_assert(af_sess); + + af_sess->supi = ogs_strdup(test_ue->supi); + ogs_assert(af_sess->supi); + + af_sess->dnn = ogs_strdup(sess->dnn); + ogs_assert(af_sess->dnn); + + af_local_discover_and_send(OpenAPI_nf_type_BSF, af_sess, NULL, + af_nbsf_management_build_discover); + + /* Wait for PCF-Discovery */ + ogs_msleep(100); + + /* Send AF-Session : CREATE */ + memset(&af_param, 0, sizeof(af_param)); + af_param.med_type = OpenAPI_media_type_AUDIO; + af_param.qos_type = 1; + af_param.flow_type = 99; /* For ping test */ + + af_local_send_to_pcf(af_sess, &af_param, + af_npcf_policyauthorization_build_create); + + /* Receive NG-Paging */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_Paging, + test_ue->ngap_procedure_code); + + /* + * Send InitialUEMessage + + * Service request + * - Type: Mobile terminated services(2) + * - PDU Session Status + */ + test_ue->service_request_param.integrity_protected = 0; + test_ue->service_request_param.pdu_session_status = 1; + test_ue->service_request_param. + psimask.pdu_session_status = (1 << 5 | 1 << 6); + nasbuf = testgmm_build_service_request( + test_ue, OGS_NAS_SERVICE_TYPE_MOBILE_TERMINATED_SERVICES, NULL); + ABTS_PTR_NOTNULL(tc, nasbuf); + + test_ue->service_request_param.integrity_protected = 1; + test_ue->service_request_param.pdu_session_status = 0; + gmmbuf = testgmm_build_service_request( + test_ue, OGS_NAS_SERVICE_TYPE_MOBILE_TERMINATED_SERVICES, nasbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + + sendbuf = testngap_build_initial_ue_message(test_ue, gmmbuf, true, true); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive InitialContextSetupRequest + + * Service accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_InitialContextSetup, + test_ue->ngap_procedure_code); + ABTS_INT_EQUAL(tc, 0x6000, test_ue->pdu_session_status); + + /* Send InitialContextSetupResponse */ + sendbuf = testngap_build_initial_context_setup_response(test_ue, false); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDUSessionResourceModifyRequest + + * DL NAS transport + + * PDU session modification command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceModify, + test_ue->ngap_procedure_code); + + /* Send PDU session resource modify response */ + qos_flow = test_qos_flow_find_by_qfi(sess, 2); + ogs_assert(qos_flow); + + sendbuf = testngap_build_qos_flow_resource_modify_response(qos_flow); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDU session resource modify complete */ + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_MODIFICATION_REQUEST; + sess->ul_nas_transport_param.dnn = 0; + sess->ul_nas_transport_param.s_nssai = 0; + + sess->pdu_session_establishment_param.ssc_mode = 0; + sess->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_modification_complete(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Configuration update command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Configuration update complete */ + gmmbuf = testgmm_build_configuration_update_complete(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send UEContextReleaseRequest */ + sendbuf = testngap_build_ue_context_release_request(test_ue, + NGAP_Cause_PR_radioNetwork, NGAP_CauseRadioNetwork_user_inactivity, + true); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive UEContextReleaseCommand */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_UEContextRelease, + test_ue->ngap_procedure_code); + + /* Send UEContextReleaseComplete */ + sendbuf = testngap_build_ue_context_release_complete(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send AF-Session : UPDATE */ + memset(&af_param, 0, sizeof(af_param)); + af_param.med_type = OpenAPI_media_type_AUDIO; + af_param.qos_type = 2; + af_param.flow_type = 1; + + af_local_send_to_pcf(af_sess, &af_param, + af_npcf_policyauthorization_build_update); + + /* Receive NG-Paging */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_Paging, + test_ue->ngap_procedure_code); + + /* + * Send InitialUEMessage + + * Service request + * - Type: Mobile terminated services(2) + * - PDU Session Status + */ + test_ue->service_request_param.integrity_protected = 0; + test_ue->service_request_param.pdu_session_status = 1; + test_ue->service_request_param. + psimask.pdu_session_status = (1 << 5 | 1 << 6); + nasbuf = testgmm_build_service_request( + test_ue, OGS_NAS_SERVICE_TYPE_MOBILE_TERMINATED_SERVICES, NULL); + ABTS_PTR_NOTNULL(tc, nasbuf); + + test_ue->service_request_param.integrity_protected = 1; + test_ue->service_request_param.pdu_session_status = 0; + gmmbuf = testgmm_build_service_request( + test_ue, OGS_NAS_SERVICE_TYPE_MOBILE_TERMINATED_SERVICES, nasbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + + sendbuf = testngap_build_initial_ue_message(test_ue, gmmbuf, true, true); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive InitialContextSetupRequest + + * Service accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_InitialContextSetup, + test_ue->ngap_procedure_code); + ABTS_INT_EQUAL(tc, 0x6000, test_ue->pdu_session_status); + + /* Send InitialContextSetupResponse */ + sendbuf = testngap_build_initial_context_setup_response(test_ue, false); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDUSessionResourceModifyRequest + + * DL NAS transport + + * PDU session modification command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceModify, + test_ue->ngap_procedure_code); + + /* Send PDU session resource modify response */ + qos_flow = test_qos_flow_find_by_qfi(sess, 2); + ogs_assert(qos_flow); + + sendbuf = testngap_build_qos_flow_resource_modify_response(qos_flow); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDU session resource modify complete */ + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_MODIFICATION_REQUEST; + sess->ul_nas_transport_param.dnn = 0; + sess->ul_nas_transport_param.s_nssai = 0; + + sess->pdu_session_establishment_param.ssc_mode = 0; + sess->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_modification_complete(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Configuration update command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Configuration update complete */ + gmmbuf = testgmm_build_configuration_update_complete(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send UEContextReleaseRequest */ + sendbuf = testngap_build_ue_context_release_request(test_ue, + NGAP_Cause_PR_radioNetwork, NGAP_CauseRadioNetwork_user_inactivity, + true); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive UEContextReleaseCommand */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_UEContextRelease, + test_ue->ngap_procedure_code); + + /* Send UEContextReleaseComplete */ + sendbuf = testngap_build_ue_context_release_complete(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send AF-Session : DELETE */ + af_local_send_to_pcf(af_sess, NULL, + af_npcf_policyauthorization_build_delete); + + /* Receive NG-Paging */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_Paging, + test_ue->ngap_procedure_code); + + /* + * Send InitialUEMessage + + * Service request + * - Type: Mobile terminated services(2) + * - PDU Session Status + */ + test_ue->service_request_param.integrity_protected = 0; + test_ue->service_request_param.pdu_session_status = 1; + test_ue->service_request_param. + psimask.pdu_session_status = (1 << 5 | 1 << 6); + nasbuf = testgmm_build_service_request( + test_ue, OGS_NAS_SERVICE_TYPE_MOBILE_TERMINATED_SERVICES, NULL); + ABTS_PTR_NOTNULL(tc, nasbuf); + + test_ue->service_request_param.integrity_protected = 1; + test_ue->service_request_param.pdu_session_status = 0; + gmmbuf = testgmm_build_service_request( + test_ue, OGS_NAS_SERVICE_TYPE_MOBILE_TERMINATED_SERVICES, nasbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + + sendbuf = testngap_build_initial_ue_message(test_ue, gmmbuf, true, true); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive InitialContextSetupRequest + + * Service accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_InitialContextSetup, + test_ue->ngap_procedure_code); + ABTS_INT_EQUAL(tc, 0x6000, test_ue->pdu_session_status); + + /* Send InitialContextSetupResponse */ + sendbuf = testngap_build_initial_context_setup_response(test_ue, false); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDUSessionResourceModifyRequest + + * DL NAS transport + + * PDU session modification command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceModify, + test_ue->ngap_procedure_code); + + /* Send PDU session resource modify response */ + qos_flow = test_qos_flow_find_by_qfi(sess, 2); + ogs_assert(qos_flow); + + sendbuf = testngap_build_qos_flow_resource_release_response(qos_flow); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDU session resource modify complete */ + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_MODIFICATION_REQUEST; + sess->ul_nas_transport_param.dnn = 0; + sess->ul_nas_transport_param.s_nssai = 0; + + sess->pdu_session_establishment_param.ssc_mode = 0; + sess->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_modification_complete(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Test Bearer Remove */ + test_bearer_remove(qos_flow); + + /* Receive Configuration update command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Configuration update complete */ + gmmbuf = testgmm_build_configuration_update_complete(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send De-registration request */ + gmmbuf = testgmm_build_de_registration_request(test_ue, 1); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive UEContextReleaseCommand */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_UEContextRelease, + test_ue->ngap_procedure_code); + + /* Send UEContextReleaseComplete */ + sendbuf = testngap_build_ue_context_release_complete(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + ogs_msleep(300); + + /********** Remove Subscriber in Database */ + ABTS_INT_EQUAL(tc, OGS_OK, test_db_remove_ue(test_ue)); + + /* gNB disonncect from UPF */ + testgnb_gtpu_close(gtpu); + + /* gNB disonncect from AMF */ + testgnb_ngap_close(ngap); + + /* Clear Test UE Context */ + test_ue_remove(test_ue); +} + +static void test6_func(abts_case *tc, void *data) +{ + int rv; + ogs_socknode_t *ngap; + ogs_socknode_t *gtpu; + ogs_pkbuf_t *gmmbuf; + ogs_pkbuf_t *gsmbuf; + ogs_pkbuf_t *nasbuf; + ogs_pkbuf_t *sendbuf; + ogs_pkbuf_t *recvbuf; + ogs_ngap_message_t message; + int i; + + uint8_t tmp[OGS_MAX_SDU_LEN]; + char *_gtp_payload = "34ff0024" + "0000000100000085 010002004500001c 0c0b000040015a7a 0a2d00010a2d0002" + "00000964cd7c291f"; + + ogs_nas_5gs_mobile_identity_suci_t mobile_identity_suci; + test_ue_t *test_ue = NULL; + test_sess_t *sess = NULL; + test_bearer_t *qos_flow = NULL; + + af_sess_t *af_sess1 = NULL, *af_sess2 = NULL; + af_npcf_policyauthorization_param_t af_param; + + bson_t *doc = NULL; + + /* Setup Test UE & Session Context */ + memset(&mobile_identity_suci, 0, sizeof(mobile_identity_suci)); + + mobile_identity_suci.h.supi_format = OGS_NAS_5GS_SUPI_FORMAT_IMSI; + mobile_identity_suci.h.type = OGS_NAS_5GS_MOBILE_IDENTITY_SUCI; + mobile_identity_suci.routing_indicator1 = 0; + mobile_identity_suci.routing_indicator2 = 0xf; + mobile_identity_suci.routing_indicator3 = 0xf; + mobile_identity_suci.routing_indicator4 = 0xf; + mobile_identity_suci.protection_scheme_id = OGS_NAS_5GS_NULL_SCHEME; + mobile_identity_suci.home_network_pki_value = 0; + mobile_identity_suci.scheme_output[0] = 0; + mobile_identity_suci.scheme_output[1] = 0; + mobile_identity_suci.scheme_output[2] = 0x20; + mobile_identity_suci.scheme_output[3] = 0x31; + mobile_identity_suci.scheme_output[4] = 0x90; + + test_ue = test_ue_add_by_suci(&mobile_identity_suci, 13); + ogs_assert(test_ue); + + test_ue->nr_cgi.cell_id = 0x40001; + + test_ue->nas.registration.tsc = 0; + test_ue->nas.registration.ksi = OGS_NAS_KSI_NO_KEY_IS_AVAILABLE; + test_ue->nas.registration.follow_on_request = 1; + test_ue->nas.registration.value = OGS_NAS_5GS_REGISTRATION_TYPE_INITIAL; + + test_ue->k_string = "465b5ce8b199b49faa5f0a2ee238a6bc"; + test_ue->opc_string = "e8ed289deba952e4283b54e88e6183ca"; + + /* gNB connects to AMF */ + ngap = testngap_client(AF_INET); + ABTS_PTR_NOTNULL(tc, ngap); + + /* gNB connects to UPF */ + gtpu = test_gtpu_server(1, AF_INET); + ABTS_PTR_NOTNULL(tc, gtpu); + + /* Send NG-Setup Reqeust */ + sendbuf = testngap_build_ng_setup_request(0x4000, 22); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive NG-Setup Response */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /********** Insert Subscriber in Database */ + doc = test_db_new_ims(test_ue); + ABTS_PTR_NOTNULL(tc, doc); + ABTS_INT_EQUAL(tc, OGS_OK, test_db_insert_ue(test_ue, doc)); + + /* Send Registration request */ + test_ue->registration_request_param.guti = 1; + gmmbuf = testgmm_build_registration_request(test_ue, NULL); + ABTS_PTR_NOTNULL(tc, gmmbuf); + + test_ue->registration_request_param.gmm_capability = 1; + test_ue->registration_request_param.requested_nssai = 1; + test_ue->registration_request_param.last_visited_registered_tai = 1; + test_ue->registration_request_param.ue_usage_setting = 1; + nasbuf = testgmm_build_registration_request(test_ue, NULL); + ABTS_PTR_NOTNULL(tc, nasbuf); + + sendbuf = testngap_build_initial_ue_message(test_ue, gmmbuf, false, true); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Identity request */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Identity response */ + gmmbuf = testgmm_build_identity_response(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Authentication request */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Authentication response */ + gmmbuf = testgmm_build_authentication_response(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Security mode command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Security mode complete */ + gmmbuf = testgmm_build_security_mode_complete(test_ue, nasbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive InitialContextSetupRequest + + * Registration accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_InitialContextSetup, + test_ue->ngap_procedure_code); + + /* Send UERadioCapabilityInfoIndication */ + sendbuf = testngap_build_ue_radio_capability_info_indication(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send InitialContextSetupResponse */ + sendbuf = testngap_build_initial_context_setup_response(test_ue, false); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Registration complete */ + gmmbuf = testgmm_build_registration_complete(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Configuration update command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send PDU session establishment request */ + sess = test_sess_add_by_dnn_and_psi(test_ue, "internet", 5); + ogs_assert(sess); + + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_INITIAL; + sess->ul_nas_transport_param.dnn = 1; + sess->ul_nas_transport_param.s_nssai = 1; + + sess->pdu_session_establishment_param.ssc_mode = 1; + sess->pdu_session_establishment_param.epco = 1; + + gsmbuf = testgsm_build_pdu_session_establishment_request(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDUSessionResourceSetupRequest + + * DL NAS transport + + * PDU session establishment accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceSetup, + test_ue->ngap_procedure_code); + + /* Send GTP-U ICMP Packet */ + qos_flow = test_qos_flow_find_by_qfi(sess, 1); + ogs_assert(qos_flow); + rv = test_gtpu_send_ping(gtpu, qos_flow, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDUSessionResourceSetupResponse */ + sendbuf = testngap_sess_build_pdu_session_resource_setup_response(sess); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = testgnb_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send GTP-U ICMP Packet */ + rv = test_gtpu_send_ping(gtpu, qos_flow, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = testgnb_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send GTP-U Router Solicitation */ + rv = test_gtpu_send_slacc_rs(gtpu, qos_flow); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U Router Advertisement */ + recvbuf = test_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + testgtpu_recv(test_ue, recvbuf); + + /* Send PDU session establishment request */ + sess = test_sess_add_by_dnn_and_psi(test_ue, "ims", 6); + ogs_assert(sess); + + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_INITIAL; + sess->ul_nas_transport_param.dnn = 1; + sess->ul_nas_transport_param.s_nssai = 1; + + sess->pdu_session_establishment_param.ssc_mode = 1; + sess->pdu_session_establishment_param.epco = 1; + + gsmbuf = testgsm_build_pdu_session_establishment_request(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDU session establishment accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send PDUSessionResourceSetupResponse */ + sendbuf = testngap_sess_build_pdu_session_resource_setup_response(sess); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Add AF-Session */ + af_sess1 = af_sess_add_by_ue_address(&sess->ue_ip); + ogs_assert(af_sess1); + + af_sess1->supi = ogs_strdup(test_ue->supi); + ogs_assert(af_sess1->supi); + + af_sess1->dnn = ogs_strdup(sess->dnn); + ogs_assert(af_sess1->dnn); + + af_local_discover_and_send(OpenAPI_nf_type_BSF, af_sess1, NULL, + af_nbsf_management_build_discover); + + /* Wait for PCF-Discovery */ + ogs_msleep(100); + + /* Send AF-Session : CREATE */ + memset(&af_param, 0, sizeof(af_param)); + af_param.med_type = OpenAPI_media_type_AUDIO; + af_param.qos_type = 1; + af_param.flow_type = 99; + + af_local_send_to_pcf(af_sess1, &af_param, + af_npcf_policyauthorization_build_create); + + /* Receive PDUSessionResourceModifyRequest + + * DL NAS transport + + * PDU session modification command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceModify, + test_ue->ngap_procedure_code); + + /* Send PDU session resource modify response */ + qos_flow = test_qos_flow_find_by_qfi(sess, 2); + ogs_assert(qos_flow); + + sendbuf = testngap_build_qos_flow_resource_modify_response(qos_flow); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDU session resource modify complete */ + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_MODIFICATION_REQUEST; + sess->ul_nas_transport_param.dnn = 0; + sess->ul_nas_transport_param.s_nssai = 0; + + sess->pdu_session_establishment_param.ssc_mode = 0; + sess->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_modification_complete(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Wait for PDU session resource modify complete */ + ogs_msleep(100); + + /* Add AF-Session */ + af_sess2 = af_sess_add_by_ue_address(&sess->ue_ip); + ogs_assert(af_sess2); + + af_sess2->supi = ogs_strdup(test_ue->supi); + ogs_assert(af_sess2->supi); + + af_sess2->dnn = ogs_strdup(sess->dnn); + ogs_assert(af_sess2->dnn); + + af_local_discover_and_send(OpenAPI_nf_type_BSF, af_sess2, NULL, + af_nbsf_management_build_discover); + + /* Wait for PCF-Discovery */ + ogs_msleep(100); + + /* Send AF-Session : CREATE */ + memset(&af_param, 0, sizeof(af_param)); + af_param.med_type = OpenAPI_media_type_AUDIO; + af_param.qos_type = 1; + af_param.flow_type = 2; + + af_local_send_to_pcf(af_sess2, &af_param, + af_npcf_policyauthorization_build_create); + + /* Receive PDUSessionResourceModifyRequest + + * DL NAS transport + + * PDU session modification command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceModify, + test_ue->ngap_procedure_code); + + /* Send PDU session resource modify response */ + qos_flow = test_qos_flow_find_by_qfi(sess, 3); + ogs_assert(qos_flow); + + sendbuf = testngap_build_qos_flow_resource_modify_response(qos_flow); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDU session resource modify complete */ + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_MODIFICATION_REQUEST; + sess->ul_nas_transport_param.dnn = 0; + sess->ul_nas_transport_param.s_nssai = 0; + + sess->pdu_session_establishment_param.ssc_mode = 0; + sess->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_modification_complete(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Wait for PDU session resource modify complete */ + ogs_msleep(100); + + /* Send AF-Session : DELETE */ + af_local_send_to_pcf(af_sess1, NULL, + af_npcf_policyauthorization_build_delete); + + /* Receive PDUSessionResourceModifyRequest + + * DL NAS transport + + * PDU session modification command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceModify, + test_ue->ngap_procedure_code); + + /* Send PDU session resource modify response */ + qos_flow = test_qos_flow_find_by_qfi(sess, 2); + ogs_assert(qos_flow); + + sendbuf = testngap_build_qos_flow_resource_release_response(qos_flow); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDU session resource modify complete */ + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_MODIFICATION_REQUEST; + sess->ul_nas_transport_param.dnn = 0; + sess->ul_nas_transport_param.s_nssai = 0; + + sess->pdu_session_establishment_param.ssc_mode = 0; + sess->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_modification_complete(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Wait for PDU session resource modify complete */ + ogs_msleep(100); + + /* Test Bearer Remove */ + test_bearer_remove(qos_flow); + + /* Send AF-Session : DELETE */ + af_local_send_to_pcf(af_sess2, NULL, + af_npcf_policyauthorization_build_delete); + + /* Receive PDUSessionResourceModifyRequest + + * DL NAS transport + + * PDU session modification command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceModify, + test_ue->ngap_procedure_code); + + /* Send PDU session resource modify response */ + qos_flow = test_qos_flow_find_by_qfi(sess, 3); + ogs_assert(qos_flow); + + sendbuf = testngap_build_qos_flow_resource_release_response(qos_flow); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDU session resource modify complete */ + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_MODIFICATION_REQUEST; + sess->ul_nas_transport_param.dnn = 0; + sess->ul_nas_transport_param.s_nssai = 0; + + sess->pdu_session_establishment_param.ssc_mode = 0; + sess->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_modification_complete(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Wait for PDU session resource modify complete */ + ogs_msleep(100); + + /* Test Bearer Remove */ + test_bearer_remove(qos_flow); + + /* Send De-registration request */ + gmmbuf = testgmm_build_de_registration_request(test_ue, 1); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive UEContextReleaseCommand */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_UEContextRelease, + test_ue->ngap_procedure_code); + + /* Send UEContextReleaseComplete */ + sendbuf = testngap_build_ue_context_release_complete(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + ogs_msleep(300); + + /********** Remove Subscriber in Database */ + ABTS_INT_EQUAL(tc, OGS_OK, test_db_remove_ue(test_ue)); + + /* gNB disonncect from UPF */ + testgnb_gtpu_close(gtpu); + + /* gNB disonncect from AMF */ + testgnb_ngap_close(ngap); + + /* Clear Test UE Context */ + test_ue_remove(test_ue); +} + +static void test7_func(abts_case *tc, void *data) +{ + int rv; + ogs_socknode_t *ngap; + ogs_socknode_t *gtpu; + ogs_pkbuf_t *gmmbuf; + ogs_pkbuf_t *gsmbuf; + ogs_pkbuf_t *nasbuf; + ogs_pkbuf_t *sendbuf; + ogs_pkbuf_t *recvbuf; + ogs_ngap_message_t message; + int i; + + uint8_t tmp[OGS_MAX_SDU_LEN]; + char *_gtp_payload = "34ff0024" + "0000000100000085 010002004500001c 0c0b000040015a7a 0a2d00010a2d0002" + "00000964cd7c291f"; + + ogs_nas_5gs_mobile_identity_suci_t mobile_identity_suci; + test_ue_t *test_ue = NULL; + test_sess_t *sess = NULL; + test_bearer_t *qos_flow = NULL; + + af_sess_t *af_sess = NULL, *af_sess2 = NULL; + af_npcf_policyauthorization_param_t af_param; + + bson_t *doc = NULL; + + /* Setup Test UE & Session Context */ + memset(&mobile_identity_suci, 0, sizeof(mobile_identity_suci)); + + mobile_identity_suci.h.supi_format = OGS_NAS_5GS_SUPI_FORMAT_IMSI; + mobile_identity_suci.h.type = OGS_NAS_5GS_MOBILE_IDENTITY_SUCI; + mobile_identity_suci.routing_indicator1 = 0; + mobile_identity_suci.routing_indicator2 = 0xf; + mobile_identity_suci.routing_indicator3 = 0xf; + mobile_identity_suci.routing_indicator4 = 0xf; + mobile_identity_suci.protection_scheme_id = OGS_NAS_5GS_NULL_SCHEME; + mobile_identity_suci.home_network_pki_value = 0; + mobile_identity_suci.scheme_output[0] = 0; + mobile_identity_suci.scheme_output[1] = 0; + mobile_identity_suci.scheme_output[2] = 0x20; + mobile_identity_suci.scheme_output[3] = 0x31; + mobile_identity_suci.scheme_output[4] = 0x90; + + test_ue = test_ue_add_by_suci(&mobile_identity_suci, 13); + ogs_assert(test_ue); + + test_ue->nr_cgi.cell_id = 0x40001; + + test_ue->nas.registration.tsc = 0; + test_ue->nas.registration.ksi = OGS_NAS_KSI_NO_KEY_IS_AVAILABLE; + test_ue->nas.registration.follow_on_request = 1; + test_ue->nas.registration.value = OGS_NAS_5GS_REGISTRATION_TYPE_INITIAL; + + test_ue->k_string = "465b5ce8b199b49faa5f0a2ee238a6bc"; + test_ue->opc_string = "e8ed289deba952e4283b54e88e6183ca"; + + /* gNB connects to AMF */ + ngap = testngap_client(AF_INET); + ABTS_PTR_NOTNULL(tc, ngap); + + /* gNB connects to UPF */ + gtpu = test_gtpu_server(1, AF_INET); + ABTS_PTR_NOTNULL(tc, gtpu); + + /* Send NG-Setup Reqeust */ + sendbuf = testngap_build_ng_setup_request(0x4000, 22); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive NG-Setup Response */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /********** Insert Subscriber in Database */ + doc = test_db_new_ims(test_ue); + ABTS_PTR_NOTNULL(tc, doc); + ABTS_INT_EQUAL(tc, OGS_OK, test_db_insert_ue(test_ue, doc)); + + /* Send Registration request */ + test_ue->registration_request_param.guti = 1; + gmmbuf = testgmm_build_registration_request(test_ue, NULL); + ABTS_PTR_NOTNULL(tc, gmmbuf); + + test_ue->registration_request_param.gmm_capability = 1; + test_ue->registration_request_param.requested_nssai = 1; + test_ue->registration_request_param.last_visited_registered_tai = 1; + test_ue->registration_request_param.ue_usage_setting = 1; + nasbuf = testgmm_build_registration_request(test_ue, NULL); + ABTS_PTR_NOTNULL(tc, nasbuf); + + sendbuf = testngap_build_initial_ue_message(test_ue, gmmbuf, false, true); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Identity request */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Identity response */ + gmmbuf = testgmm_build_identity_response(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Authentication request */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Authentication response */ + gmmbuf = testgmm_build_authentication_response(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Security mode command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Security mode complete */ + gmmbuf = testgmm_build_security_mode_complete(test_ue, nasbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive InitialContextSetupRequest + + * Registration accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_InitialContextSetup, + test_ue->ngap_procedure_code); + + /* Send UERadioCapabilityInfoIndication */ + sendbuf = testngap_build_ue_radio_capability_info_indication(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send InitialContextSetupResponse */ + sendbuf = testngap_build_initial_context_setup_response(test_ue, false); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Registration complete */ + gmmbuf = testgmm_build_registration_complete(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Configuration update command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send PDU session establishment request */ + sess = test_sess_add_by_dnn_and_psi(test_ue, "internet", 5); + ogs_assert(sess); + + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_INITIAL; + sess->ul_nas_transport_param.dnn = 1; + sess->ul_nas_transport_param.s_nssai = 1; + + sess->pdu_session_establishment_param.ssc_mode = 1; + sess->pdu_session_establishment_param.epco = 1; + + gsmbuf = testgsm_build_pdu_session_establishment_request(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDUSessionResourceSetupRequest + + * DL NAS transport + + * PDU session establishment accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceSetup, + test_ue->ngap_procedure_code); + + /* Send GTP-U ICMP Packet */ + qos_flow = test_qos_flow_find_by_qfi(sess, 1); + ogs_assert(qos_flow); + rv = test_gtpu_send_ping(gtpu, qos_flow, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDUSessionResourceSetupResponse */ + sendbuf = testngap_sess_build_pdu_session_resource_setup_response(sess); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = testgnb_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send GTP-U ICMP Packet */ + rv = test_gtpu_send_ping(gtpu, qos_flow, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = testgnb_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send GTP-U Router Solicitation */ + rv = test_gtpu_send_slacc_rs(gtpu, qos_flow); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U Router Advertisement */ + recvbuf = test_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + testgtpu_recv(test_ue, recvbuf); + + /* Send PDU session establishment request */ + sess = test_sess_add_by_dnn_and_psi(test_ue, "ims", 6); + ogs_assert(sess); + + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_INITIAL; + sess->ul_nas_transport_param.dnn = 1; + sess->ul_nas_transport_param.s_nssai = 1; + + sess->pdu_session_establishment_param.ssc_mode = 1; + sess->pdu_session_establishment_param.epco = 1; + + gsmbuf = testgsm_build_pdu_session_establishment_request(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDU session establishment accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send PDUSessionResourceSetupResponse */ + sendbuf = testngap_sess_build_pdu_session_resource_setup_response(sess); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Add AF-Session */ + af_sess = af_sess_add_by_ue_address(&sess->ue_ip); + ogs_assert(af_sess); + + af_sess->supi = ogs_strdup(test_ue->supi); + ogs_assert(af_sess->supi); + + af_sess->dnn = ogs_strdup(sess->dnn); + ogs_assert(af_sess->dnn); + + af_local_discover_and_send(OpenAPI_nf_type_BSF, af_sess, NULL, + af_nbsf_management_build_discover); + + /* Wait for PCF-Discovery */ + ogs_msleep(100); + + /* Send AF-Session : CREATE */ + memset(&af_param, 0, sizeof(af_param)); + af_param.med_type = OpenAPI_media_type_AUDIO; + af_param.qos_type = 1; + af_param.flow_type = 99; /* For ping test */ + af_local_send_to_pcf(af_sess, &af_param, + af_npcf_policyauthorization_build_create); + + /* Receive PDUSessionResourceModifyRequest + + * DL NAS transport + + * PDU session modification command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceModify, + test_ue->ngap_procedure_code); + + /* Send PDU session resource modify response */ + qos_flow = test_qos_flow_find_by_qfi(sess, 2); + ogs_assert(qos_flow); + + sendbuf = testngap_build_qos_flow_resource_modify_response(qos_flow); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDU session resource modify complete */ + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_MODIFICATION_REQUEST; + sess->ul_nas_transport_param.dnn = 0; + sess->ul_nas_transport_param.s_nssai = 0; + + sess->pdu_session_establishment_param.ssc_mode = 0; + sess->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_modification_complete(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Wait for PCF-Discovery */ + ogs_msleep(100); + + /* Send AF-Session : DELETE */ + af_local_send_to_pcf(af_sess, NULL, + af_npcf_policyauthorization_build_delete); + + /* Receive PDUSessionResourceModifyRequest + + * DL NAS transport + + * PDU session modification command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceModify, + test_ue->ngap_procedure_code); + + /* Send Error Indication */ + rv = test_gtpu_send_error_indication(gtpu, qos_flow); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDUSessionResourceReleaseCommand */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceRelease, + test_ue->ngap_procedure_code); + + /* Send PDU session resource modify response */ + qos_flow = test_qos_flow_find_by_qfi(sess, 2); + ogs_assert(qos_flow); + + sendbuf = testngap_build_qos_flow_resource_release_response(qos_flow); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDU session resource modify complete */ + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_MODIFICATION_REQUEST; + sess->ul_nas_transport_param.dnn = 0; + sess->ul_nas_transport_param.s_nssai = 0; + + sess->pdu_session_establishment_param.ssc_mode = 0; + sess->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_modification_complete(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Wait for PDU session resource modify complete */ + ogs_msleep(100); + + /* Test Bearer Remove */ + test_bearer_remove(qos_flow); + + /* Send PDUSessionResourceReleaseResponse */ + sendbuf = testngap_build_pdu_session_resource_release_response(sess); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDUSessionResourceSetupRequest */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceSetup, + test_ue->ngap_procedure_code); + + /* Send PDUSessionResourceSetupResponse */ + sendbuf = testngap_sess_build_pdu_session_resource_setup_response(sess); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Wait to setup N3 data connection. + * Otherwise, network-triggered service request is initiated */ + ogs_msleep(100); /* Send De-registration request */ gmmbuf = testgmm_build_de_registration_request(test_ue, 1); @@ -355,6 +3950,12 @@ abts_suite *test_af(abts_suite *suite) suite = ADD_SUITE(suite) abts_run_test(suite, test1_func, NULL); + abts_run_test(suite, test2_func, NULL); + abts_run_test(suite, test3_func, NULL); + abts_run_test(suite, test4_func, NULL); + abts_run_test(suite, test5_func, NULL); + abts_run_test(suite, test6_func, NULL); + abts_run_test(suite, test7_func, NULL); return suite; } diff --git a/tests/vonr/meson.build b/tests/vonr/meson.build index d0c6768cb..dce2f1654 100644 --- a/tests/vonr/meson.build +++ b/tests/vonr/meson.build @@ -20,6 +20,7 @@ test5gc_vonr_sources = files(''' qos-flow-test.c session-test.c af-test.c + video-test.c '''.split()) test5gc_vonr_exe = executable('vonr', diff --git a/tests/vonr/qos-flow-test.c b/tests/vonr/qos-flow-test.c index a8c8dd167..e92051898 100644 --- a/tests/vonr/qos-flow-test.c +++ b/tests/vonr/qos-flow-test.c @@ -260,7 +260,7 @@ static void test1_func(abts_case *tc, void *data) qos_flow = test_qos_flow_find_by_qfi(sess, 2); ogs_assert(qos_flow); - sendbuf = testngap_build_pdu_session_resource_modify_response(qos_flow); + sendbuf = testngap_build_qos_flow_resource_modify_response(qos_flow); ABTS_PTR_NOTNULL(tc, sendbuf); rv = testgnb_ngap_send(ngap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); diff --git a/tests/vonr/session-test.c b/tests/vonr/session-test.c index 6ce4df703..6b7a41108 100644 --- a/tests/vonr/session-test.c +++ b/tests/vonr/session-test.c @@ -293,7 +293,7 @@ static void test1_func(abts_case *tc, void *data) qos_flow = test_qos_flow_find_by_qfi(sess, 2); ogs_assert(qos_flow); - sendbuf = testngap_build_pdu_session_resource_modify_response(qos_flow); + sendbuf = testngap_build_qos_flow_resource_modify_response(qos_flow); ABTS_PTR_NOTNULL(tc, sendbuf); rv = testgnb_ngap_send(ngap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); @@ -771,7 +771,7 @@ static void test2_func(abts_case *tc, void *data) qos_flow = test_qos_flow_find_by_qfi(sess, 2); ogs_assert(qos_flow); - sendbuf = testngap_build_pdu_session_resource_modify_response(qos_flow); + sendbuf = testngap_build_qos_flow_resource_modify_response(qos_flow); ABTS_PTR_NOTNULL(tc, sendbuf); rv = testgnb_ngap_send(ngap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); @@ -1205,7 +1205,7 @@ static void test3_func(abts_case *tc, void *data) qos_flow = test_qos_flow_find_by_qfi(sess, 2); ogs_assert(qos_flow); - sendbuf = testngap_build_pdu_session_resource_modify_response(qos_flow); + sendbuf = testngap_build_qos_flow_resource_modify_response(qos_flow); ABTS_PTR_NOTNULL(tc, sendbuf); rv = testgnb_ngap_send(ngap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); @@ -1628,7 +1628,7 @@ static void test4_func(abts_case *tc, void *data) qos_flow2 = test_qos_flow_find_by_qfi(sess6, 2); ogs_assert(qos_flow2); - sendbuf = testngap_build_pdu_session_resource_modify_response(qos_flow2); + sendbuf = testngap_build_qos_flow_resource_modify_response(qos_flow2); ABTS_PTR_NOTNULL(tc, sendbuf); rv = testgnb_ngap_send(ngap, sendbuf); ABTS_INT_EQUAL(tc, OGS_OK, rv); diff --git a/tests/vonr/video-test.c b/tests/vonr/video-test.c new file mode 100644 index 000000000..6f5b2869f --- /dev/null +++ b/tests/vonr/video-test.c @@ -0,0 +1,561 @@ +/* + * Copyright (C) 2019,2020 by Sukchan Lee + * + * This file is part of Open5GS. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "test-common.h" +#include "af/sbi-path.h" + +static void test1_func(abts_case *tc, void *data) +{ + int rv; + ogs_socknode_t *ngap; + ogs_socknode_t *gtpu; + ogs_pkbuf_t *gmmbuf; + ogs_pkbuf_t *gsmbuf; + ogs_pkbuf_t *nasbuf; + ogs_pkbuf_t *sendbuf; + ogs_pkbuf_t *recvbuf; + ogs_ngap_message_t message; + int i; + + uint8_t tmp[OGS_MAX_SDU_LEN]; + char *_gtp_payload = "34ff0024" + "0000000100000085 010002004500001c 0c0b000040015a7a 0a2d00010a2d0002" + "00000964cd7c291f"; + + ogs_nas_5gs_mobile_identity_suci_t mobile_identity_suci; + test_ue_t *test_ue = NULL; + test_sess_t *sess = NULL; + test_bearer_t *qos_flow = NULL; + + af_sess_t *af_sess = NULL, *af_sess2 = NULL; + af_npcf_policyauthorization_param_t af_param; + + bson_t *doc = NULL; + + /* Setup Test UE & Session Context */ + memset(&mobile_identity_suci, 0, sizeof(mobile_identity_suci)); + + mobile_identity_suci.h.supi_format = OGS_NAS_5GS_SUPI_FORMAT_IMSI; + mobile_identity_suci.h.type = OGS_NAS_5GS_MOBILE_IDENTITY_SUCI; + mobile_identity_suci.routing_indicator1 = 0; + mobile_identity_suci.routing_indicator2 = 0xf; + mobile_identity_suci.routing_indicator3 = 0xf; + mobile_identity_suci.routing_indicator4 = 0xf; + mobile_identity_suci.protection_scheme_id = OGS_NAS_5GS_NULL_SCHEME; + mobile_identity_suci.home_network_pki_value = 0; + mobile_identity_suci.scheme_output[0] = 0; + mobile_identity_suci.scheme_output[1] = 0; + mobile_identity_suci.scheme_output[2] = 0x20; + mobile_identity_suci.scheme_output[3] = 0x31; + mobile_identity_suci.scheme_output[4] = 0x90; + + test_ue = test_ue_add_by_suci(&mobile_identity_suci, 13); + ogs_assert(test_ue); + + test_ue->nr_cgi.cell_id = 0x40001; + + test_ue->nas.registration.tsc = 0; + test_ue->nas.registration.ksi = OGS_NAS_KSI_NO_KEY_IS_AVAILABLE; + test_ue->nas.registration.follow_on_request = 1; + test_ue->nas.registration.value = OGS_NAS_5GS_REGISTRATION_TYPE_INITIAL; + + test_ue->k_string = "465b5ce8b199b49faa5f0a2ee238a6bc"; + test_ue->opc_string = "e8ed289deba952e4283b54e88e6183ca"; + + /* gNB connects to AMF */ + ngap = testngap_client(AF_INET); + ABTS_PTR_NOTNULL(tc, ngap); + + /* gNB connects to UPF */ + gtpu = test_gtpu_server(1, AF_INET); + ABTS_PTR_NOTNULL(tc, gtpu); + + /* Send NG-Setup Reqeust */ + sendbuf = testngap_build_ng_setup_request(0x4000, 22); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive NG-Setup Response */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /********** Insert Subscriber in Database */ + doc = test_db_new_ims(test_ue); + ABTS_PTR_NOTNULL(tc, doc); + ABTS_INT_EQUAL(tc, OGS_OK, test_db_insert_ue(test_ue, doc)); + + /* Send Registration request */ + test_ue->registration_request_param.guti = 1; + gmmbuf = testgmm_build_registration_request(test_ue, NULL); + ABTS_PTR_NOTNULL(tc, gmmbuf); + + test_ue->registration_request_param.gmm_capability = 1; + test_ue->registration_request_param.requested_nssai = 1; + test_ue->registration_request_param.last_visited_registered_tai = 1; + test_ue->registration_request_param.ue_usage_setting = 1; + nasbuf = testgmm_build_registration_request(test_ue, NULL); + ABTS_PTR_NOTNULL(tc, nasbuf); + + sendbuf = testngap_build_initial_ue_message(test_ue, gmmbuf, false, true); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Identity request */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Identity response */ + gmmbuf = testgmm_build_identity_response(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Authentication request */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Authentication response */ + gmmbuf = testgmm_build_authentication_response(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Security mode command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send Security mode complete */ + gmmbuf = testgmm_build_security_mode_complete(test_ue, nasbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive InitialContextSetupRequest + + * Registration accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_InitialContextSetup, + test_ue->ngap_procedure_code); + + /* Send UERadioCapabilityInfoIndication */ + sendbuf = testngap_build_ue_radio_capability_info_indication(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send InitialContextSetupResponse */ + sendbuf = testngap_build_initial_context_setup_response(test_ue, false); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Registration complete */ + gmmbuf = testgmm_build_registration_complete(test_ue); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Configuration update command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send PDU session establishment request */ + sess = test_sess_add_by_dnn_and_psi(test_ue, "internet", 5); + ogs_assert(sess); + + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_INITIAL; + sess->ul_nas_transport_param.dnn = 1; + sess->ul_nas_transport_param.s_nssai = 1; + + sess->pdu_session_establishment_param.ssc_mode = 1; + sess->pdu_session_establishment_param.epco = 1; + + gsmbuf = testgsm_build_pdu_session_establishment_request(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDUSessionResourceSetupRequest + + * DL NAS transport + + * PDU session establishment accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceSetup, + test_ue->ngap_procedure_code); + + /* Send GTP-U ICMP Packet */ + qos_flow = test_qos_flow_find_by_qfi(sess, 1); + ogs_assert(qos_flow); + rv = test_gtpu_send_ping(gtpu, qos_flow, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDUSessionResourceSetupResponse */ + sendbuf = testngap_sess_build_pdu_session_resource_setup_response(sess); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = testgnb_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send GTP-U ICMP Packet */ + rv = test_gtpu_send_ping(gtpu, qos_flow, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = testgnb_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send GTP-U Router Solicitation */ + rv = test_gtpu_send_slacc_rs(gtpu, qos_flow); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U Router Advertisement */ + recvbuf = test_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + testgtpu_recv(test_ue, recvbuf); + + /* Send PDU session establishment request */ + sess = test_sess_add_by_dnn_and_psi(test_ue, "ims", 6); + ogs_assert(sess); + + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_INITIAL; + sess->ul_nas_transport_param.dnn = 1; + sess->ul_nas_transport_param.s_nssai = 1; + + sess->pdu_session_establishment_param.ssc_mode = 1; + sess->pdu_session_establishment_param.epco = 1; + + gsmbuf = testgsm_build_pdu_session_establishment_request(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDU session establishment accept */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + + /* Send PDUSessionResourceSetupResponse */ + sendbuf = testngap_sess_build_pdu_session_resource_setup_response(sess); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Add AF-Session */ + af_sess = af_sess_add_by_ue_address(&sess->ue_ip); + ogs_assert(af_sess); + + af_sess->supi = ogs_strdup(test_ue->supi); + ogs_assert(af_sess->supi); + + af_sess->dnn = ogs_strdup(sess->dnn); + ogs_assert(af_sess->dnn); + + af_local_discover_and_send(OpenAPI_nf_type_BSF, af_sess, NULL, + af_nbsf_management_build_discover); + + /* Wait for PCF-Discovery */ + ogs_msleep(100); + + /* Send AF-Session : CREATE */ + memset(&af_param, 0, sizeof(af_param)); + af_local_send_to_pcf(af_sess, &af_param, + af_npcf_policyauthorization_build_create_video); + + /* Receive PDUSessionResourceModifyRequest + + * DL NAS transport + + * PDU session modification command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceModify, + test_ue->ngap_procedure_code); + + /* Receive PDUSessionResourceModifyRequest + + * DL NAS transport + + * PDU session modification command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceModify, + test_ue->ngap_procedure_code); + + /* Send PDU session resource modify response */ + qos_flow = test_qos_flow_find_by_qfi(sess, 2); + ogs_assert(qos_flow); + + sendbuf = testngap_build_qos_flow_resource_modify_response(qos_flow); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDU session resource modify complete */ + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_MODIFICATION_REQUEST; + sess->ul_nas_transport_param.dnn = 0; + sess->ul_nas_transport_param.s_nssai = 0; + + sess->pdu_session_establishment_param.ssc_mode = 0; + sess->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_modification_complete(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Wait for PDU session resource modify complete */ + ogs_msleep(100); + + /* Send PDU session resource modify response */ + qos_flow = test_qos_flow_find_by_qfi(sess, 3); + ogs_assert(qos_flow); + + sendbuf = testngap_build_qos_flow_resource_modify_response(qos_flow); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDU session resource modify complete */ + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_MODIFICATION_REQUEST; + sess->ul_nas_transport_param.dnn = 0; + sess->ul_nas_transport_param.s_nssai = 0; + + sess->pdu_session_establishment_param.ssc_mode = 0; + sess->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_modification_complete(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Wait for PDU session resource modify complete */ + ogs_msleep(100); + + /* Send PDU session modification request */ + qos_flow = test_qos_flow_find_by_qfi(sess, 2); + ogs_assert(qos_flow); + + sess->pti = 8; + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_MODIFICATION_REQUEST; + sess->ul_nas_transport_param.dnn = 1; + sess->ul_nas_transport_param.s_nssai = 1; + + sess->pdu_session_establishment_param.ssc_mode = 1; + sess->pdu_session_establishment_param.epco = 1; + + gsmbuf = testgsm_build_pdu_session_modification_request( + qos_flow, + 0, + OGS_NAS_QOS_CODE_MODIFY_EXISTING_QOS_RULE_AND_DELETE_PACKET_FILTERS, + 0); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive PDUSessionResourceModifyRequest + + * DL NAS transport + + * PDU session modification command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceModify, + test_ue->ngap_procedure_code); + + /* Send PDU session resource modify response */ + qos_flow = test_qos_flow_find_by_qfi(sess, 2); + ogs_assert(qos_flow); + + sendbuf = testngap_build_qos_flow_resource_release_response(qos_flow); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDU session resource modify complete */ + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_MODIFICATION_REQUEST; + sess->ul_nas_transport_param.dnn = 0; + sess->ul_nas_transport_param.s_nssai = 0; + + sess->pdu_session_establishment_param.ssc_mode = 0; + sess->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_modification_complete(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Wait for PDU session resource modify complete */ + ogs_msleep(100); + + /* Test Bearer Remove */ + test_bearer_remove(qos_flow); + + /* Send AF-Session : DELETE */ + af_local_send_to_pcf(af_sess, NULL, + af_npcf_policyauthorization_build_delete); + + /* Receive PDUSessionResourceModifyRequest + + * DL NAS transport + + * PDU session modification command */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_PDUSessionResourceModify, + test_ue->ngap_procedure_code); + + /* Send PDU session resource modify response */ + qos_flow = test_qos_flow_find_by_qfi(sess, 3); + ogs_assert(qos_flow); + + sendbuf = testngap_build_qos_flow_resource_release_response(qos_flow); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send PDU session resource modify complete */ + sess->ul_nas_transport_param.request_type = + OGS_NAS_5GS_REQUEST_TYPE_MODIFICATION_REQUEST; + sess->ul_nas_transport_param.dnn = 0; + sess->ul_nas_transport_param.s_nssai = 0; + + sess->pdu_session_establishment_param.ssc_mode = 0; + sess->pdu_session_establishment_param.epco = 0; + + gsmbuf = testgsm_build_pdu_session_modification_complete(sess); + ABTS_PTR_NOTNULL(tc, gsmbuf); + gmmbuf = testgmm_build_ul_nas_transport(sess, + OGS_NAS_PAYLOAD_CONTAINER_N1_SM_INFORMATION, gsmbuf); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Wait for PDU session resource modify complete */ + ogs_msleep(100); + + /* Test Bearer Remove */ + test_bearer_remove(qos_flow); + + /* Send De-registration request */ + gmmbuf = testgmm_build_de_registration_request(test_ue, 1); + ABTS_PTR_NOTNULL(tc, gmmbuf); + sendbuf = testngap_build_uplink_nas_transport(test_ue, gmmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive UEContextReleaseCommand */ + recvbuf = testgnb_ngap_read(ngap); + ABTS_PTR_NOTNULL(tc, recvbuf); + testngap_recv(test_ue, recvbuf); + ABTS_INT_EQUAL(tc, + NGAP_ProcedureCode_id_UEContextRelease, + test_ue->ngap_procedure_code); + + /* Send UEContextReleaseComplete */ + sendbuf = testngap_build_ue_context_release_complete(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testgnb_ngap_send(ngap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + ogs_msleep(300); + + /********** Remove Subscriber in Database */ + ABTS_INT_EQUAL(tc, OGS_OK, test_db_remove_ue(test_ue)); + + /* gNB disonncect from UPF */ + testgnb_gtpu_close(gtpu); + + /* gNB disonncect from AMF */ + testgnb_ngap_close(ngap); + + /* Clear Test UE Context */ + test_ue_remove(test_ue); +} + +abts_suite *test_video(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, test1_func, NULL); + + return suite; +}