diff --git a/lib/app/ogs-context.c b/lib/app/ogs-context.c index f05c8faed..4e23f9957 100644 --- a/lib/app/ogs-context.c +++ b/lib/app/ogs-context.c @@ -60,13 +60,10 @@ ogs_app_context_t *ogs_app() static void recalculate_pool_size(void) { -#define MAX_NUM_OF_BEARER 4 /* Num of Bearer per Session */ #define MAX_NUM_OF_TUNNEL 3 /* Num of Tunnel per Bearer */ -#define MAX_NUM_OF_PF 16 /* Num of PacketFilter per Bearer */ self.pool.sess = self.max.ue * OGS_MAX_NUM_OF_SESS; - self.pool.bearer = self.pool.sess * MAX_NUM_OF_BEARER; + self.pool.bearer = self.pool.sess * OGS_MAX_NUM_OF_BEARER; self.pool.tunnel = self.pool.bearer * MAX_NUM_OF_TUNNEL; - self.pool.pf = self.pool.bearer * MAX_NUM_OF_PF; #define MAX_NUM_OF_TIMER 16 self.pool.timer = self.max.ue * MAX_NUM_OF_TIMER; diff --git a/lib/app/ogs-context.h b/lib/app/ogs-context.h index dd46bb641..03988e50c 100644 --- a/lib/app/ogs-context.h +++ b/lib/app/ogs-context.h @@ -90,7 +90,6 @@ typedef struct ogs_app_context_s { uint64_t sess; uint64_t bearer; uint64_t tunnel; - uint64_t pf; uint64_t nf_service; uint64_t nf_subscription; uint64_t sbi_message; diff --git a/lib/core/ogs-3gpp-types.h b/lib/core/ogs-3gpp-types.h index 8ddd50ef0..820232706 100644 --- a/lib/core/ogs-3gpp-types.h +++ b/lib/core/ogs-3gpp-types.h @@ -29,7 +29,9 @@ extern "C" { #endif /* __cplusplus */ #define OGS_MAX_NUM_OF_SESS 4 /* Num of APN(Session) per UE */ +#define OGS_MAX_NUM_OF_BEARER 4 /* Num of Bearer per Session */ #define OGS_MAX_NUM_OF_RULE 4 /* Num of Rule per Session */ +#define OGS_MAX_NUM_OF_PF 16 /* Num of PacketFilter per Bearer */ /* Num of PacketFilter per Bearer(GTP) or QoS(NAS-5GS) */ #define OGS_MAX_NUM_OF_PACKET_FILTER 16 diff --git a/lib/diameter/common/init.c b/lib/diameter/common/init.c index 900da3a7d..466e2aa92 100644 --- a/lib/diameter/common/init.c +++ b/lib/diameter/common/init.c @@ -90,15 +90,15 @@ static void diam_gnutls_log_func(int level, const char *str) static void diam_log_func(int printlevel, const char *fname, int line, const char *format, va_list ap) { - char buffer[OGS_HUGE_LEN]; + char buffer[OGS_HUGE_LEN*2]; int ret = 0; #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wformat-nonliteral" - ret = vsnprintf(buffer, OGS_HUGE_LEN, format, ap); + ret = ogs_vsnprintf(buffer, OGS_HUGE_LEN*2, format, ap); #pragma GCC diagnostic pop - if (ret < 0 || ret > OGS_HUGE_LEN) { - ogs_error("vsnprintf() failed"); + if (ret < 0 || ret > OGS_HUGE_LEN*2) { + ogs_error("vsnprintf() failed[ret=%d]", ret); return; } diff --git a/lib/diameter/common/message.c b/lib/diameter/common/message.c index 2f245ace1..91cb6850d 100644 --- a/lib/diameter/common/message.c +++ b/lib/diameter/common/message.c @@ -40,6 +40,9 @@ struct dict_object *ogs_diam_experimental_result_code = NULL; struct dict_object *ogs_diam_vendor_specific_application_id = NULL; struct dict_object *ogs_diam_mip6_agent_info = NULL; struct dict_object *ogs_diam_mip_home_agent_address = NULL; +struct dict_object *ogs_diam_authorization_lifetime = NULL; +struct dict_object *ogs_diam_auth_grace_period = NULL; +struct dict_object *ogs_diam_session_timeout = NULL; struct dict_object *ogs_diam_vendor = NULL; struct dict_object *ogs_diam_vendor_id = NULL; @@ -71,6 +74,9 @@ int ogs_diam_message_init() CHECK_dict_search( DICT_AVP, AVP_BY_NAME, "Vendor-Specific-Application-Id", &ogs_diam_vendor_specific_application_id); CHECK_dict_search( DICT_AVP, AVP_BY_NAME, "MIP6-Agent-Info", &ogs_diam_mip6_agent_info); CHECK_dict_search( DICT_AVP, AVP_BY_NAME, "MIP-Home-Agent-Address", &ogs_diam_mip_home_agent_address); + CHECK_dict_search( DICT_AVP, AVP_BY_NAME, "Authorization-Lifetime", &ogs_diam_authorization_lifetime); + CHECK_dict_search( DICT_AVP, AVP_BY_NAME, "Auth-Grace-Period", &ogs_diam_auth_grace_period); + CHECK_dict_search( DICT_AVP, AVP_BY_NAME, "Session-Timeout", &ogs_diam_session_timeout); return 0; } diff --git a/lib/diameter/common/message.h b/lib/diameter/common/message.h index 97dc65716..dea82bfaa 100644 --- a/lib/diameter/common/message.h +++ b/lib/diameter/common/message.h @@ -62,6 +62,9 @@ extern struct dict_object *ogs_diam_experimental_result_code; extern struct dict_object *ogs_diam_vendor_specific_application_id; extern struct dict_object *ogs_diam_mip6_agent_info; extern struct dict_object *ogs_diam_mip_home_agent_address; +extern struct dict_object *ogs_diam_authorization_lifetime; +extern struct dict_object *ogs_diam_auth_grace_period; +extern struct dict_object *ogs_diam_session_timeout; extern struct dict_object *ogs_diam_vendor; extern struct dict_object *ogs_diam_vendor_id; diff --git a/lib/diameter/rx/message.c b/lib/diameter/rx/message.c index 7632f11f1..139d8dc52 100644 --- a/lib/diameter/rx/message.c +++ b/lib/diameter/rx/message.c @@ -31,6 +31,7 @@ struct dict_object *ogs_diam_rx_cmd_asa = NULL; struct dict_object *ogs_diam_rx_cmd_str = NULL; struct dict_object *ogs_diam_rx_cmd_sta = NULL; +struct dict_object *ogs_diam_rx_af_application_identifier = NULL; struct dict_object *ogs_diam_rx_media_component_description = NULL; struct dict_object *ogs_diam_rx_media_component_number = NULL; struct dict_object *ogs_diam_rx_media_type = NULL; @@ -49,6 +50,7 @@ struct dict_object *ogs_diam_rx_flow_description = NULL; struct dict_object *ogs_diam_rx_subscription_id = NULL; struct dict_object *ogs_diam_rx_subscription_id_type = NULL; struct dict_object *ogs_diam_rx_subscription_id_data = NULL; +struct dict_object *ogs_diam_rx_reservation_priority = NULL; struct dict_object *ogs_diam_rx_specific_action = NULL; struct dict_object *ogs_diam_rx_framed_ip_address = NULL; struct dict_object *ogs_diam_rx_framed_ipv6_prefix = NULL; @@ -74,6 +76,7 @@ int ogs_diam_rx_init(void) CHECK_dict_search(DICT_COMMAND, CMD_BY_NAME, "Session-Termination-Request", &ogs_diam_rx_cmd_str); CHECK_dict_search(DICT_COMMAND, CMD_BY_NAME, "Session-Termination-Answer", &ogs_diam_rx_cmd_sta); + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "AF-Application-Identifier", &ogs_diam_rx_af_application_identifier); CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Media-Component-Description", &ogs_diam_rx_media_component_description); CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Media-Component-Number", &ogs_diam_rx_media_component_number); CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Media-Type", &ogs_diam_rx_media_type); @@ -92,6 +95,7 @@ int ogs_diam_rx_init(void) CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Subscription-Id", &ogs_diam_rx_subscription_id); CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Subscription-Id-Type", &ogs_diam_rx_subscription_id_type); CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Subscription-Id-Data", &ogs_diam_rx_subscription_id_data); + CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Reservation-Priority", &ogs_diam_rx_reservation_priority); CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Specific-Action", &ogs_diam_rx_specific_action); CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Framed-IP-Address", &ogs_diam_rx_framed_ip_address); CHECK_dict_search(DICT_AVP, AVP_BY_NAME_ALL_VENDORS, "Framed-IPv6-Prefix", &ogs_diam_rx_framed_ipv6_prefix); diff --git a/lib/diameter/rx/message.h b/lib/diameter/rx/message.h index dadebe6c9..6bc806705 100644 --- a/lib/diameter/rx/message.h +++ b/lib/diameter/rx/message.h @@ -57,6 +57,7 @@ extern struct dict_object *ogs_diam_rx_cmd_asa; extern struct dict_object *ogs_diam_rx_cmd_str; extern struct dict_object *ogs_diam_rx_cmd_sta; +extern struct dict_object *ogs_diam_rx_af_application_identifier; extern struct dict_object *ogs_diam_rx_media_component_description; extern struct dict_object *ogs_diam_rx_media_component_number; extern struct dict_object *ogs_diam_rx_media_type; @@ -83,6 +84,14 @@ extern struct dict_object *ogs_diam_rx_subscription_id; #define OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_NAI 3 extern struct dict_object *ogs_diam_rx_subscription_id_type; extern struct dict_object *ogs_diam_rx_subscription_id_data; +extern struct dict_object *ogs_diam_rx_reservation_priority; +#define OGS_DIAM_RX_SPECIFIC_ACTION_CHARGING_CORRELATION_EXCHANGE 1 +#define OGS_DIAM_RX_SPECIFIC_ACTION_INDICATION_OF_LOSS_OF_BEARER 2 +#define OGS_DIAM_RX_SPECIFIC_ACTION_INDICATION_OF_RECOVERY_OF_BEARER 3 +#define OGS_DIAM_RX_SPECIFIC_ACTION_INDICATION_OF_RELEASE_OF_BEARER 4 +#define OGS_DIAM_RX_SPECIFIC_ACTION_INDICATION_OF_ESTABLISHMENT_OF_BEARER 5 +#define OGS_DIAM_RX_SPECIFIC_ACTION_IP_CAN_CHANGE 6 +#define OGS_DIAM_RX_SPECIFIC_ACTION_ACCESS_NETWORK_INFO_REPORT 12 extern struct dict_object *ogs_diam_rx_specific_action; extern struct dict_object *ogs_diam_rx_framed_ip_address; extern struct dict_object *ogs_diam_rx_framed_ipv6_prefix; diff --git a/lib/pfcp/context.c b/lib/pfcp/context.c index 1fe5652ae..4232443af 100644 --- a/lib/pfcp/context.c +++ b/lib/pfcp/context.c @@ -26,11 +26,6 @@ static OGS_POOL(ogs_pfcp_node_pool, ogs_pfcp_node_t); static OGS_POOL(ogs_pfcp_gtpu_resource_pool, ogs_pfcp_gtpu_resource_t); static OGS_POOL(ogs_pfcp_sess_pool, ogs_pfcp_sess_t); -static OGS_POOL(ogs_pfcp_pdr_pool, ogs_pfcp_pdr_t); -static OGS_POOL(ogs_pfcp_far_pool, ogs_pfcp_far_t); -static OGS_POOL(ogs_pfcp_urr_pool, ogs_pfcp_urr_t); -static OGS_POOL(ogs_pfcp_qer_pool, ogs_pfcp_qer_t); -static OGS_POOL(ogs_pfcp_bar_pool, ogs_pfcp_bar_t); static OGS_POOL(ogs_pfcp_dev_pool, ogs_pfcp_dev_t); static OGS_POOL(ogs_pfcp_subnet_pool, ogs_pfcp_subnet_t); @@ -72,16 +67,6 @@ void ogs_pfcp_context_init(int num_of_gtpu_resource) ogs_pool_init(&ogs_pfcp_sess_pool, ogs_app()->pool.sess); - ogs_pool_init(&ogs_pfcp_pdr_pool, - ogs_app()->pool.sess * OGS_MAX_NUM_OF_PDR); - ogs_pool_init(&ogs_pfcp_far_pool, - ogs_app()->pool.sess * OGS_MAX_NUM_OF_FAR); - ogs_pool_init(&ogs_pfcp_urr_pool, - ogs_app()->pool.sess * OGS_MAX_NUM_OF_URR); - ogs_pool_init(&ogs_pfcp_qer_pool, - ogs_app()->pool.sess * OGS_MAX_NUM_OF_QER); - ogs_pool_init(&ogs_pfcp_bar_pool, - ogs_app()->pool.sess * OGS_MAX_NUM_OF_BAR); ogs_pool_init(&ogs_pfcp_rule_pool, ogs_app()->pool.sess * OGS_MAX_NUM_OF_RULE); @@ -110,11 +95,6 @@ void ogs_pfcp_context_final(void) ogs_pool_final(&ogs_pfcp_rule_pool); ogs_pool_final(&ogs_pfcp_sess_pool); - ogs_pool_final(&ogs_pfcp_pdr_pool); - ogs_pool_final(&ogs_pfcp_far_pool); - ogs_pool_final(&ogs_pfcp_urr_pool); - ogs_pool_final(&ogs_pfcp_qer_pool); - ogs_pool_final(&ogs_pfcp_bar_pool); ogs_pfcp_node_remove_all(&self.peer_list); ogs_pfcp_gtpu_resource_remove_all(&self.gtpu_resource_list); @@ -811,10 +791,13 @@ ogs_pfcp_pdr_t *ogs_pfcp_pdr_add(ogs_pfcp_sess_t *sess) ogs_assert(sess); - ogs_pool_alloc(&ogs_pfcp_pdr_pool, &pdr); + ogs_pool_alloc(&sess->pdr_pool, &pdr); ogs_assert(pdr); memset(pdr, 0, sizeof *pdr); + pdr->index = ogs_pool_index(&sess->pdr_pool, pdr); + ogs_assert(pdr->index > 0 && pdr->index <= OGS_MAX_NUM_OF_PDR); + pdr->sess = sess; ogs_list_add(&sess->pdr_list, pdr); @@ -929,7 +912,7 @@ void ogs_pfcp_pdr_remove(ogs_pfcp_pdr_t *pdr) if (pdr->dnn) ogs_free(pdr->dnn); - ogs_pool_free(&ogs_pfcp_pdr_pool, pdr); + ogs_pool_free(&pdr->sess->pdr_pool, pdr); } void ogs_pfcp_pdr_remove_all(ogs_pfcp_sess_t *sess) @@ -947,10 +930,13 @@ ogs_pfcp_far_t *ogs_pfcp_far_add(ogs_pfcp_sess_t *sess) ogs_assert(sess); - ogs_pool_alloc(&ogs_pfcp_far_pool, &far); + ogs_pool_alloc(&sess->far_pool, &far); ogs_assert(far); memset(far, 0, sizeof *far); + far->index = ogs_pool_index(&sess->far_pool, far); + ogs_assert(far->index > 0 && far->index <= OGS_MAX_NUM_OF_FAR); + far->apply_action = OGS_PFCP_APPLY_ACTION_FORW; far->sess = sess; @@ -1002,7 +988,7 @@ void ogs_pfcp_far_remove(ogs_pfcp_far_t *far) ogs_pkbuf_free(far->buffered_packet[i]); ogs_list_remove(&sess->far_list, far); - ogs_pool_free(&ogs_pfcp_far_pool, far); + ogs_pool_free(&sess->far_pool, far); } void ogs_pfcp_far_remove_all(ogs_pfcp_sess_t *sess) @@ -1021,10 +1007,13 @@ ogs_pfcp_urr_t *ogs_pfcp_urr_add(ogs_pfcp_sess_t *sess) ogs_assert(sess); - ogs_pool_alloc(&ogs_pfcp_urr_pool, &urr); + ogs_pool_alloc(&sess->urr_pool, &urr); ogs_assert(urr); memset(urr, 0, sizeof *urr); + urr->index = ogs_pool_index(&sess->urr_pool, urr); + ogs_assert(urr->index > 0 && urr->index <= OGS_MAX_NUM_OF_URR); + urr->sess = sess; ogs_list_add(&sess->urr_list, urr); @@ -1070,7 +1059,7 @@ void ogs_pfcp_urr_remove(ogs_pfcp_urr_t *urr) ogs_assert(sess); ogs_list_remove(&sess->urr_list, urr); - ogs_pool_free(&ogs_pfcp_urr_pool, urr); + ogs_pool_free(&sess->urr_pool, urr); } void ogs_pfcp_urr_remove_all(ogs_pfcp_sess_t *sess) @@ -1089,10 +1078,13 @@ ogs_pfcp_qer_t *ogs_pfcp_qer_add(ogs_pfcp_sess_t *sess) ogs_assert(sess); - ogs_pool_alloc(&ogs_pfcp_qer_pool, &qer); + ogs_pool_alloc(&sess->qer_pool, &qer); ogs_assert(qer); memset(qer, 0, sizeof *qer); + qer->index = ogs_pool_index(&sess->qer_pool, qer); + ogs_assert(qer->index > 0 && qer->index <= OGS_MAX_NUM_OF_QER); + qer->sess = sess; ogs_list_add(&sess->qer_list, qer); @@ -1138,7 +1130,7 @@ void ogs_pfcp_qer_remove(ogs_pfcp_qer_t *qer) ogs_assert(sess); ogs_list_remove(&sess->qer_list, qer); - ogs_pool_free(&ogs_pfcp_qer_pool, qer); + ogs_pool_free(&sess->qer_pool, qer); } void ogs_pfcp_qer_remove_all(ogs_pfcp_sess_t *sess) @@ -1158,7 +1150,7 @@ ogs_pfcp_bar_t *ogs_pfcp_bar_new(ogs_pfcp_sess_t *sess) ogs_assert(sess); ogs_assert(sess->bar == NULL); /* Only One BAR is supported */ - ogs_pool_alloc(&ogs_pfcp_bar_pool, &bar); + ogs_pool_alloc(&sess->bar_pool, &bar); ogs_assert(bar); memset(bar, 0, sizeof *bar); @@ -1179,7 +1171,7 @@ void ogs_pfcp_bar_delete(ogs_pfcp_bar_t *bar) bar->sess = NULL; sess->bar = NULL; - ogs_pool_free(&ogs_pfcp_bar_pool, bar); + ogs_pool_free(&sess->bar_pool, bar); } ogs_pfcp_rule_t *ogs_pfcp_rule_add(ogs_pfcp_pdr_t *pdr) diff --git a/lib/pfcp/context.h b/lib/pfcp/context.h index d5015f25d..42e987f89 100644 --- a/lib/pfcp/context.h +++ b/lib/pfcp/context.h @@ -103,25 +103,16 @@ typedef struct ogs_pfcp_gtpu_resource_s { ogs_pfcp_user_plane_ip_resource_info_t info; } __attribute__ ((packed)) ogs_pfcp_gtpu_resource_t; +typedef struct ogs_pfcp_sess_s ogs_pfcp_sess_t; typedef struct ogs_pfcp_pdr_s ogs_pfcp_pdr_t; typedef struct ogs_pfcp_far_s ogs_pfcp_far_t; typedef struct ogs_pfcp_urr_s ogs_pfcp_urr_t; typedef struct ogs_pfcp_qer_s ogs_pfcp_qer_t; typedef struct ogs_pfcp_bar_s ogs_pfcp_bar_t; -typedef struct ogs_pfcp_sess_s { - ogs_list_t pdr_list; /* PDR List */ - ogs_list_t far_list; /* FAR List */ - ogs_list_t urr_list; /* URR List */ - ogs_list_t qer_list; /* QER List */ - ogs_pfcp_bar_t *bar; /* BAR Item */ - - /* Related Context */ - ogs_pfcp_pdr_t *default_pdr; /* Used by UPF */ -} ogs_pfcp_sess_t; - typedef struct ogs_pfcp_pdr_s { ogs_lnode_t lnode; + uint32_t index; uint64_t hashkey; @@ -159,6 +150,7 @@ typedef struct ogs_pfcp_pdr_s { typedef struct ogs_pfcp_far_s { ogs_lnode_t lnode; + uint32_t index; ogs_pfcp_far_id_t id; ogs_pfcp_apply_action_t apply_action; @@ -179,6 +171,7 @@ typedef struct ogs_pfcp_far_s { typedef struct ogs_pfcp_urr_s { ogs_lnode_t lnode; + uint32_t index; ogs_pfcp_urr_id_t id; @@ -187,6 +180,7 @@ typedef struct ogs_pfcp_urr_s { typedef struct ogs_pfcp_qer_s { ogs_lnode_t lnode; + uint32_t index; ogs_pfcp_qer_id_t id; @@ -205,6 +199,23 @@ typedef struct ogs_pfcp_bar_s { ogs_pfcp_sess_t *sess; } ogs_pfcp_bar_t; +typedef struct ogs_pfcp_sess_s { + ogs_list_t pdr_list; /* PDR List */ + ogs_list_t far_list; /* FAR List */ + ogs_list_t urr_list; /* URR List */ + ogs_list_t qer_list; /* QER List */ + ogs_pfcp_bar_t *bar; /* BAR Item */ + + OGS_POOL(pdr_pool, ogs_pfcp_pdr_t); + OGS_POOL(far_pool, ogs_pfcp_far_t); + OGS_POOL(urr_pool, ogs_pfcp_urr_t); + OGS_POOL(qer_pool, ogs_pfcp_qer_t); + OGS_POOL(bar_pool, ogs_pfcp_bar_t); + + /* Related Context */ + ogs_pfcp_pdr_t *default_pdr; /* Used by UPF */ +} ogs_pfcp_sess_t; + typedef struct ogs_pfcp_subnet_s ogs_pfcp_subnet_t; typedef struct ogs_pfcp_ue_ip_s { uint32_t addr[4]; diff --git a/lib/pfcp/message.c b/lib/pfcp/message.c index f60fe2e6c..d1235f825 100644 --- a/lib/pfcp/message.c +++ b/lib/pfcp/message.c @@ -20,7 +20,7 @@ /******************************************************************************* * This file had been created by pfcp-tlv.py script v0.1.0 * Please do not modify this file but regenerate it via script. - * Created on: 2020-08-12 20:18:49.875450 by acetcom + * Created on: 2020-08-28 21:50:38.885547 by acetcom * from 29244-g10.docx ******************************************************************************/ @@ -2579,7 +2579,7 @@ ogs_tlv_desc_t ogs_pfcp_msg_desc_pfcp_session_establishment_request = &ogs_pfcp_tlv_desc_create_urr, &ogs_tlv_desc_more2, &ogs_pfcp_tlv_desc_create_qer, - &ogs_tlv_desc_more2, + &ogs_tlv_desc_more4, &ogs_pfcp_tlv_desc_create_bar, &ogs_pfcp_tlv_desc_create_traffic_endpoint, &ogs_pfcp_tlv_desc_pdn_type, @@ -2629,7 +2629,7 @@ ogs_tlv_desc_t ogs_pfcp_msg_desc_pfcp_session_modification_request = &ogs_pfcp_tlv_desc_remove_urr, &ogs_tlv_desc_more2, &ogs_pfcp_tlv_desc_remove_qer, - &ogs_tlv_desc_more2, + &ogs_tlv_desc_more4, &ogs_pfcp_tlv_desc_remove_bar, &ogs_pfcp_tlv_desc_remove_traffic_endpoint, &ogs_pfcp_tlv_desc_create_pdr, @@ -2639,7 +2639,7 @@ ogs_tlv_desc_t ogs_pfcp_msg_desc_pfcp_session_modification_request = &ogs_pfcp_tlv_desc_create_urr, &ogs_tlv_desc_more2, &ogs_pfcp_tlv_desc_create_qer, - &ogs_tlv_desc_more2, + &ogs_tlv_desc_more4, &ogs_pfcp_tlv_desc_create_bar, &ogs_pfcp_tlv_desc_create_traffic_endpoint, &ogs_pfcp_tlv_desc_update_pdr, @@ -2649,7 +2649,7 @@ ogs_tlv_desc_t ogs_pfcp_msg_desc_pfcp_session_modification_request = &ogs_pfcp_tlv_desc_update_urr, &ogs_tlv_desc_more2, &ogs_pfcp_tlv_desc_update_qer, - &ogs_tlv_desc_more2, + &ogs_tlv_desc_more4, &ogs_pfcp_tlv_desc_update_bar_session_modification_request, &ogs_pfcp_tlv_desc_update_traffic_endpoint, &ogs_pfcp_tlv_desc_pfcpsmreq_flags, diff --git a/lib/pfcp/message.h b/lib/pfcp/message.h index b470c47ff..bd9c4055a 100644 --- a/lib/pfcp/message.h +++ b/lib/pfcp/message.h @@ -20,7 +20,7 @@ /******************************************************************************* * This file had been created by pfcp-tlv.py script v0.1.0 * Please do not modify this file but regenerate it via script. - * Created on: 2020-08-12 20:18:49.864313 by acetcom + * Created on: 2020-08-28 21:50:38.876204 by acetcom * from 29244-g10.docx ******************************************************************************/ @@ -1185,7 +1185,7 @@ typedef struct ogs_pfcp_session_establishment_request_s { ogs_pfcp_tlv_create_pdr_t create_pdr[8]; ogs_pfcp_tlv_create_far_t create_far[8]; ogs_pfcp_tlv_create_urr_t create_urr[2]; - ogs_pfcp_tlv_create_qer_t create_qer[2]; + ogs_pfcp_tlv_create_qer_t create_qer[4]; ogs_pfcp_tlv_create_bar_t create_bar; ogs_pfcp_tlv_create_traffic_endpoint_t create_traffic_endpoint; ogs_pfcp_tlv_pdn_type_t pdn_type; @@ -1220,19 +1220,19 @@ typedef struct ogs_pfcp_session_modification_request_s { ogs_pfcp_tlv_remove_pdr_t remove_pdr[8]; ogs_pfcp_tlv_remove_far_t remove_far[8]; ogs_pfcp_tlv_remove_urr_t remove_urr[2]; - ogs_pfcp_tlv_remove_qer_t remove_qer[2]; + ogs_pfcp_tlv_remove_qer_t remove_qer[4]; ogs_pfcp_tlv_remove_bar_t remove_bar; ogs_pfcp_tlv_remove_traffic_endpoint_t remove_traffic_endpoint; ogs_pfcp_tlv_create_pdr_t create_pdr[8]; ogs_pfcp_tlv_create_far_t create_far[8]; ogs_pfcp_tlv_create_urr_t create_urr[2]; - ogs_pfcp_tlv_create_qer_t create_qer[2]; + ogs_pfcp_tlv_create_qer_t create_qer[4]; ogs_pfcp_tlv_create_bar_t create_bar; ogs_pfcp_tlv_create_traffic_endpoint_t create_traffic_endpoint; ogs_pfcp_tlv_update_pdr_t update_pdr[8]; ogs_pfcp_tlv_update_far_t update_far[8]; ogs_pfcp_tlv_update_urr_t update_urr[2]; - ogs_pfcp_tlv_update_qer_t update_qer[2]; + ogs_pfcp_tlv_update_qer_t update_qer[4]; ogs_pfcp_tlv_update_bar_session_modification_request_t update_bar; ogs_pfcp_tlv_update_traffic_endpoint_t update_traffic_endpoint; ogs_pfcp_tlv_pfcpsmreq_flags_t pfcpsmreq_flags; diff --git a/lib/pfcp/ogs-pfcp.h b/lib/pfcp/ogs-pfcp.h index 7f3a12acb..37c74f721 100644 --- a/lib/pfcp/ogs-pfcp.h +++ b/lib/pfcp/ogs-pfcp.h @@ -27,10 +27,10 @@ #define OGS_PFCP_UDP_PORT 8805 -#define OGS_MAX_NUM_OF_PDR 8 -#define OGS_MAX_NUM_OF_FAR 8 +#define OGS_MAX_NUM_OF_PDR 16 +#define OGS_MAX_NUM_OF_FAR 16 #define OGS_MAX_NUM_OF_URR 2 -#define OGS_MAX_NUM_OF_QER 2 +#define OGS_MAX_NUM_OF_QER 4 #define OGS_MAX_NUM_OF_BAR 1 #define OGS_MAX_NUM_OF_GTPU_RESOURCE 4 diff --git a/lib/pfcp/support/cache/tlv-msg-50.py b/lib/pfcp/support/cache/tlv-msg-50.py index a7d780461..c5d73bc80 100644 --- a/lib/pfcp/support/cache/tlv-msg-50.py +++ b/lib/pfcp/support/cache/tlv-msg-50.py @@ -4,7 +4,7 @@ ies.append({ "ie_type" : "F-SEID", "ie_value" : "CP F-SEID", "presence" : "M", " ies.append({ "ie_type" : "Create PDR", "ie_value" : "Create PDR", "presence" : "M", "tlv_more" : "7", "comment" : "This IE shall be present for at least one PDR to be associated to the PFCP session.Several IEs with the same IE type may be present to represent multiple PDRs.See Table 7.5.2.2-1."}) ies.append({ "ie_type" : "Create FAR", "ie_value" : "Create FAR", "presence" : "M", "tlv_more" : "7", "comment" : "This IE shall be present for at least one FAR to be associated to the PFCP session.Several IEs with the same IE type may be present to represent multiple FARs.See Table 7.5.2.3-1."}) ies.append({ "ie_type" : "Create URR", "ie_value" : "Create URR", "presence" : "C", "tlv_more" : "1", "comment" : "This IE shall be present if a measurement action shall be applied to packets matching one or more PDR(s) of this PFCP session.Several IEs within the same IE type may be present to represent multiple URRs.See Table 7.5.2.4-1."}) -ies.append({ "ie_type" : "Create QER", "ie_value" : "Create QER", "presence" : "C", "tlv_more" : "1", "comment" : "This IE shall be present if a QoS enforcement or QoS marking action shall be applied to packets matching one or more PDR(s) of this PFCP session.Several IEs within the same IE type may be present to represent multiple QERs.See Table 7.5.2.5-1."}) +ies.append({ "ie_type" : "Create QER", "ie_value" : "Create QER", "presence" : "C", "tlv_more" : "3", "comment" : "This IE shall be present if a QoS enforcement or QoS marking action shall be applied to packets matching one or more PDR(s) of this PFCP session.Several IEs within the same IE type may be present to represent multiple QERs.See Table 7.5.2.5-1."}) ies.append({ "ie_type" : "Create BAR", "ie_value" : "Create BAR", "presence" : "O", "tlv_more" : "0", "comment" : "When present, this IE shall contain the buffering instructions to be applied by the UP function to any FAR of this PFCP session set with the Apply Action requesting the packets to be buffered and with a BAR ID IE referring to this BAR. See table 7.5.2.6-1."}) ies.append({ "ie_type" : "Create Traffic Endpoint", "ie_value" : "Create Traffic Endpoint", "presence" : "C", "tlv_more" : "0", "comment" : "This IE may be present if the UP function has indicated support of PDI optimization.Several IEs within the same IE type may be present to represent multiple Traffic Endpoints.See Table 7.5.2.7-1."}) ies.append({ "ie_type" : "PDN Type", "ie_value" : "PDN Type", "presence" : "C", "tlv_more" : "0", "comment" : "This IE shall be present if the PFCP session is setup for an individual PDN connection or PDU session (see clause 5.2.1).When present, this IE shall indicate whether this is an IP or non-IP PDN connection/PDU session or, for 5GC, an Ethernet PDU session. See NOTE 3."}) diff --git a/lib/pfcp/support/cache/tlv-msg-52.py b/lib/pfcp/support/cache/tlv-msg-52.py index efb4f1622..08fda64ee 100644 --- a/lib/pfcp/support/cache/tlv-msg-52.py +++ b/lib/pfcp/support/cache/tlv-msg-52.py @@ -6,8 +6,8 @@ type_list["Remove FAR"]["max_tlv_more"] = "7" ies.append({ "ie_type" : "Remove FAR", "ie_value" : "Remove FAR", "presence" : "C", "tlv_more" : "7", "comment" : "When present, this IE shall contain the FAR Rule which is requested to be removed. See Table 7.5.4-7-1.Several IEs within the same IE type may be present to represent a list of FARs to remove."}) type_list["Remove URR"]["max_tlv_more"] = "1" ies.append({ "ie_type" : "Remove URR", "ie_value" : "Remove URR", "presence" : "C", "tlv_more" : "1", "comment" : "When present, this shall contain the URR Rule which is requested to be removed. See Table 7.5.4-8-1.Several IEs within the same IE type may be present to represent a list of URRs to remove."}) -type_list["Remove QER"]["max_tlv_more"] = "1" -ies.append({ "ie_type" : "Remove QER", "ie_value" : "Remove QER", "presence" : "C", "tlv_more" : "1", "comment" : "When present, this IE shall contain the QER Rule which is requested to be removed. See Table 7.5.4-9-1.Several IEs within the same IE type may be present to represent a list of QERs to remove."}) +type_list["Remove QER"]["max_tlv_more"] = "3" +ies.append({ "ie_type" : "Remove QER", "ie_value" : "Remove QER", "presence" : "C", "tlv_more" : "3", "comment" : "When present, this IE shall contain the QER Rule which is requested to be removed. See Table 7.5.4-9-1.Several IEs within the same IE type may be present to represent a list of QERs to remove."}) ies.append({ "ie_type" : "Remove BAR", "ie_value" : "Remove BAR", "presence" : "C", "tlv_more" : "0", "comment" : "When present, this IE shall contain the BAR Rule which is requested to be removed. See Table 7.5.4.12-1."}) ies.append({ "ie_type" : "Remove Traffic Endpoint", "ie_value" : "Remove Traffic Endpoint", "presence" : "C", "tlv_more" : "0", "comment" : "When present, this IE shall contain the Traffic Endpoint ID identifying the traffic endpoint to be removed, if the UP function has indicated support of PDI optimization.All the PDRs that refer to the removed Traffic Endpoint shall be deleted.See Table 7.5.4.14-1."}) type_list["Create PDR"]["max_tlv_more"] = "7" @@ -16,8 +16,8 @@ type_list["Create FAR"]["max_tlv_more"] = "7" ies.append({ "ie_type" : "Create FAR", "ie_value" : "Create FAR", "presence" : "C", "tlv_more" : "7", "comment" : "This IE shall be present if the CP function requests the UP function to create a new FAR.See Table 7.5.2.3-1.Several IEs within the same IE type may be present to represent a list of FARs to create."}) type_list["Create URR"]["max_tlv_more"] = "1" ies.append({ "ie_type" : "Create URR", "ie_value" : "Create URR", "presence" : "C", "tlv_more" : "1", "comment" : "This IE shall be present if the CP function requests the UP function to create a new URR. See Table 7.5.2.4-1.Several IEs within the same IE type may be present to represent a list of URRs to create."}) -type_list["Create QER"]["max_tlv_more"] = "1" -ies.append({ "ie_type" : "Create QER", "ie_value" : "Create QER", "presence" : "C", "tlv_more" : "1", "comment" : "This IE shall be present if the CP function requests the UP function to create a new QER. See Table 7.5.2.5-1.Several IEs within the same IE type may be present to represent a list of QERs to create."}) +type_list["Create QER"]["max_tlv_more"] = "3" +ies.append({ "ie_type" : "Create QER", "ie_value" : "Create QER", "presence" : "C", "tlv_more" : "3", "comment" : "This IE shall be present if the CP function requests the UP function to create a new QER. See Table 7.5.2.5-1.Several IEs within the same IE type may be present to represent a list of QERs to create."}) ies.append({ "ie_type" : "Create BAR", "ie_value" : "Create BAR", "presence" : "C", "tlv_more" : "0", "comment" : "This IE shall be present if the CP function requests the UP function to create a new BAR.See Table 7.5.2.6-1."}) ies.append({ "ie_type" : "Create Traffic Endpoint", "ie_value" : "Create Traffic Endpoint", "presence" : "C", "tlv_more" : "0", "comment" : "When present this IE shall contain the information associated with the Traffic Endpoint to be created, if the UP function has indicated support of PDI optimization. See Table 7.5.2.7-1."}) type_list["Update PDR"]["max_tlv_more"] = "7" @@ -26,8 +26,8 @@ type_list["Update FAR"]["max_tlv_more"] = "7" ies.append({ "ie_type" : "Update FAR", "ie_value" : "Update FAR", "presence" : "C", "tlv_more" : "7", "comment" : "This IE shall be present if a FAR previously created for the PFCP session need to be modified. See Table 7.5.4.3-1. Several IEs within the same IE type may be present to represent a list of FARs to update."}) type_list["Update URR"]["max_tlv_more"] = "1" ies.append({ "ie_type" : "Update URR", "ie_value" : "Update URR", "presence" : "C", "tlv_more" : "1", "comment" : "This IE shall be present if URR(s) previously created for the PFCP session need to be modified.Several IEs within the same IE type may be present to represent a list of modified URRs. Previously URRs that are not modified shall not be included. See Table 7.5.4.4-1."}) -type_list["Update QER"]["max_tlv_more"] = "1" -ies.append({ "ie_type" : "Update QER", "ie_value" : "Update QER", "presence" : "C", "tlv_more" : "1", "comment" : "This IE shall be present if QER(s) previously created for the PFCP session need to be modified.Several IEs within the same IE type may be present to represent a list of modified QERs.Previously created QERs that are not modified shall not be included.See Table 7.5.4.5-1."}) +type_list["Update QER"]["max_tlv_more"] = "3" +ies.append({ "ie_type" : "Update QER", "ie_value" : "Update QER", "presence" : "C", "tlv_more" : "3", "comment" : "This IE shall be present if QER(s) previously created for the PFCP session need to be modified.Several IEs within the same IE type may be present to represent a list of modified QERs.Previously created QERs that are not modified shall not be included.See Table 7.5.4.5-1."}) ies.append({ "ie_type" : "Update BAR Session Modification Request", "ie_value" : "Update BAR", "presence" : "C", "tlv_more" : "0", "comment" : "This IE shall be present if a BAR previously created for the PFCP session needs to be modified.A previously created BAR that is not modified shall not be included.See Table 7.5.4.11-1."}) ies.append({ "ie_type" : "Update Traffic Endpoint", "ie_value" : "Update Traffic Endpoint", "presence" : "C", "tlv_more" : "0", "comment" : "When present this IE shall contain the information associated with the traffic endpoint to be updated, if the UP function has indicated support of PDI optimization.All the PDRs that refer to the Traffic Endpoint shall use the updated Traffic Endpoint information.See Table 7.5.4.13-1."}) ies.append({ "ie_type" : "PFCPSMReq-Flags", "ie_value" : "PFCPSMReq-Flags", "presence" : "C", "tlv_more" : "0", "comment" : "This IE shall be included if at least one of the flags is set to 1.- DROBU (Drop Buffered Packets): the CP function shall set this flag if the UP function is requested to drop the packets currently buffered for this PFCP session (see NOTE 1).- QAURR (Query All URRs): the CP function shall set this flag if the CP function requests immediate usage report(s) for all the URRs previously provisioned for this PFCP session (see NOTE 3). "}) diff --git a/lib/pfcp/support/pfcp-tlv.py b/lib/pfcp/support/pfcp-tlv.py index 362d34d33..4efbc0748 100644 --- a/lib/pfcp/support/pfcp-tlv.py +++ b/lib/pfcp/support/pfcp-tlv.py @@ -149,7 +149,7 @@ def get_cells(cells): if ie_type == 'Create URR' or ie_type == 'Update URR' or ie_type == "Remove URR": tlv_more = "1" if ie_type == 'Create QER' or ie_type == 'Update QER' or ie_type == "Remove QER": - tlv_more = "1" + tlv_more = "3" if ie_type == 'User Plane IP Resource Information': tlv_more = "3" if ie_type == 'SDF Filter': diff --git a/src/amf/gmm-handler.c b/src/amf/gmm-handler.c index 4345da7ea..ecbf6b78a 100644 --- a/src/amf/gmm-handler.c +++ b/src/amf/gmm-handler.c @@ -103,17 +103,8 @@ int gmm_handle_registration_request(amf_ue_t *amf_ue, amf_ue->nas.tsc, amf_ue->nas.ksi, amf_ue->nas.data); /* * REGISTRATION_REQUEST - * Clear EBI generator - * Clear Timer and Message - * - * TAU_REQUEST - * Clear Timer and Message - * * SERVICE_REQUEST * Clear Timer and Message - * - * EXTENDED_SERVICE_REQUEST - * Clear Timer and Message */ CLEAR_AMF_UE_ALL_TIMERS(amf_ue); @@ -337,17 +328,8 @@ int gmm_handle_service_request(amf_ue_t *amf_ue, /* * REGISTRATION_REQUEST - * Clear EBI generator - * Clear Timer and Message - * - * TAU_REQUEST - * Clear Timer and Message - * * SERVICE_REQUEST * Clear Timer and Message - * - * EXTENDED_SERVICE_REQUEST - * Clear Timer and Message */ CLEAR_AMF_UE_ALL_TIMERS(amf_ue); @@ -648,17 +630,8 @@ int gmm_handle_tau_request(amf_ue_t *amf_ue, /* * REGISTRATION_REQUEST - * Clear EBI generator - * Clear Timer and Message - * - * TAU_REQUEST - * Clear Timer and Message - * * SERVICE_REQUEST * Clear Timer and Message - * - * EXTENDED_SERVICE_REQUEST - * Clear Timer and Message */ CLEAR_AMF_UE_ALL_TIMERS(amf_ue); diff --git a/src/mme/emm-handler.c b/src/mme/emm-handler.c index cf2ee7565..9872ed288 100644 --- a/src/mme/emm-handler.c +++ b/src/mme/emm-handler.c @@ -73,21 +73,13 @@ int emm_handle_attach_request(mme_ue_t *mme_ue, mme_ue->nas_eps.type, mme_ue->nas_eps.ksi, mme_ue->nas_eps.data); /* * ATTACH_REQUEST - * Clear EBI generator - * Clear Timer and Message - * * TAU_REQUEST - * Clear Timer and Message - * * SERVICE_REQUEST - * Clear Timer and Message - * * EXTENDED_SERVICE_REQUEST * Clear Timer and Message */ CLEAR_MME_UE_ALL_TIMERS(mme_ue); - CLEAR_EPS_BEARER_ID(mme_ue); CLEAR_SERVICE_INDICATOR(mme_ue); if (SECURITY_CONTEXT_IS_VALID(mme_ue)) { ogs_kdf_kenb(mme_ue->kasme, mme_ue->ul_count.i32, mme_ue->kenb); @@ -403,15 +395,8 @@ int emm_handle_service_request( /* * ATTACH_REQUEST - * Clear EBI generator - * Clear Timer and Message - * * TAU_REQUEST - * Clear Timer and Message - * * SERVICE_REQUEST - * Clear Timer and Message - * * EXTENDED_SERVICE_REQUEST * Clear Timer and Message */ @@ -468,15 +453,8 @@ int emm_handle_tau_request(mme_ue_t *mme_ue, /* * ATTACH_REQUEST - * Clear EBI generator - * Clear Timer and Message - * * TAU_REQUEST - * Clear Timer and Message - * * SERVICE_REQUEST - * Clear Timer and Message - * * EXTENDED_SERVICE_REQUEST * Clear Timer and Message */ @@ -602,15 +580,8 @@ int emm_handle_extended_service_request(mme_ue_t *mme_ue, /* * ATTACH_REQUEST - * Clear EBI generator - * Clear Timer and Message - * * TAU_REQUEST - * Clear Timer and Message - * * SERVICE_REQUEST - * Clear Timer and Message - * * EXTENDED_SERVICE_REQUEST * Clear Timer and Message */ diff --git a/src/mme/mme-context.c b/src/mme/mme-context.c index f2e223a56..be3f86887 100644 --- a/src/mme/mme-context.c +++ b/src/mme/mme-context.c @@ -45,7 +45,6 @@ static OGS_POOL(mme_enb_pool, mme_enb_t); static OGS_POOL(mme_ue_pool, mme_ue_t); static OGS_POOL(enb_ue_pool, enb_ue_t); static OGS_POOL(mme_sess_pool, mme_sess_t); -static OGS_POOL(mme_bearer_pool, mme_bearer_t); static int context_initialized = 0; @@ -130,7 +129,6 @@ void mme_context_init() ogs_pool_init(&mme_ue_pool, ogs_app()->max.ue); ogs_pool_init(&enb_ue_pool, ogs_app()->max.ue); ogs_pool_init(&mme_sess_pool, ogs_app()->pool.sess); - ogs_pool_init(&mme_bearer_pool, ogs_app()->pool.bearer); ogs_pool_init(&self.m_tmsi, ogs_app()->max.ue); self.enb_addr_hash = ogs_hash_make(); @@ -169,7 +167,6 @@ void mme_context_final() ogs_hash_destroy(self.guti_ue_hash); ogs_pool_final(&self.m_tmsi); - ogs_pool_final(&mme_bearer_pool); ogs_pool_final(&mme_sess_pool); ogs_pool_final(&mme_ue_pool); ogs_pool_final(&enb_ue_pool); @@ -2238,6 +2235,8 @@ mme_ue_t *mme_ue_add(enb_ue_t *enb_ue) ogs_assert(mme_ue); memset(mme_ue, 0, sizeof *mme_ue); + ogs_pool_init(&mme_ue->bearer_pool, + MAX_EPS_BEARER_ID - MIN_EPS_BEARER_ID + 1); ogs_list_init(&mme_ue->sess_list); mme_ue->mme_s11_teid = ogs_pool_index(&mme_ue_pool, mme_ue); @@ -2339,6 +2338,8 @@ void mme_ue_remove(mme_ue_t *mme_ue) mme_sess_remove_all(mme_ue); mme_pdn_remove_all(mme_ue); + ogs_pool_final(&mme_ue->bearer_pool); + ogs_pool_free(&mme_ue_pool, mme_ue); } @@ -2782,12 +2783,14 @@ mme_bearer_t *mme_bearer_add(mme_sess_t *sess) mme_ue = sess->mme_ue; ogs_assert(mme_ue); - ogs_pool_alloc(&mme_bearer_pool, &bearer); + ogs_pool_alloc(&mme_ue->bearer_pool, &bearer); ogs_assert(bearer); memset(bearer, 0, sizeof *bearer); - bearer->ebi = OGS_NEXT_ID(mme_ue->ebi, - MIN_EPS_BEARER_ID, MAX_EPS_BEARER_ID); + bearer->index = ogs_pool_index(&mme_ue->bearer_pool, bearer); + bearer->ebi = bearer->index + MIN_EPS_BEARER_ID - 1; + ogs_assert(bearer->ebi >= MIN_EPS_BEARER_ID && + bearer->ebi <= MAX_EPS_BEARER_ID); bearer->mme_ue = mme_ue; bearer->sess = sess; @@ -2811,6 +2814,7 @@ void mme_bearer_remove(mme_bearer_t *bearer) mme_event_t e; ogs_assert(bearer); + ogs_assert(bearer->mme_ue); ogs_assert(bearer->sess); memset(&e, 0, sizeof(e)); @@ -2825,7 +2829,14 @@ void mme_bearer_remove(mme_bearer_t *bearer) OGS_TLV_CLEAR_DATA(&bearer->tft); - ogs_pool_free(&mme_bearer_pool, bearer); + ogs_pool_free(&bearer->mme_ue->bearer_pool, bearer); + + if (ogs_pool_size(&bearer->mme_ue->bearer_pool) == + ogs_pool_avail(&bearer->mme_ue->bearer_pool)) { + ogs_pool_final(&bearer->mme_ue->bearer_pool); + ogs_pool_init(&bearer->mme_ue->bearer_pool, + MAX_EPS_BEARER_ID - MIN_EPS_BEARER_ID + 1); + } } void mme_bearer_remove_all(mme_sess_t *sess) diff --git a/src/mme/mme-context.h b/src/mme/mme-context.h index a5ead5289..c2a323ad0 100644 --- a/src/mme/mme-context.h +++ b/src/mme/mme-context.h @@ -54,6 +54,8 @@ typedef struct mme_csmap_s mme_csmap_t; typedef struct enb_ue_s enb_ue_t; typedef struct mme_ue_s mme_ue_t; +typedef struct mme_sess_s mme_sess_t; +typedef struct mme_bearer_s mme_bearer_t; typedef struct ogs_diam_config_s ogs_diam_config_t; @@ -266,6 +268,89 @@ struct enb_ue_s { mme_ue_t *mme_ue; }; +#define BEARER_CONTEXT_IS_ACTIVE(__mME) \ + (mme_bearer_is_inactive(__mME) == 0) +#define CLEAR_BEARER_CONTEXT(__mME) \ + mme_bearer_set_inactive(__mME) + +#define MME_HAVE_ENB_S1U_PATH(__bEARER) \ + ((__bEARER) && ((__bEARER)->enb_s1u_teid)) +#define CLEAR_ENB_S1U_PATH(__bEARER) \ + do { \ + ogs_assert((__bEARER)); \ + (__bEARER)->enb_s1u_teid = 0; \ + } while(0) + +#define MME_HAVE_ENB_DL_INDIRECT_TUNNEL(__bEARER) \ + ((__bEARER) && ((__bEARER)->enb_dl_teid)) +#define MME_HAVE_ENB_UL_INDIRECT_TUNNEL(__bEARER) \ + ((__bEARER) && ((__bEARER)->enb_ul_teid)) +#define MME_HAVE_SGW_DL_INDIRECT_TUNNEL(__bEARER) \ + ((__bEARER) && ((__bEARER)->sgw_dl_teid)) +#define MME_HAVE_SGW_UL_INDIRECT_TUNNEL(__bEARER) \ + ((__bEARER) && ((__bEARER)->sgw_ul_teid)) +#define CLEAR_INDIRECT_TUNNEL(__bEARER) \ + do { \ + ogs_assert((__bEARER)); \ + (__bEARER)->enb_dl_teid = 0; \ + (__bEARER)->enb_ul_teid = 0; \ + (__bEARER)->sgw_dl_teid = 0; \ + (__bEARER)->sgw_ul_teid = 0; \ + } while(0) +typedef struct mme_bearer_s { + ogs_lnode_t lnode; + uint32_t index; + ogs_fsm_t sm; /* State Machine */ + + uint8_t ebi; /* EPS Bearer ID */ + + uint32_t enb_s1u_teid; + ogs_ip_t enb_s1u_ip; + uint32_t sgw_s1u_teid; + ogs_ip_t sgw_s1u_ip; + + uint32_t target_s1u_teid; /* Target S1U TEID from HO-Req-Ack */ + ogs_ip_t target_s1u_ip; /* Target S1U ADDR from HO-Req-Ack */ + + uint32_t enb_dl_teid; + ogs_ip_t enb_dl_ip; + uint32_t enb_ul_teid; + ogs_ip_t enb_ul_ip; + + uint32_t sgw_dl_teid; + ogs_ip_t sgw_dl_ip; + uint32_t sgw_ul_teid; + ogs_ip_t sgw_ul_ip; + + ogs_qos_t qos; + ogs_tlv_octet_t tft; /* Saved TFT */ + +#define CLEAR_BEARER_ALL_TIMERS(__bEARER) \ + do { \ + CLEAR_BEARER_TIMER((__bEARER)->t3489); \ + } while(0); +#define CLEAR_BEARER_TIMER(__bEARER_TIMER) \ + do { \ + ogs_timer_stop((__bEARER_TIMER).timer); \ + if ((__bEARER_TIMER).pkbuf) \ + { \ + ogs_pkbuf_free((__bEARER_TIMER).pkbuf); \ + (__bEARER_TIMER).pkbuf = NULL; \ + } \ + (__bEARER_TIMER).retry_count = 0; \ + } while(0); + struct { + ogs_pkbuf_t *pkbuf; + ogs_timer_t *timer; + uint32_t retry_count;; + } t3489; + + /* Related Context */ + mme_ue_t *mme_ue; + mme_sess_t *sess; + ogs_gtp_xact_t *xact; +} mme_bearer_t; + struct mme_ue_s { ogs_lnode_t lnode; ogs_fsm_t sm; /* A state machine */ @@ -387,16 +472,11 @@ struct mme_ue_s { ogs_subscription_data_t subscription_data; /* ESM Info */ + ogs_list_t sess_list; + #define MIN_EPS_BEARER_ID 5 #define MAX_EPS_BEARER_ID 15 - -#define CLEAR_EPS_BEARER_ID(__mME) \ - do { \ - ogs_assert((__mME)); \ - (__mME)->ebi = MIN_EPS_BEARER_ID - 1; \ - } while(0) - uint8_t ebi; /* EPS Bearer ID generator */ - ogs_list_t sess_list; + OGS_POOL(bearer_pool, mme_bearer_t); #define ECM_CONNECTED(__mME) \ ((__mME) && ((__mME)->enb_ue != NULL)) @@ -546,88 +626,6 @@ typedef struct mme_sess_s { ogs_tlv_octet_t pgw_pco; } mme_sess_t; -#define BEARER_CONTEXT_IS_ACTIVE(__mME) \ - (mme_bearer_is_inactive(__mME) == 0) -#define CLEAR_BEARER_CONTEXT(__mME) \ - mme_bearer_set_inactive(__mME) - -#define MME_HAVE_ENB_S1U_PATH(__bEARER) \ - ((__bEARER) && ((__bEARER)->enb_s1u_teid)) -#define CLEAR_ENB_S1U_PATH(__bEARER) \ - do { \ - ogs_assert((__bEARER)); \ - (__bEARER)->enb_s1u_teid = 0; \ - } while(0) - -#define MME_HAVE_ENB_DL_INDIRECT_TUNNEL(__bEARER) \ - ((__bEARER) && ((__bEARER)->enb_dl_teid)) -#define MME_HAVE_ENB_UL_INDIRECT_TUNNEL(__bEARER) \ - ((__bEARER) && ((__bEARER)->enb_ul_teid)) -#define MME_HAVE_SGW_DL_INDIRECT_TUNNEL(__bEARER) \ - ((__bEARER) && ((__bEARER)->sgw_dl_teid)) -#define MME_HAVE_SGW_UL_INDIRECT_TUNNEL(__bEARER) \ - ((__bEARER) && ((__bEARER)->sgw_ul_teid)) -#define CLEAR_INDIRECT_TUNNEL(__bEARER) \ - do { \ - ogs_assert((__bEARER)); \ - (__bEARER)->enb_dl_teid = 0; \ - (__bEARER)->enb_ul_teid = 0; \ - (__bEARER)->sgw_dl_teid = 0; \ - (__bEARER)->sgw_ul_teid = 0; \ - } while(0) -typedef struct mme_bearer_s { - ogs_lnode_t lnode; - ogs_fsm_t sm; /* State Machine */ - - uint8_t ebi; /* EPS Bearer ID */ - - uint32_t enb_s1u_teid; - ogs_ip_t enb_s1u_ip; - uint32_t sgw_s1u_teid; - ogs_ip_t sgw_s1u_ip; - - uint32_t target_s1u_teid; /* Target S1U TEID from HO-Req-Ack */ - ogs_ip_t target_s1u_ip; /* Target S1U ADDR from HO-Req-Ack */ - - uint32_t enb_dl_teid; - ogs_ip_t enb_dl_ip; - uint32_t enb_ul_teid; - ogs_ip_t enb_ul_ip; - - uint32_t sgw_dl_teid; - ogs_ip_t sgw_dl_ip; - uint32_t sgw_ul_teid; - ogs_ip_t sgw_ul_ip; - - ogs_qos_t qos; - ogs_tlv_octet_t tft; /* Saved TFT */ - -#define CLEAR_BEARER_ALL_TIMERS(__bEARER) \ - do { \ - CLEAR_BEARER_TIMER((__bEARER)->t3489); \ - } while(0); -#define CLEAR_BEARER_TIMER(__bEARER_TIMER) \ - do { \ - ogs_timer_stop((__bEARER_TIMER).timer); \ - if ((__bEARER_TIMER).pkbuf) \ - { \ - ogs_pkbuf_free((__bEARER_TIMER).pkbuf); \ - (__bEARER_TIMER).pkbuf = NULL; \ - } \ - (__bEARER_TIMER).retry_count = 0; \ - } while(0); - struct { - ogs_pkbuf_t *pkbuf; - ogs_timer_t *timer; - uint32_t retry_count;; - } t3489; - - /* Related Context */ - mme_ue_t *mme_ue; - mme_sess_t *sess; - ogs_gtp_xact_t *xact; -} mme_bearer_t; - void mme_context_init(void); void mme_context_final(void); mme_context_t *mme_self(void); diff --git a/src/mme/mme-fd-path.c b/src/mme/mme-fd-path.c index 66c5b23ac..e5fb4d7c6 100644 --- a/src/mme/mme-fd-path.c +++ b/src/mme/mme-fd-path.c @@ -157,7 +157,8 @@ void mme_s6a_send_air(mme_ue_t *mme_ue, ogs_assert(ret == 0); /* Set Vendor-Specific-Application-Id AVP */ - ret = ogs_diam_message_vendor_specific_appid_set(req, OGS_DIAM_S6A_APPLICATION_ID); + ret = ogs_diam_message_vendor_specific_appid_set( + req, OGS_DIAM_S6A_APPLICATION_ID); ogs_assert(ret == 0); ret = clock_gettime(CLOCK_REALTIME, &sess_data->ts); diff --git a/src/pcrf/pcrf-gx-path.c b/src/pcrf/pcrf-gx-path.c index 40c49d6a9..9b36daad3 100644 --- a/src/pcrf/pcrf-gx-path.c +++ b/src/pcrf/pcrf-gx-path.c @@ -292,8 +292,7 @@ static int pcrf_gx_ccr_cb( struct msg **msg, struct avp *avp, /* Check Session */ if (!sess_data && (cc_request_type == OGS_DIAM_GX_CC_REQUEST_TYPE_UPDATE_REQUEST || - cc_request_type == OGS_DIAM_GX_CC_REQUEST_TYPE_TERMINATION_REQUEST)) - { + cc_request_type == OGS_DIAM_GX_CC_REQUEST_TYPE_TERMINATION_REQUEST)) { ogs_error("No Session for CC-Request-Type: [%d]", cc_request_type); result_code = OGS_DIAM_UNKNOWN_SESSION_ID; goto out; diff --git a/src/pcrf/pcrf-rx-path.c b/src/pcrf/pcrf-rx-path.c index 000082feb..86a8036a4 100644 --- a/src/pcrf/pcrf-rx-path.c +++ b/src/pcrf/pcrf-rx-path.c @@ -666,7 +666,8 @@ static int pcrf_rx_str_cb( struct msg **msg, struct avp *avp, if (sess_data->state != SESSION_ABORTED) { /* Send Re-Auth Request if Abort-Session-Request is not initaited */ - rv = pcrf_gx_send_rar(sess_data->gx_sid, sess_data->rx_sid, &rx_message); + rv = pcrf_gx_send_rar( + sess_data->gx_sid, sess_data->rx_sid, &rx_message); if (rv != OGS_OK) { result_code = rx_message.result_code; ogs_error("pcrf_gx_send_rar() failed"); diff --git a/src/sgwc/context.c b/src/sgwc/context.c index b0df2628f..f0c944c0a 100644 --- a/src/sgwc/context.c +++ b/src/sgwc/context.c @@ -389,6 +389,12 @@ sgwc_sess_t *sgwc_sess_add(sgwc_ue_t *sgwc_ue, char *apn) } memset(sess, 0, sizeof *sess); + ogs_pool_init(&sess->pfcp.pdr_pool, OGS_MAX_NUM_OF_PDR); + ogs_pool_init(&sess->pfcp.far_pool, OGS_MAX_NUM_OF_FAR); + ogs_pool_init(&sess->pfcp.urr_pool, OGS_MAX_NUM_OF_URR); + ogs_pool_init(&sess->pfcp.qer_pool, OGS_MAX_NUM_OF_QER); + ogs_pool_init(&sess->pfcp.bar_pool, OGS_MAX_NUM_OF_BAR); + sess->index = ogs_pool_index(&sgwc_sess_pool, sess); ogs_assert(sess->index > 0 && sess->index <= ogs_app()->pool.sess); @@ -396,10 +402,6 @@ sgwc_sess_t *sgwc_sess_add(sgwc_ue_t *sgwc_ue, char *apn) sess->sgw_s5c_teid = sess->index; sess->sgwc_sxa_seid = sess->index; - /* Indirect tunnel ID generator */ - sess->indirect_pdr_id = OGS_MAX_NUM_OF_PDR; - sess->indirect_far_id = OGS_MAX_NUM_OF_FAR; - /* Set APN */ ogs_cpystrn(sess->pdn.apn, apn, OGS_MAX_APN_LEN+1); @@ -488,6 +490,12 @@ int sgwc_sess_remove(sgwc_sess_t *sess) sgwc_bearer_remove_all(sess); + ogs_pool_final(&sess->pfcp.pdr_pool); + ogs_pool_final(&sess->pfcp.far_pool); + ogs_pool_final(&sess->pfcp.urr_pool); + ogs_pool_final(&sess->pfcp.qer_pool); + ogs_pool_final(&sess->pfcp.bar_pool); + ogs_pool_free(&sgwc_sess_pool, sess); return OGS_OK; @@ -586,8 +594,6 @@ int sgwc_bearer_remove(sgwc_bearer_t *bearer) sgwc_tunnel_remove_all(bearer); - ogs_pfcp_sess_clear(&bearer->pfcp); - /* Free the buffered packets */ for (i = 0; i < bearer->num_buffered_pkt; i++) ogs_pkbuf_free(bearer->buffered_pkts[i]); @@ -690,9 +696,9 @@ sgwc_tunnel_t *sgwc_tunnel_add( tunnel->index = ogs_pool_index(&sgwc_tunnel_pool, tunnel); ogs_assert(tunnel->index > 0 && tunnel->index <= ogs_app()->pool.tunnel); - pdr = ogs_pfcp_pdr_add(&bearer->pfcp); + pdr = ogs_pfcp_pdr_add(&sess->pfcp); ogs_assert(pdr); - pdr->id = OGS_NEXT_ID(sess->pdr_id, 1, OGS_MAX_NUM_OF_PDR+1); + pdr->id = pdr->index; pdr->src_if = src_if; if (strlen(sess->pdn.apn)) @@ -711,26 +717,12 @@ sgwc_tunnel_t *sgwc_tunnel_add( } else ogs_assert_if_reached(); - far = ogs_pfcp_far_add(&bearer->pfcp); + far = ogs_pfcp_far_add(&sess->pfcp); ogs_assert(far); - far->id = OGS_NEXT_ID(sess->far_id, 1, OGS_MAX_NUM_OF_FAR+1); + far->id = far->index; far->dst_if = dst_if; ogs_pfcp_pdr_associate_far(pdr, far); - if (interface_type == OGS_GTP_F_TEID_SGW_GTP_U_FOR_DL_DATA_FORWARDING || - interface_type == OGS_GTP_F_TEID_SGW_GTP_U_FOR_UL_DATA_FORWARDING) { - - /* - * If it is an indirect tunnel, - * it will use a different ID space - * to avoid collisions with normal tunnels. - */ - pdr->id = OGS_NEXT_ID(sess->indirect_pdr_id, - OGS_MAX_NUM_OF_PDR, OGS_MAX_NUM_OF_PDR*2); - far->id = OGS_NEXT_ID(sess->indirect_far_id, - OGS_MAX_NUM_OF_FAR, OGS_MAX_NUM_OF_FAR*2); - } - ogs_assert(sess->pfcp_node); resource = ogs_pfcp_gtpu_resource_find( &sess->pfcp_node->gtpu_resource_list, @@ -778,6 +770,9 @@ int sgwc_tunnel_remove(sgwc_tunnel_t *tunnel) ogs_list_remove(&tunnel->bearer->tunnel_list, tunnel); + ogs_pfcp_pdr_remove(tunnel->pdr); + ogs_pfcp_far_remove(tunnel->far); + if (tunnel->local_addr) ogs_freeaddrinfo(tunnel->local_addr); if (tunnel->local_addr6) diff --git a/src/sgwc/context.h b/src/sgwc/context.h index b5b098c65..290636924 100644 --- a/src/sgwc/context.h +++ b/src/sgwc/context.h @@ -78,10 +78,13 @@ typedef struct sgwc_ue_s { ogs_gtp_node_t *gnode; } sgwc_ue_t; +#define SGWC_SESS(pfcp_sess) ogs_container_of(pfcp_sess, sgwc_sess_t, pfcp) typedef struct sgwc_sess_s { ogs_lnode_t lnode; /* A node of list_t */ uint32_t index; /**< An index of this node */ + ogs_pfcp_sess_t pfcp; /* PFCP session context */ + uint32_t sgw_s5c_teid; /* SGW-S5C-TEID is derived from INDEX */ uint32_t pgw_s5c_teid; /* PGW-S5C-TEID is received from PGW */ @@ -101,17 +104,6 @@ typedef struct sgwc_sess_s { bool delete_indirect_tunnel; } state; - ogs_pfcp_pdr_id_t pdr_id; /* ID Generator(1~OGS_MAX_NUM_OF_PDR) */ - ogs_pfcp_far_id_t far_id; /* ID Generator(1~OGS_MAX_NUM_OF_FAR) */ - ogs_pfcp_urr_id_t urr_id; /* ID Generator(1~OGS_MAX_NUM_OF_URR) */ - ogs_pfcp_qer_id_t qer_id; /* ID Generator(1~OGS_MAX_NUM_OF_URR) */ - ogs_pfcp_bar_id_t bar_id; /* ID Generator(1~OGS_MAX_NUM_OF_BAR) */ - - /* ID Generator(OGS_MAX_NUM_OF_PDR~OGS_MAX_NUM_OF_PDR*2) */ - ogs_pfcp_pdr_id_t indirect_pdr_id; - /* ID Generator(OGS_MAX_NUM_OF_FAR~OGS_MAX_NUM_OF_FAR*2) */ - ogs_pfcp_far_id_t indirect_far_id; - /* APN Configuration */ ogs_pdn_t pdn; @@ -124,12 +116,9 @@ typedef struct sgwc_sess_s { sgwc_ue_t *sgwc_ue; } sgwc_sess_t; -#define SGWC_BEARER(pfcp_sess) ogs_container_of(pfcp_sess, sgwc_bearer_t, pfcp) typedef struct sgwc_bearer_s { ogs_lnode_t lnode; - ogs_pfcp_sess_t pfcp; /* PFCP session context */ - uint8_t ebi; /* Pkts which will be buffered in case of UE-IDLE */ diff --git a/src/sgwc/sxa-build.c b/src/sgwc/sxa-build.c index 249d426f8..686022027 100644 --- a/src/sgwc/sxa-build.c +++ b/src/sgwc/sxa-build.c @@ -26,8 +26,6 @@ ogs_pkbuf_t *sgwc_sxa_build_session_establishment_request( ogs_pfcp_session_establishment_request_t *req = NULL; ogs_pkbuf_t *pkbuf = NULL; - sgwc_bearer_t *bearer = NULL; - ogs_pfcp_pdr_t *pdr = NULL; ogs_pfcp_far_t *far = NULL; ogs_pfcp_urr_t *urr = NULL; @@ -66,38 +64,30 @@ ogs_pkbuf_t *sgwc_sxa_build_session_establishment_request( /* Create PDR */ i = 0; - ogs_list_for_each(&sess->bearer_list, bearer) { - ogs_list_for_each(&bearer->pfcp.pdr_list, pdr) { - ogs_pfcp_build_create_pdr(&req->create_pdr[i], i, pdr); - i++; - } + ogs_list_for_each(&sess->pfcp.pdr_list, pdr) { + ogs_pfcp_build_create_pdr(&req->create_pdr[i], i, pdr); + i++; } /* Create FAR */ i = 0; - ogs_list_for_each(&sess->bearer_list, bearer) { - ogs_list_for_each(&bearer->pfcp.far_list, far) { - ogs_pfcp_build_create_far(&req->create_far[i], i, far); - i++; - } + ogs_list_for_each(&sess->pfcp.far_list, far) { + ogs_pfcp_build_create_far(&req->create_far[i], i, far); + i++; } /* Create URR */ i = 0; - ogs_list_for_each(&sess->bearer_list, bearer) { - ogs_list_for_each(&bearer->pfcp.urr_list, urr) { - ogs_pfcp_build_create_urr(&req->create_urr[i], i, urr); - i++; - } + ogs_list_for_each(&sess->pfcp.urr_list, urr) { + ogs_pfcp_build_create_urr(&req->create_urr[i], i, urr); + i++; } /* Create QER */ i = 0; - ogs_list_for_each(&sess->bearer_list, bearer) { - ogs_list_for_each(&bearer->pfcp.qer_list, qer) { - ogs_pfcp_build_create_qer(&req->create_qer[i], i, qer); - i++; - } + ogs_list_for_each(&sess->pfcp.qer_list, qer) { + ogs_pfcp_build_create_qer(&req->create_qer[i], i, qer); + i++; } /* PDN Type */ diff --git a/src/sgwc/sxa-handler.c b/src/sgwc/sxa-handler.c index 9a819ad78..7801dbdf2 100644 --- a/src/sgwc/sxa-handler.c +++ b/src/sgwc/sxa-handler.c @@ -858,6 +858,7 @@ void sgwc_sxa_handle_session_report_request( ogs_pfcp_session_report_request_t *pfcp_req) { sgwc_bearer_t *bearer = NULL; + sgwc_tunnel_t *tunnel = NULL; ogs_pfcp_report_type_t report_type; uint8_t cause_value = 0; @@ -895,18 +896,20 @@ void sgwc_sxa_handle_session_report_request( pdr_id = pfcp_req->downlink_data_report.pdr_id.u16; ogs_list_for_each(&sess->bearer_list, bearer) { - if (ogs_pfcp_pdr_find(&bearer->pfcp, pdr_id)) break; + ogs_list_for_each(&bearer->tunnel_list, tunnel) { + ogs_assert(tunnel->pdr); + if (tunnel->pdr->id == pdr_id) { + sgwc_gtp_send_downlink_data_notification(bearer, pfcp_xact); + return; + } + } } } } - if (!bearer) { - ogs_error("No Bearer"); - ogs_pfcp_send_error_message(pfcp_xact, 0, - OGS_PFCP_SESSION_REPORT_RESPONSE_TYPE, - OGS_PFCP_CAUSE_SESSION_CONTEXT_NOT_FOUND, 0); - return; - } + ogs_error("No Bearer"); + ogs_pfcp_send_error_message(pfcp_xact, 0, + OGS_PFCP_SESSION_REPORT_RESPONSE_TYPE, + OGS_PFCP_CAUSE_SESSION_CONTEXT_NOT_FOUND, 0); - sgwc_gtp_send_downlink_data_notification(bearer, pfcp_xact); } diff --git a/src/sgwu/context.c b/src/sgwu/context.c index afbdadc28..c0c89988f 100644 --- a/src/sgwu/context.c +++ b/src/sgwu/context.c @@ -374,6 +374,12 @@ sgwu_sess_t *sgwu_sess_add(ogs_pfcp_f_seid_t *cp_f_seid, ogs_assert(sess); memset(sess, 0, sizeof *sess); + ogs_pool_init(&sess->pfcp.pdr_pool, OGS_MAX_NUM_OF_PDR); + ogs_pool_init(&sess->pfcp.far_pool, OGS_MAX_NUM_OF_FAR); + ogs_pool_init(&sess->pfcp.urr_pool, OGS_MAX_NUM_OF_URR); + ogs_pool_init(&sess->pfcp.qer_pool, OGS_MAX_NUM_OF_QER); + ogs_pool_init(&sess->pfcp.bar_pool, OGS_MAX_NUM_OF_BAR); + sess->index = ogs_pool_index(&sgwu_sess_pool, sess); ogs_assert(sess->index > 0 && sess->index <= ogs_app()->pool.sess); @@ -406,6 +412,12 @@ int sgwu_sess_remove(sgwu_sess_t *sess) ogs_hash_set(self.sess_hash, &sess->sgwc_sxa_seid, sizeof(sess->sgwc_sxa_seid), NULL); + ogs_pool_final(&sess->pfcp.pdr_pool); + ogs_pool_final(&sess->pfcp.far_pool); + ogs_pool_final(&sess->pfcp.urr_pool); + ogs_pool_final(&sess->pfcp.qer_pool); + ogs_pool_final(&sess->pfcp.bar_pool); + ogs_pool_free(&sgwu_sess_pool, sess); ogs_info("Removed a session. Number of active sessions is now %d", diff --git a/src/smf/bearer-binding.c b/src/smf/bearer-binding.c index 8bcc59e30..20f0c8d8e 100644 --- a/src/smf/bearer-binding.c +++ b/src/smf/bearer-binding.c @@ -170,7 +170,7 @@ void smf_bearer_binding(smf_sess_t *sess) } if (pcc_rule->type == OGS_PCC_RULE_TYPE_INSTALL) { - ogs_pfcp_pdr_t *pdr = NULL; + ogs_pfcp_pdr_t *dl_pdr = NULL, *ul_pdr = NULL; bearer = smf_bearer_find_by_qci_arp(sess, pcc_rule->qos.qci, @@ -189,8 +189,10 @@ void smf_bearer_binding(smf_sess_t *sess) ogs_assert(bearer); /* Precedence is set to the order in which it was created */ - ogs_list_for_each(&bearer->pfcp.pdr_list, pdr) - pdr->precedence = pdr->id; + ogs_assert(bearer->dl_pdr); + ogs_assert(bearer->ul_pdr); + bearer->dl_pdr->precedence = bearer->dl_pdr->id; + bearer->ul_pdr->precedence = bearer->ul_pdr->id; bearer->name = ogs_strdup(pcc_rule->name); ogs_assert(bearer->name); @@ -231,8 +233,13 @@ void smf_bearer_binding(smf_sess_t *sess) } } - ogs_list_for_each(&bearer->pfcp.pdr_list, pdr) - pdr->num_of_flow = 0; + 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; for (j = 0; j < pcc_rule->num_of_flow; j++) { ogs_flow_t *flow = &pcc_rule->flow[j]; @@ -241,25 +248,15 @@ void smf_bearer_binding(smf_sess_t *sess) ogs_expect_or_return(flow); ogs_expect_or_return(flow->description); - ogs_list_for_each(&bearer->pfcp.pdr_list, pdr) { - if (flow->direction == OGS_FLOW_DOWNLINK_ONLY) { - if (pdr->src_if == OGS_PFCP_INTERFACE_CORE) { - pdr->flow_description[pdr->num_of_flow++] = - flow->description; - break; - } - - } else if (flow->direction == OGS_FLOW_UPLINK_ONLY) { - if (pdr->src_if == OGS_PFCP_INTERFACE_ACCESS) { - pdr->flow_description[pdr->num_of_flow++] = - flow->description; - break; - } - } else { - ogs_error("Flow Bidirectional is not supported[%d]", - flow->direction); - break; - } + 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); } pf = smf_pf_add(bearer, pcc_rule->precedence); @@ -323,13 +320,12 @@ void smf_bearer_binding(smf_sess_t *sess) } else if (pcc_rule->type == OGS_PCC_RULE_TYPE_REMOVE) { bearer = smf_bearer_find_by_name(sess, pcc_rule->name); - ogs_assert(bearer); if (!bearer) { ogs_warn("No need to send 'Delete Bearer Request'"); ogs_warn(" - Bearer[Name:%s] has already been removed.", pcc_rule->name); - return; + continue; } memset(&h, 0, sizeof(ogs_gtp_header_t)); diff --git a/src/smf/context.c b/src/smf/context.c index 58a9b90ef..847005b55 100644 --- a/src/smf/context.c +++ b/src/smf/context.c @@ -29,8 +29,6 @@ static OGS_POOL(smf_ue_pool, smf_ue_t); static OGS_POOL(smf_sess_pool, smf_sess_t); static OGS_POOL(smf_bearer_pool, smf_bearer_t); -static OGS_POOL(smf_pf_pool, smf_pf_t); - static int context_initialized = 0; void smf_context_init(void) @@ -64,8 +62,6 @@ void smf_context_init(void) ogs_pool_init(&smf_sess_pool, ogs_app()->pool.sess); ogs_pool_init(&smf_bearer_pool, ogs_app()->pool.bearer); - ogs_pool_init(&smf_pf_pool, ogs_app()->pool.pf); - self.supi_hash = ogs_hash_make(); self.imsi_hash = ogs_hash_make(); self.ipv4_hash = ogs_hash_make(); @@ -93,8 +89,6 @@ void smf_context_final(void) ogs_pool_final(&smf_bearer_pool); ogs_pool_final(&smf_sess_pool); - ogs_pool_final(&smf_pf_pool); - ogs_gtp_node_remove_all(&self.sgw_s5c_list); ogs_gtp_node_final(); @@ -674,6 +668,12 @@ smf_sess_t *smf_sess_add_by_apn(smf_ue_t *smf_ue, char *apn) } memset(sess, 0, sizeof *sess); + ogs_pool_init(&sess->pfcp.pdr_pool, OGS_MAX_NUM_OF_PDR); + ogs_pool_init(&sess->pfcp.far_pool, OGS_MAX_NUM_OF_FAR); + ogs_pool_init(&sess->pfcp.urr_pool, OGS_MAX_NUM_OF_URR); + ogs_pool_init(&sess->pfcp.qer_pool, OGS_MAX_NUM_OF_QER); + ogs_pool_init(&sess->pfcp.bar_pool, OGS_MAX_NUM_OF_BAR); + sess->index = ogs_pool_index(&smf_sess_pool, sess); ogs_assert(sess->index > 0 && sess->index <= ogs_app()->pool.sess); @@ -775,6 +775,12 @@ smf_sess_t *smf_sess_add_by_psi(smf_ue_t *smf_ue, uint8_t psi) } memset(sess, 0, sizeof *sess); + ogs_pool_init(&sess->pfcp.pdr_pool, OGS_MAX_NUM_OF_PDR); + ogs_pool_init(&sess->pfcp.far_pool, OGS_MAX_NUM_OF_FAR); + ogs_pool_init(&sess->pfcp.urr_pool, OGS_MAX_NUM_OF_URR); + ogs_pool_init(&sess->pfcp.qer_pool, OGS_MAX_NUM_OF_QER); + ogs_pool_init(&sess->pfcp.bar_pool, OGS_MAX_NUM_OF_BAR); + sess->index = ogs_pool_index(&smf_sess_pool, sess); ogs_assert(sess->index > 0 && sess->index <= ogs_app()->pool.sess); @@ -974,6 +980,12 @@ void smf_sess_remove(smf_sess_t *sess) smf_bearer_remove_all(sess); + ogs_pool_final(&sess->pfcp.pdr_pool); + ogs_pool_final(&sess->pfcp.far_pool); + ogs_pool_final(&sess->pfcp.urr_pool); + ogs_pool_final(&sess->pfcp.qer_pool); + ogs_pool_final(&sess->pfcp.bar_pool); + ogs_pool_free(&smf_sess_pool, sess); } @@ -1084,17 +1096,21 @@ smf_bearer_t *smf_qos_flow_add(smf_sess_t *sess) ogs_list_init(&qos_flow->pf_list); - dl_pdr = ogs_pfcp_pdr_add(&qos_flow->pfcp); + dl_pdr = ogs_pfcp_pdr_add(&sess->pfcp); ogs_assert(dl_pdr); - dl_pdr->id = OGS_NEXT_ID(sess->pdr_id, 1, OGS_MAX_NUM_OF_PDR+1); + dl_pdr->id = dl_pdr->index; + qos_flow->dl_pdr = dl_pdr; + dl_pdr->src_if = OGS_PFCP_INTERFACE_CORE; if (strlen(sess->pdn.apn)) dl_pdr->apn = ogs_strdup(sess->pdn.apn); - ul_pdr = ogs_pfcp_pdr_add(&qos_flow->pfcp); + ul_pdr = ogs_pfcp_pdr_add(&sess->pfcp); ogs_assert(ul_pdr); - ul_pdr->id = OGS_NEXT_ID(sess->pdr_id, 1, OGS_MAX_NUM_OF_PDR+1); + ul_pdr->id = ul_pdr->index; + qos_flow->ul_pdr = ul_pdr; + ul_pdr->src_if = OGS_PFCP_INTERFACE_ACCESS; if (strlen(sess->pdn.apn)) @@ -1113,21 +1129,27 @@ smf_bearer_t *smf_qos_flow_add(smf_sess_t *sess) } else ogs_assert_if_reached(); - dl_far = ogs_pfcp_far_add(&qos_flow->pfcp); + dl_far = ogs_pfcp_far_add(&sess->pfcp); ogs_assert(dl_far); - dl_far->id = OGS_NEXT_ID(sess->far_id, 1, OGS_MAX_NUM_OF_FAR+1); + dl_far->id = dl_far->index; + qos_flow->dl_far = dl_far; + dl_far->dst_if = OGS_PFCP_INTERFACE_ACCESS; ogs_pfcp_pdr_associate_far(dl_pdr, dl_far); - ul_far = ogs_pfcp_far_add(&qos_flow->pfcp); + ul_far = ogs_pfcp_far_add(&sess->pfcp); ogs_assert(ul_far); - ul_far->id = OGS_NEXT_ID(sess->far_id, 1, OGS_MAX_NUM_OF_FAR+1); + ul_far->id = ul_far->index; + qos_flow->ul_far = ul_far; + ul_far->dst_if = OGS_PFCP_INTERFACE_CORE; ogs_pfcp_pdr_associate_far(ul_pdr, ul_far); - qer = ogs_pfcp_qer_add(&qos_flow->pfcp); + qer = ogs_pfcp_qer_add(&sess->pfcp); ogs_assert(qer); - qer->id = OGS_NEXT_ID(sess->qer_id, 1, OGS_MAX_NUM_OF_QER+1); + qer->id = qer->index; + qos_flow->qer = qer; + ogs_pfcp_pdr_associate_qer(dl_pdr, qer); ogs_pfcp_pdr_associate_qer(ul_pdr, qer); @@ -1172,23 +1194,29 @@ smf_bearer_t *smf_bearer_add(smf_sess_t *sess) ogs_assert(bearer); memset(bearer, 0, sizeof *bearer); + ogs_pool_init(&bearer->pf_pool, OGS_MAX_NUM_OF_PF); + bearer->index = ogs_pool_index(&smf_bearer_pool, bearer); ogs_assert(bearer->index > 0 && bearer->index <= ogs_app()->pool.bearer); ogs_list_init(&bearer->pf_list); - dl_pdr = ogs_pfcp_pdr_add(&bearer->pfcp); + dl_pdr = ogs_pfcp_pdr_add(&sess->pfcp); ogs_assert(dl_pdr); - dl_pdr->id = OGS_NEXT_ID(sess->pdr_id, 1, OGS_MAX_NUM_OF_PDR+1); + dl_pdr->id = dl_pdr->index; + bearer->dl_pdr = dl_pdr; + dl_pdr->src_if = OGS_PFCP_INTERFACE_CORE; if (strlen(sess->pdn.apn)) dl_pdr->apn = ogs_strdup(sess->pdn.apn); - ul_pdr = ogs_pfcp_pdr_add(&bearer->pfcp); + ul_pdr = ogs_pfcp_pdr_add(&sess->pfcp); ogs_assert(ul_pdr); - ul_pdr->id = OGS_NEXT_ID(sess->pdr_id, 1, OGS_MAX_NUM_OF_PDR+1); + ul_pdr->id = ul_pdr->index; + bearer->ul_pdr = ul_pdr; + ul_pdr->src_if = OGS_PFCP_INTERFACE_ACCESS; if (strlen(sess->pdn.apn)) @@ -1207,15 +1235,19 @@ smf_bearer_t *smf_bearer_add(smf_sess_t *sess) } else ogs_assert_if_reached(); - dl_far = ogs_pfcp_far_add(&bearer->pfcp); + dl_far = ogs_pfcp_far_add(&sess->pfcp); ogs_assert(dl_far); - dl_far->id = OGS_NEXT_ID(sess->far_id, 1, OGS_MAX_NUM_OF_FAR+1); + dl_far->id = dl_far->index; + bearer->dl_far = dl_far; + dl_far->dst_if = OGS_PFCP_INTERFACE_ACCESS; ogs_pfcp_pdr_associate_far(dl_pdr, dl_far); - ul_far = ogs_pfcp_far_add(&bearer->pfcp); + ul_far = ogs_pfcp_far_add(&sess->pfcp); ogs_assert(ul_far); - ul_far->id = OGS_NEXT_ID(sess->far_id, 1, OGS_MAX_NUM_OF_FAR+1); + ul_far->id = ul_far->index; + bearer->ul_far = ul_far; + ul_far->dst_if = OGS_PFCP_INTERFACE_CORE; ogs_pfcp_pdr_associate_far(ul_pdr, ul_far); @@ -1225,29 +1257,29 @@ smf_bearer_t *smf_bearer_add(smf_sess_t *sess) sess->pdn.apn, OGS_PFCP_INTERFACE_ACCESS); if (resource) { ogs_pfcp_user_plane_ip_resource_info_to_sockaddr(&resource->info, - &bearer->upf_s5u_addr, &bearer->upf_s5u_addr6); - ogs_assert(bearer->upf_s5u_addr || bearer->upf_s5u_addr6); + &bearer->pgw_s5u_addr, &bearer->pgw_s5u_addr6); + ogs_assert(bearer->pgw_s5u_addr || bearer->pgw_s5u_addr6); if (resource->info.teidri) - bearer->upf_s5u_teid = OGS_PFCP_GTPU_INDEX_TO_TEID( + bearer->pgw_s5u_teid = OGS_PFCP_GTPU_INDEX_TO_TEID( bearer->index, resource->info.teidri, resource->info.teid_range); else - bearer->upf_s5u_teid = bearer->index; + bearer->pgw_s5u_teid = bearer->index; } else { if (sess->pfcp_node->addr.ogs_sa_family == AF_INET) - ogs_copyaddrinfo(&bearer->upf_s5u_addr, &sess->pfcp_node->addr); + ogs_copyaddrinfo(&bearer->pgw_s5u_addr, &sess->pfcp_node->addr); else if (sess->pfcp_node->addr.ogs_sa_family == AF_INET6) - ogs_copyaddrinfo(&bearer->upf_s5u_addr6, &sess->pfcp_node->addr); + ogs_copyaddrinfo(&bearer->pgw_s5u_addr6, &sess->pfcp_node->addr); else ogs_assert_if_reached(); - ogs_assert(bearer->upf_s5u_addr || bearer->upf_s5u_addr6); + ogs_assert(bearer->pgw_s5u_addr || bearer->pgw_s5u_addr6); - bearer->upf_s5u_teid = bearer->index; + bearer->pgw_s5u_teid = bearer->index; } - ogs_pfcp_sockaddr_to_f_teid(bearer->upf_s5u_addr, bearer->upf_s5u_addr6, + ogs_pfcp_sockaddr_to_f_teid(bearer->pgw_s5u_addr, bearer->pgw_s5u_addr6, &ul_pdr->f_teid, &ul_pdr->f_teid_len); - ul_pdr->f_teid.teid = bearer->upf_s5u_teid; + ul_pdr->f_teid.teid = bearer->pgw_s5u_teid; bearer->sess = sess; @@ -1262,17 +1294,25 @@ int smf_bearer_remove(smf_bearer_t *bearer) ogs_assert(bearer->sess); ogs_list_remove(&bearer->sess->bearer_list, bearer); - ogs_pfcp_sess_clear(&bearer->pfcp); + + ogs_pfcp_pdr_remove(bearer->dl_pdr); + ogs_pfcp_pdr_remove(bearer->ul_pdr); + ogs_pfcp_far_remove(bearer->dl_far); + ogs_pfcp_far_remove(bearer->ul_far); + if (bearer->qer) + ogs_pfcp_qer_remove(bearer->qer); if (bearer->name) ogs_free(bearer->name); - if (bearer->upf_s5u_addr) - ogs_freeaddrinfo(bearer->upf_s5u_addr); - if (bearer->upf_s5u_addr6) - ogs_freeaddrinfo(bearer->upf_s5u_addr6); + if (bearer->pgw_s5u_addr) + ogs_freeaddrinfo(bearer->pgw_s5u_addr); + if (bearer->pgw_s5u_addr6) + ogs_freeaddrinfo(bearer->pgw_s5u_addr6); smf_pf_remove_all(bearer); + ogs_pool_final(&bearer->pf_pool); + ogs_pool_free(&smf_bearer_pool, bearer); return OGS_OK; @@ -1293,9 +1333,9 @@ smf_bearer_t *smf_bearer_find(uint32_t index) return ogs_pool_find(&smf_bearer_pool, index); } -smf_bearer_t *smf_bearer_find_by_upf_s5u_teid(uint32_t upf_s5u_teid) +smf_bearer_t *smf_bearer_find_by_pgw_s5u_teid(uint32_t pgw_s5u_teid) { - return smf_bearer_find(upf_s5u_teid); + return smf_bearer_find(pgw_s5u_teid); } smf_bearer_t *smf_bearer_find_by_ebi(smf_sess_t *sess, uint8_t ebi) @@ -1407,11 +1447,14 @@ smf_pf_t *smf_pf_add(smf_bearer_t *bearer, uint32_t precedence) ogs_assert(bearer); - ogs_pool_alloc(&smf_pf_pool, &pf); + ogs_pool_alloc(&bearer->pf_pool, &pf); ogs_assert(pf); memset(pf, 0, sizeof *pf); - pf->identifier = OGS_NEXT_ID(bearer->pf_identifier, 1, 15); + pf->index = ogs_pool_index(&bearer->pf_pool, pf); + ogs_assert(pf->index > 0 && pf->index <= OGS_MAX_NUM_OF_PF); + + pf->identifier = pf->index; pf->bearer = bearer; ogs_list_add(&bearer->pf_list, pf); @@ -1428,7 +1471,7 @@ int smf_pf_remove(smf_pf_t *pf) if (pf->flow_description) ogs_free(pf->flow_description); - ogs_pool_free(&smf_pf_pool, pf); + ogs_pool_free(&pf->bearer->pf_pool, pf); return OGS_OK; } diff --git a/src/smf/context.h b/src/smf/context.h index 134eb2d00..a933114e1 100644 --- a/src/smf/context.h +++ b/src/smf/context.h @@ -131,11 +131,64 @@ typedef struct smf_ue_s { smf_sess_remove(__sESS); \ } while(0) +typedef struct smf_bearer_s smf_bearer_t; +typedef struct smf_sess_s smf_sess_t; + +typedef struct smf_pf_s { + ogs_lnode_t lnode; + uint32_t index; + +ED3(uint8_t spare:2;, + uint8_t direction:2;, + uint8_t identifier:4;) + + ogs_ipfw_rule_t ipfw_rule; + char *flow_description; + + smf_bearer_t *bearer; +} smf_pf_t; + +typedef struct smf_bearer_s { + ogs_lnode_t lnode; /**< A node of list_t */ + uint32_t index; + + ogs_pfcp_pdr_t *dl_pdr; + ogs_pfcp_pdr_t *ul_pdr; + ogs_pfcp_far_t *dl_far; + ogs_pfcp_far_t *ul_far; + ogs_pfcp_qer_t *qer; + + uint8_t qfi; /* 5GC */ + uint8_t ebi; /* EPC */ + + uint32_t pgw_s5u_teid; /* PGW-S5U TEID */ + ogs_sockaddr_t *pgw_s5u_addr; /* PGW-S5U IPv4 */ + ogs_sockaddr_t *pgw_s5u_addr6; /* PGW-S5U IPv6 */ + + uint32_t sgw_s5u_teid; /* SGW-S5U TEID */ + ogs_ip_t sgw_s5u_ip; /* SGW-S5U IPv4/IPv6 */ + + char *name; /* PCC Rule Name */ + ogs_qos_t qos; /* QoS Infomration */ + + OGS_POOL(pf_pool, smf_pf_t); + + /* Packet Filter Identifier Generator(1~15) */ + uint8_t pf_identifier; + /* Packet Filter List */ + ogs_list_t pf_list; + + smf_sess_t *sess; +} smf_bearer_t; + +#define SMF_SESS(pfcp_sess) ogs_container_of(pfcp_sess, smf_sess_t, pfcp) typedef struct smf_sess_s { ogs_sbi_object_t sbi; uint32_t index; /**< An index of this node */ ogs_fsm_t sm; /* A state machine */ + ogs_pfcp_sess_t pfcp; /* PFCP session context */ + uint32_t smf_n4_teid; /* SMF-N4-TEID is derived from INDEX */ uint32_t sgw_s5c_teid; /* SGW-S5C-TEID is received from SGW */ @@ -151,12 +204,6 @@ typedef struct smf_sess_s { char *gx_sid; /* Gx Session ID */ - ogs_pfcp_pdr_id_t pdr_id; /* ID Generator(1~OGS_MAX_NUM_OF_PDR) */ - ogs_pfcp_far_id_t far_id; /* ID Generator(1~OGS_MAX_NUM_OF_FAR) */ - ogs_pfcp_urr_id_t urr_id; /* ID Generator(1~OGS_MAX_NUM_OF_URR) */ - ogs_pfcp_qer_id_t qer_id; /* ID Generator(1~OGS_MAX_NUM_OF_URR) */ - ogs_pfcp_bar_id_t bar_id; /* ID Generator(1~OGS_MAX_NUM_OF_BAR) */ - uint8_t qos_flow_identifier; /* ID Generator(1~OGS_MAX_QOS_FLOW_ID) */ char *sm_context_ref; /* smContextRef */ @@ -227,47 +274,6 @@ typedef struct smf_sess_s { smf_ue_t *smf_ue; } smf_sess_t; -#define SMF_BEARER(pfcp_sess) ogs_container_of(pfcp_sess, smf_bearer_t, pfcp) -typedef struct smf_bearer_s { - ogs_lnode_t lnode; /**< A node of list_t */ - uint32_t index; - - ogs_pfcp_sess_t pfcp; /* PFCP session context */ - - uint8_t qfi; /* 5GC */ - uint8_t ebi; /* EPC */ - - uint32_t upf_s5u_teid; /* UPF-S5U TEID */ - ogs_sockaddr_t *upf_s5u_addr; /* UPF-S5U IPv4 */ - ogs_sockaddr_t *upf_s5u_addr6; /* UPF-S5U IPv6 */ - - uint32_t sgw_s5u_teid; /* SGW-S5U TEID */ - ogs_ip_t sgw_s5u_ip; /* SGW-S5U IPv4/IPv6 */ - - char *name; /* PCC Rule Name */ - ogs_qos_t qos; /* QoS Infomration */ - - /* Packet Filter Identifier Generator(1~15) */ - uint8_t pf_identifier; - /* Packet Filter List */ - ogs_list_t pf_list; - - smf_sess_t *sess; -} smf_bearer_t; - -typedef struct smf_pf_s { - ogs_lnode_t lnode; - -ED3(uint8_t spare:2;, - uint8_t direction:2;, - uint8_t identifier:4;) - - ogs_ipfw_rule_t ipfw_rule; - char *flow_description; - - smf_bearer_t *bearer; -} smf_pf_t; - void smf_context_init(void); void smf_context_final(void); smf_context_t *smf_self(void); @@ -312,7 +318,7 @@ smf_bearer_t *smf_bearer_add(smf_sess_t *sess); int smf_bearer_remove(smf_bearer_t *bearer); void smf_bearer_remove_all(smf_sess_t *sess); smf_bearer_t *smf_bearer_find(uint32_t index); -smf_bearer_t *smf_bearer_find_by_upf_s5u_teid(uint32_t upf_s5u_teid); +smf_bearer_t *smf_bearer_find_by_pgw_s5u_teid(uint32_t pgw_s5u_teid); smf_bearer_t *smf_bearer_find_by_ebi(smf_sess_t *sess, uint8_t ebi); smf_bearer_t *smf_bearer_find_by_name(smf_sess_t *sess, char *name); smf_bearer_t *smf_bearer_find_by_qci_arp(smf_sess_t *sess, diff --git a/src/smf/gx-handler.c b/src/smf/gx-handler.c index 4cfea2f2a..6033a1bf6 100644 --- a/src/smf/gx-handler.c +++ b/src/smf/gx-handler.c @@ -48,8 +48,9 @@ void smf_gx_handle_cca_initial_request( int i; smf_bearer_t *bearer = NULL; - ogs_pfcp_pdr_t *pdr = NULL; - ogs_pfcp_far_t *far = NULL; + ogs_pfcp_pdr_t *dl_pdr = NULL; + ogs_pfcp_pdr_t *ul_pdr = NULL; + ogs_pfcp_far_t *dl_far = NULL; ogs_pfcp_qer_t *qer = NULL; ogs_assert(sess); @@ -119,11 +120,12 @@ void smf_gx_handle_cca_initial_request( /* Setup QER */ if (sess->pdn.ambr.downlink || sess->pdn.ambr.uplink) { /* Only 1 QER is used per bearer */ - qer = ogs_list_first(&bearer->pfcp.qer_list); + qer = bearer->qer; if (!qer) { - qer = ogs_pfcp_qer_add(&bearer->pfcp); + qer = ogs_pfcp_qer_add(&sess->pfcp); ogs_assert(qer); - qer->id = OGS_NEXT_ID(sess->qer_id, 1, OGS_MAX_NUM_OF_QER+1); + qer->id = qer->index; + bearer->qer = qer; } qer->mbr.uplink = sess->pdn.ambr.uplink; @@ -131,31 +133,32 @@ void smf_gx_handle_cca_initial_request( } /* Setup FAR */ - ogs_list_for_each(&bearer->pfcp.far_list, far) { + dl_far = bearer->dl_far; + ogs_assert(dl_far); - /* Set Outer Header Creation to the Default DL FAR */ - if (far->dst_if == OGS_PFCP_INTERFACE_ACCESS) { - ogs_pfcp_ip_to_outer_header_creation(&bearer->sgw_s5u_ip, - &far->outer_header_creation, &far->outer_header_creation_len); - far->outer_header_creation.teid = bearer->sgw_s5u_teid; - } - } + /* Set Outer Header Creation to the Default DL FAR */ + ogs_pfcp_ip_to_outer_header_creation(&bearer->sgw_s5u_ip, + &dl_far->outer_header_creation, &dl_far->outer_header_creation_len); + dl_far->outer_header_creation.teid = bearer->sgw_s5u_teid; /* Setup PDR */ - ogs_list_for_each(&bearer->pfcp.pdr_list, pdr) { + dl_pdr = bearer->dl_pdr; + ogs_assert(dl_pdr); + ul_pdr = bearer->ul_pdr; + ogs_assert(ul_pdr); - /* Set UE IP Address to the Default DL PDR */ - if (pdr->src_if == OGS_PFCP_INTERFACE_CORE) { - ogs_pfcp_paa_to_ue_ip_addr(&sess->pdn.paa, - &pdr->ue_ip_addr, &pdr->ue_ip_addr_len); - pdr->ue_ip_addr.sd = OGS_PFCP_UE_IP_DST; - } + /* Set UE IP Address to the Default DL PDR */ + ogs_pfcp_paa_to_ue_ip_addr(&sess->pdn.paa, + &dl_pdr->ue_ip_addr, &dl_pdr->ue_ip_addr_len); + dl_pdr->ue_ip_addr.sd = OGS_PFCP_UE_IP_DST; - /* Default PDRs is set to lowest precedence(highest precedence value) */ - pdr->precedence = 0xffffffff; + /* Default PDRs is set to lowest precedence(highest precedence value) */ + dl_pdr->precedence = 0xffffffff; + ul_pdr->precedence = 0xffffffff; - if (qer) - ogs_pfcp_pdr_associate_qer(pdr, qer); + if (qer) { + ogs_pfcp_pdr_associate_qer(dl_pdr, qer); + ogs_pfcp_pdr_associate_qer(ul_pdr, qer); } smf_epc_pfcp_send_session_establishment_request(sess, gtp_xact); diff --git a/src/smf/n4-build.c b/src/smf/n4-build.c index da8a3c29a..fa0139dae 100644 --- a/src/smf/n4-build.c +++ b/src/smf/n4-build.c @@ -27,8 +27,6 @@ ogs_pkbuf_t *smf_n4_build_session_establishment_request( ogs_pfcp_session_establishment_request_t *req = NULL; ogs_pkbuf_t *pkbuf = NULL; - smf_bearer_t *bearer = NULL; - ogs_pfcp_pdr_t *pdr = NULL; ogs_pfcp_far_t *far = NULL; ogs_pfcp_urr_t *urr = NULL; @@ -67,38 +65,30 @@ ogs_pkbuf_t *smf_n4_build_session_establishment_request( /* Create PDR */ i = 0; - ogs_list_for_each(&sess->bearer_list, bearer) { - ogs_list_for_each(&bearer->pfcp.pdr_list, pdr) { - ogs_pfcp_build_create_pdr(&req->create_pdr[i], i, pdr); - i++; - } + ogs_list_for_each(&sess->pfcp.pdr_list, pdr) { + ogs_pfcp_build_create_pdr(&req->create_pdr[i], i, pdr); + i++; } /* Create FAR */ i = 0; - ogs_list_for_each(&sess->bearer_list, bearer) { - ogs_list_for_each(&bearer->pfcp.far_list, far) { - ogs_pfcp_build_create_far(&req->create_far[i], i, far); - i++; - } + ogs_list_for_each(&sess->pfcp.far_list, far) { + ogs_pfcp_build_create_far(&req->create_far[i], i, far); + i++; } /* Create URR */ i = 0; - ogs_list_for_each(&sess->bearer_list, bearer) { - ogs_list_for_each(&bearer->pfcp.urr_list, urr) { - ogs_pfcp_build_create_urr(&req->create_urr[i], i, urr); - i++; - } + ogs_list_for_each(&sess->pfcp.urr_list, urr) { + ogs_pfcp_build_create_urr(&req->create_urr[i], i, urr); + i++; } /* Create QER */ i = 0; - ogs_list_for_each(&sess->bearer_list, bearer) { - ogs_list_for_each(&bearer->pfcp.qer_list, qer) { - ogs_pfcp_build_create_qer(&req->create_qer[i], i, qer); - i++; - } + ogs_list_for_each(&sess->pfcp.qer_list, qer) { + ogs_pfcp_build_create_qer(&req->create_qer[i], i, qer); + i++; } /* PDN Type */ @@ -118,9 +108,6 @@ ogs_pkbuf_t *smf_n4_build_qos_flow_modification_request( { ogs_pfcp_message_t pfcp_message; ogs_pfcp_session_modification_request_t *req = NULL; - ogs_pfcp_pdr_t *pdr = NULL; - ogs_pfcp_far_t *far = NULL; - ogs_pfcp_qer_t *qer = NULL; ogs_pkbuf_t *pkbuf = NULL; int i; @@ -138,34 +125,50 @@ ogs_pkbuf_t *smf_n4_build_qos_flow_modification_request( if (modify_flags & OGS_PFCP_MODIFY_REMOVE) { /* Remove PDR */ i = 0; - ogs_list_for_each(&qos_flow->pfcp.pdr_list, pdr) { + if (qos_flow->dl_pdr) { ogs_pfcp_tlv_remove_pdr_t *message = &req->remove_pdr[i]; message->presence = 1; message->pdr_id.presence = 1; - message->pdr_id.u16 = pdr->id; + message->pdr_id.u16 = qos_flow->dl_pdr->id; + i++; + } + if (qos_flow->ul_pdr) { + ogs_pfcp_tlv_remove_pdr_t *message = &req->remove_pdr[i]; + + message->presence = 1; + message->pdr_id.presence = 1; + message->pdr_id.u16 = qos_flow->ul_pdr->id; i++; } /* Remove FAR */ i = 0; - ogs_list_for_each(&qos_flow->pfcp.far_list, far) { + if (qos_flow->dl_far) { ogs_pfcp_tlv_remove_far_t *message = &req->remove_far[i]; message->presence = 1; message->far_id.presence = 1; - message->far_id.u32 = far->id; + message->far_id.u32 = qos_flow->dl_far->id; + i++; + } + if (qos_flow->ul_far) { + ogs_pfcp_tlv_remove_far_t *message = &req->remove_far[i]; + + message->presence = 1; + message->far_id.presence = 1; + message->far_id.u32 = qos_flow->ul_far->id; i++; } /* Remove QER */ i = 0; - ogs_list_for_each(&qos_flow->pfcp.qer_list, qer) { + if (qos_flow->qer) { ogs_pfcp_tlv_remove_qer_t *message = &req->remove_qer[i]; message->presence = 1; message->qer_id.presence = 1; - message->qer_id.u32 = qer->id; + message->qer_id.u32 = qos_flow->qer->id; i++; } } else { @@ -174,22 +177,35 @@ ogs_pkbuf_t *smf_n4_build_qos_flow_modification_request( /* Create PDR */ i = 0; - ogs_list_for_each(&qos_flow->pfcp.pdr_list, pdr) { - ogs_pfcp_build_create_pdr(&req->create_pdr[i], i, pdr); + if (qos_flow->dl_pdr) { + ogs_pfcp_build_create_pdr( + &req->create_pdr[i], i, qos_flow->dl_pdr); + i++; + } + if (qos_flow->ul_pdr) { + ogs_pfcp_build_create_pdr( + &req->create_pdr[i], i, qos_flow->ul_pdr); i++; } /* Create FAR */ i = 0; - ogs_list_for_each(&qos_flow->pfcp.far_list, far) { - ogs_pfcp_build_create_far(&req->create_far[i], i, far); + if (qos_flow->dl_far) { + ogs_pfcp_build_create_far( + &req->create_far[i], i, qos_flow->dl_far); + i++; + } + if (qos_flow->ul_far) { + ogs_pfcp_build_create_far( + &req->create_far[i], i, qos_flow->ul_far); i++; } /* Create QER */ i = 0; - ogs_list_for_each(&qos_flow->pfcp.qer_list, qer) { - ogs_pfcp_build_create_qer(&req->create_qer[i], i, qer); + if (qos_flow->qer) { + ogs_pfcp_build_create_qer( + &req->create_qer[i], i, qos_flow->qer); i++; } } @@ -198,35 +214,39 @@ ogs_pkbuf_t *smf_n4_build_qos_flow_modification_request( /* Update PDR */ i = 0; - ogs_list_for_each(&qos_flow->pfcp.pdr_list, pdr) { - ogs_pfcp_build_update_pdr(&req->update_pdr[i], i, pdr); + if (qos_flow->dl_pdr) { + ogs_pfcp_build_update_pdr( + &req->update_pdr[i], i, qos_flow->dl_pdr); + i++; + } + if (qos_flow->ul_pdr) { + ogs_pfcp_build_update_pdr( + &req->update_pdr[i], i, qos_flow->ul_pdr); i++; } } if (modify_flags & OGS_PFCP_MODIFY_ACTIVATE) { /* Update FAR - Only DL */ i = 0; - ogs_list_for_each(&qos_flow->pfcp.far_list, far) { - if (far->dst_if == OGS_PFCP_INTERFACE_ACCESS) { - - if (modify_flags & OGS_PFCP_MODIFY_END_MARKER) { - far->smreq_flags.send_end_marker_packets = 1; - } - - ogs_pfcp_build_update_far_activate( - &req->update_far[i], i, far); - i++; - - /* Clear all FAR flags */ - far->smreq_flags.value = 0; + if (qos_flow->dl_far) { + if (modify_flags & OGS_PFCP_MODIFY_END_MARKER) { + qos_flow->dl_far->smreq_flags.send_end_marker_packets = 1; } + + ogs_pfcp_build_update_far_activate( + &req->update_far[i], i, qos_flow->dl_far); + i++; + + /* Clear all FAR flags */ + qos_flow->dl_far->smreq_flags.value = 0; } } if (modify_flags & OGS_PFCP_MODIFY_QOS_UPDATE) { /* Update QER */ i = 0; - ogs_list_for_each(&qos_flow->pfcp.qer_list, qer) { - ogs_pfcp_build_update_qer(&req->update_qer[i], i, qer); + if (qos_flow->qer) { + ogs_pfcp_build_update_qer( + &req->update_qer[i], i, qos_flow->qer); i++; } } @@ -263,7 +283,6 @@ ogs_pkbuf_t *smf_5gc_n4_build_session_modification_request( ogs_pfcp_session_modification_request_t *req = NULL; ogs_pfcp_far_t *far = NULL; ogs_pkbuf_t *pkbuf = NULL; - smf_bearer_t *bearer = NULL; ogs_debug("Session Modification Request"); ogs_assert(sess); @@ -273,14 +292,12 @@ ogs_pkbuf_t *smf_5gc_n4_build_session_modification_request( memset(&pfcp_message, 0, sizeof(ogs_pfcp_message_t)); i = 0; - ogs_list_for_each(&sess->bearer_list, bearer) { - ogs_list_for_each(&bearer->pfcp.far_list, far) { - /* Update FAR - Only DL */ - if (far->dst_if == OGS_PFCP_INTERFACE_ACCESS) { - ogs_pfcp_build_update_far_deactivate( - &req->update_far[i], i, far); - i++; - } + ogs_list_for_each(&sess->pfcp.far_list, far) { + /* Update FAR - Only DL */ + if (far->dst_if == OGS_PFCP_INTERFACE_ACCESS) { + ogs_pfcp_build_update_far_deactivate( + &req->update_far[i], i, far); + i++; } } diff --git a/src/smf/ngap-handler.c b/src/smf/ngap-handler.c index 074f298ed..565353da1 100644 --- a/src/smf/ngap-handler.c +++ b/src/smf/ngap-handler.c @@ -31,7 +31,7 @@ int ngap_handle_pdu_session_resource_setup_response_transfer( uint32_t upf_n3_teid; ogs_ip_t upf_n3_ip; - ogs_pfcp_far_t *far = NULL; + ogs_pfcp_far_t *dl_far = NULL; bool far_update = false; NGAP_PDUSessionResourceSetupResponseTransfer_t message; @@ -118,25 +118,19 @@ int ngap_handle_pdu_session_resource_setup_response_transfer( sess->gnb_n3_teid != upf_n3_teid) far_update = true; - ogs_list_for_each(&qos_flow->pfcp.far_list, far) { - if (far->dst_if == OGS_PFCP_INTERFACE_ACCESS) { - if (far->apply_action != OGS_PFCP_APPLY_ACTION_FORW) { - far_update = true; - } - } + dl_far = qos_flow->dl_far; + ogs_assert(dl_far); + if (dl_far->apply_action != OGS_PFCP_APPLY_ACTION_FORW) { + far_update = true; } /* Setup FAR */ memcpy(&sess->gnb_n3_ip, &upf_n3_ip, sizeof(sess->gnb_n3_ip)); sess->gnb_n3_teid = upf_n3_teid; - ogs_list_for_each(&qos_flow->pfcp.far_list, far) { - if (far->dst_if == OGS_PFCP_INTERFACE_ACCESS) { - ogs_pfcp_ip_to_outer_header_creation(&sess->gnb_n3_ip, - &far->outer_header_creation, &far->outer_header_creation_len); - far->outer_header_creation.teid = sess->gnb_n3_teid; - } - } + ogs_pfcp_ip_to_outer_header_creation(&sess->gnb_n3_ip, + &dl_far->outer_header_creation, &dl_far->outer_header_creation_len); + dl_far->outer_header_creation.teid = sess->gnb_n3_teid; if (far_update) { smf_5gc_pfcp_send_qos_flow_modification_request( diff --git a/src/smf/nudm-handler.c b/src/smf/nudm-handler.c index 74c8c2a84..4981b4463 100644 --- a/src/smf/nudm-handler.c +++ b/src/smf/nudm-handler.c @@ -30,7 +30,8 @@ bool smf_nudm_sdm_handle_get(smf_sess_t *sess, ogs_sbi_session_t *session, smf_bearer_t *qos_flow = NULL; ogs_pfcp_gtpu_resource_t *resource = NULL; - ogs_pfcp_pdr_t *pdr = NULL; + ogs_pfcp_pdr_t *dl_pdr = NULL; + ogs_pfcp_pdr_t *ul_pdr = NULL; ogs_pfcp_qer_t *qer = NULL; ogs_sbi_server_t *server = NULL; @@ -311,30 +312,30 @@ bool smf_nudm_sdm_handle_get(smf_sess_t *sess, ogs_sbi_session_t *session, ogs_assert(qos_flow); /* Setup QER */ - ogs_list_for_each(&qos_flow->pfcp.qer_list, qer) { - qer->mbr.uplink = sess->pdn.ambr.uplink; - qer->mbr.downlink = sess->pdn.ambr.downlink; - } + qer = qos_flow->qer; + ogs_assert(qer); + qer->mbr.uplink = sess->pdn.ambr.uplink; + qer->mbr.downlink = sess->pdn.ambr.downlink; /* Setup PDR */ - ogs_list_for_each(&qos_flow->pfcp.pdr_list, pdr) { + dl_pdr = qos_flow->dl_pdr; + ogs_assert(dl_pdr); + ul_pdr = qos_flow->ul_pdr; + ogs_assert(ul_pdr); - /* Set UE IP Address to the Default DL PDR */ - if (pdr->src_if == OGS_PFCP_INTERFACE_CORE) { - ogs_pfcp_paa_to_ue_ip_addr(&sess->pdn.paa, - &pdr->ue_ip_addr, &pdr->ue_ip_addr_len); - pdr->ue_ip_addr.sd = OGS_PFCP_UE_IP_DST; + /* Set UE IP Address to the Default DL PDR */ + ogs_pfcp_paa_to_ue_ip_addr(&sess->pdn.paa, + &dl_pdr->ue_ip_addr, &dl_pdr->ue_ip_addr_len); + dl_pdr->ue_ip_addr.sd = OGS_PFCP_UE_IP_DST; - /* Set UPF-N3 TEID & ADDR to the Default UL PDR */ - } else if (pdr->src_if == OGS_PFCP_INTERFACE_ACCESS) { - ogs_pfcp_sockaddr_to_f_teid(sess->upf_n3_addr, sess->upf_n3_addr6, - &pdr->f_teid, &pdr->f_teid_len); - pdr->f_teid.teid = sess->upf_n3_teid; - } + /* Set UPF-N3 TEID & ADDR to the Default UL PDR */ + ogs_pfcp_sockaddr_to_f_teid(sess->upf_n3_addr, sess->upf_n3_addr6, + &ul_pdr->f_teid, &ul_pdr->f_teid_len); + ul_pdr->f_teid.teid = sess->upf_n3_teid; - /* Default PDRs is set to lowest precedence(highest precedence value) */ - pdr->precedence = 0xffffffff; - } + /* Default PDRs is set to lowest precedence(highest precedence value) */ + dl_pdr->precedence = 0xffffffff; + ul_pdr->precedence = 0xffffffff; smf_5gc_pfcp_send_session_establishment_request(sess, session); diff --git a/src/smf/s5c-build.c b/src/smf/s5c-build.c index 5df42e002..1afaf5128 100644 --- a/src/smf/s5c-build.c +++ b/src/smf/s5c-build.c @@ -32,7 +32,7 @@ ogs_pkbuf_t *smf_s5c_build_create_session_response( ogs_gtp_create_session_response_t *rsp = NULL; ogs_gtp_cause_t cause; - ogs_gtp_f_teid_t smf_s5c_teid, upf_s5u_teid; + ogs_gtp_f_teid_t smf_s5c_teid, pgw_s5u_teid; ogs_gtp_ambr_t ambr; ogs_gtp_bearer_qos_t bearer_qos; char bearer_qos_buf[GTP_BEARER_QOS_LEN]; @@ -48,8 +48,8 @@ ogs_pkbuf_t *smf_s5c_build_create_session_response( ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]", sess->sgw_s5c_teid, sess->smf_n4_teid); - ogs_debug(" SGW_S5U_TEID[0x%x] UPF_S5U_TEID[0x%x]", - bearer->sgw_s5u_teid, bearer->upf_s5u_teid); + ogs_debug(" SGW_S5U_TEID[0x%x] PGW_S5U_TEID[0x%x]", + bearer->sgw_s5u_teid, bearer->pgw_s5u_teid); rsp = >p_message.create_session_response; memset(>p_message, 0, sizeof(ogs_gtp_message_t)); @@ -140,14 +140,14 @@ ogs_pkbuf_t *smf_s5c_build_create_session_response( } /* Data Plane(UL) : SMF-S5U */ - memset(&upf_s5u_teid, 0, sizeof(ogs_gtp_f_teid_t)); - upf_s5u_teid.interface_type = OGS_GTP_F_TEID_S5_S8_PGW_GTP_U; - upf_s5u_teid.teid = htobe32(bearer->upf_s5u_teid); + memset(&pgw_s5u_teid, 0, sizeof(ogs_gtp_f_teid_t)); + pgw_s5u_teid.interface_type = OGS_GTP_F_TEID_S5_S8_PGW_GTP_U; + pgw_s5u_teid.teid = htobe32(bearer->pgw_s5u_teid); rv = ogs_gtp_sockaddr_to_f_teid( - bearer->upf_s5u_addr, bearer->upf_s5u_addr6, &upf_s5u_teid, &len); + bearer->pgw_s5u_addr, bearer->pgw_s5u_addr6, &pgw_s5u_teid, &len); ogs_assert(rv == OGS_OK); rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.presence = 1; - rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.data = &upf_s5u_teid; + rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.data = &pgw_s5u_teid; rsp->bearer_contexts_created.s5_s8_u_sgw_f_teid.len = len; gtp_message.h.type = type; @@ -206,7 +206,7 @@ ogs_pkbuf_t *smf_s5c_build_create_bearer_request( ogs_gtp_message_t gtp_message; ogs_gtp_create_bearer_request_t *req = NULL; - ogs_gtp_f_teid_t upf_s5u_teid; + ogs_gtp_f_teid_t pgw_s5u_teid; ogs_gtp_bearer_qos_t bearer_qos; char bearer_qos_buf[GTP_BEARER_QOS_LEN]; int len; @@ -234,15 +234,15 @@ ogs_pkbuf_t *smf_s5c_build_create_bearer_request( req->bearer_contexts.eps_bearer_id.presence = 1; req->bearer_contexts.eps_bearer_id.u8 = bearer->ebi; - /* Data Plane(UL) : UPF-S5U */ - memset(&upf_s5u_teid, 0, sizeof(ogs_gtp_f_teid_t)); - upf_s5u_teid.interface_type = OGS_GTP_F_TEID_S5_S8_PGW_GTP_U; - upf_s5u_teid.teid = htobe32(bearer->upf_s5u_teid); + /* Data Plane(UL) : PGW-S5U */ + memset(&pgw_s5u_teid, 0, sizeof(ogs_gtp_f_teid_t)); + pgw_s5u_teid.interface_type = OGS_GTP_F_TEID_S5_S8_PGW_GTP_U; + pgw_s5u_teid.teid = htobe32(bearer->pgw_s5u_teid); rv = ogs_gtp_sockaddr_to_f_teid( - bearer->upf_s5u_addr, bearer->upf_s5u_addr6, &upf_s5u_teid, &len); + bearer->pgw_s5u_addr, bearer->pgw_s5u_addr6, &pgw_s5u_teid, &len); ogs_assert(rv == OGS_OK); req->bearer_contexts.s5_s8_u_sgw_f_teid.presence = 1; - req->bearer_contexts.s5_s8_u_sgw_f_teid.data = &upf_s5u_teid; + req->bearer_contexts.s5_s8_u_sgw_f_teid.data = &pgw_s5u_teid; req->bearer_contexts.s5_s8_u_sgw_f_teid.len = len; /* Bearer QoS */ diff --git a/src/smf/s5c-handler.c b/src/smf/s5c-handler.c index 602f326e2..0f1f7927b 100644 --- a/src/smf/s5c-handler.c +++ b/src/smf/s5c-handler.c @@ -134,10 +134,10 @@ void smf_s5c_handle_create_session_request( memcpy(&sess->e_tai, &uli.tai, sizeof(sess->e_tai)); memcpy(&sess->e_cgi, &uli.e_cgi, sizeof(sess->e_cgi)); - /* Select UPF based on UE Location Information */ + /* Select PGW based on UE Location Information */ smf_sess_select_upf(sess); - /* Check if selected UPF is associated with SMF */ + /* Check if selected PGW is associated with SMF */ ogs_assert(sess->pfcp_node); if (!OGS_FSM_CHECK(&sess->pfcp_node->sm, smf_pfcp_state_associated)) { ogs_gtp_send_error_message(xact, sess ? sess->sgw_s5c_teid : 0, @@ -183,8 +183,8 @@ void smf_s5c_handle_create_session_request( ogs_debug(" SGW_S5C_TEID[0x%x] SMF_N4_TEID[0x%x]", sess->sgw_s5c_teid, sess->smf_n4_teid); - ogs_debug(" SGW_S5U_TEID[0x%x] UPF_S5U_TEID[0x%x]", - bearer->sgw_s5u_teid, bearer->upf_s5u_teid); + ogs_debug(" SGW_S5U_TEID[0x%x] PGW_S5U_TEID[0x%x]", + bearer->sgw_s5u_teid, bearer->pgw_s5u_teid); decoded = ogs_gtp_parse_bearer_qos(&bearer_qos, &req->bearer_contexts_to_be_created.bearer_level_qos); @@ -273,9 +273,9 @@ void smf_s5c_handle_create_bearer_response( ogs_gtp_create_bearer_response_t *rsp) { int rv; - ogs_gtp_f_teid_t *sgw_s5u_teid, *upf_s5u_teid; + ogs_gtp_f_teid_t *sgw_s5u_teid, *pgw_s5u_teid; smf_bearer_t *bearer = NULL; - ogs_pfcp_far_t *far = NULL; + ogs_pfcp_far_t *dl_far = NULL; ogs_assert(xact); ogs_assert(rsp); @@ -320,12 +320,12 @@ void smf_s5c_handle_create_bearer_response( return; } - /* Correlate with UPF-S5U-TEID */ - upf_s5u_teid = rsp->bearer_contexts.s5_s8_u_pgw_f_teid.data; - ogs_assert(upf_s5u_teid); + /* Correlate with PGW-S5U-TEID */ + pgw_s5u_teid = rsp->bearer_contexts.s5_s8_u_pgw_f_teid.data; + ogs_assert(pgw_s5u_teid); - /* Find the Bearer by UPF-S5U-TEID */ - bearer = smf_bearer_find_by_upf_s5u_teid(be32toh(upf_s5u_teid->teid)); + /* Find the Bearer by PGW-S5U-TEID */ + bearer = smf_bearer_find_by_pgw_s5u_teid(be32toh(pgw_s5u_teid->teid)); ogs_assert(bearer); /* Set EBI */ @@ -342,30 +342,29 @@ void smf_s5c_handle_create_bearer_response( sess->sgw_s5c_teid, sess->smf_n4_teid); /* Setup FAR */ - ogs_list_for_each(&bearer->pfcp.far_list, far) { - if (far->dst_if == OGS_PFCP_INTERFACE_ACCESS) { - ogs_pfcp_ip_to_outer_header_creation(&bearer->sgw_s5u_ip, - &far->outer_header_creation, &far->outer_header_creation_len); - far->outer_header_creation.teid = bearer->sgw_s5u_teid; - } - } + dl_far = bearer->dl_far; + ogs_assert(dl_far); + + ogs_pfcp_ip_to_outer_header_creation(&bearer->sgw_s5u_ip, + &dl_far->outer_header_creation, &dl_far->outer_header_creation_len); + dl_far->outer_header_creation.teid = bearer->sgw_s5u_teid; /* Setup QER */ if (bearer->qos.mbr.downlink || bearer->qos.mbr.uplink || bearer->qos.gbr.downlink || bearer->qos.gbr.uplink) { - ogs_pfcp_pdr_t *pdr = NULL; ogs_pfcp_qer_t *qer = NULL; /* Only 1 QER is used per bearer */ - qer = ogs_list_first(&bearer->pfcp.qer_list); + qer = bearer->qer; if (!qer) { - qer = ogs_pfcp_qer_add(&bearer->pfcp); + qer = ogs_pfcp_qer_add(&sess->pfcp); ogs_assert(qer); - qer->id = OGS_NEXT_ID(sess->qer_id, 1, OGS_MAX_NUM_OF_QER+1); + qer->id = qer->index; + bearer->qer = qer; } - ogs_list_for_each(&bearer->pfcp.pdr_list, pdr) - ogs_pfcp_pdr_associate_qer(pdr, qer); + 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; @@ -432,31 +431,27 @@ void smf_s5c_handle_update_bearer_response( if (gtp_flags & OGS_GTP_MODIFY_TFT_UPDATE) { smf_pf_t *pf = NULL; - ogs_pfcp_pdr_t *pdr = NULL; + ogs_pfcp_pdr_t *dl_pdr = NULL, *ul_pdr = NULL; - ogs_list_for_each(&bearer->pfcp.pdr_list, pdr) - pdr->num_of_flow = 0; + 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) { - ogs_list_for_each(&bearer->pfcp.pdr_list, pdr) { - if (pf->direction == OGS_FLOW_DOWNLINK_ONLY) { - if (pdr->src_if == OGS_PFCP_INTERFACE_CORE) { - pdr->flow_description[pdr->num_of_flow++] = - pf->flow_description; - break; - } + 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) { - if (pdr->src_if == OGS_PFCP_INTERFACE_ACCESS) { - pdr->flow_description[pdr->num_of_flow++] = - pf->flow_description; - break; - } - } else { - ogs_error("Flow Bidirectional is not supported[%d]", - pf->direction); - break; - } + } 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); } } @@ -467,7 +462,7 @@ void smf_s5c_handle_update_bearer_response( ogs_pfcp_qer_t *qer = NULL; /* Only 1 QER is used per bearer */ - qer = ogs_list_first(&bearer->pfcp.qer_list); + qer = bearer->qer; if (qer) { qer->mbr.uplink = bearer->qos.mbr.uplink; qer->mbr.downlink = bearer->qos.mbr.downlink; diff --git a/src/upf/context.c b/src/upf/context.c index 2328bd89f..341860ce7 100644 --- a/src/upf/context.c +++ b/src/upf/context.c @@ -388,6 +388,12 @@ upf_sess_t *upf_sess_add(ogs_pfcp_f_seid_t *cp_f_seid, ogs_assert(sess); memset(sess, 0, sizeof *sess); + ogs_pool_init(&sess->pfcp.pdr_pool, OGS_MAX_NUM_OF_PDR); + ogs_pool_init(&sess->pfcp.far_pool, OGS_MAX_NUM_OF_FAR); + ogs_pool_init(&sess->pfcp.urr_pool, OGS_MAX_NUM_OF_URR); + ogs_pool_init(&sess->pfcp.qer_pool, OGS_MAX_NUM_OF_QER); + ogs_pool_init(&sess->pfcp.bar_pool, OGS_MAX_NUM_OF_BAR); + sess->index = ogs_pool_index(&upf_sess_pool, sess); ogs_assert(sess->index > 0 && sess->index <= ogs_app()->pool.sess); @@ -483,6 +489,12 @@ int upf_sess_remove(upf_sess_t *sess) ogs_pfcp_ue_ip_free(sess->ipv6); } + ogs_pool_final(&sess->pfcp.pdr_pool); + ogs_pool_final(&sess->pfcp.far_pool); + ogs_pool_final(&sess->pfcp.urr_pool); + ogs_pool_final(&sess->pfcp.qer_pool); + ogs_pool_final(&sess->pfcp.bar_pool); + ogs_pool_free(&upf_sess_pool, sess); ogs_info("Removed a session. Number of active sessions is now %d", diff --git a/tests/volte/abts-main.c b/tests/volte/abts-main.c index 427037da0..671c0dcd3 100644 --- a/tests/volte/abts-main.c +++ b/tests/volte/abts-main.c @@ -24,6 +24,7 @@ abts_suite *test_bearer(abts_suite *suite); abts_suite *test_session(abts_suite *suite); abts_suite *test_rx(abts_suite *suite); +abts_suite *test_video(abts_suite *suite); const struct testlist { abts_suite *(*func)(abts_suite *suite); @@ -31,6 +32,7 @@ const struct testlist { {test_bearer}, {test_session}, {test_rx}, + {test_video}, {NULL}, }; diff --git a/tests/volte/meson.build b/tests/volte/meson.build index 11c497173..a45e9b8ff 100644 --- a/tests/volte/meson.build +++ b/tests/volte/meson.build @@ -23,6 +23,7 @@ testapp_volte_sources = files(''' bearer-test.c session-test.c rx-test.c + video-test.c '''.split()) testapp_volte_exe = executable('volte', diff --git a/tests/volte/pcscf-fd-path.c b/tests/volte/pcscf-fd-path.c index a15f84fdb..2de00c6af 100644 --- a/tests/volte/pcscf-fd-path.c +++ b/tests/volte/pcscf-fd-path.c @@ -20,6 +20,7 @@ #include "ogs-gtp.h" #include "ogs-diameter-rx.h" +#include "test-common.h" #include "pcscf-fd-path.h" #define MAX_NUM_SESSION_STATE 32 @@ -66,8 +67,8 @@ static int pcscf_rx_fb_cb(struct msg **msg, struct avp *avp, return ENOTSUP; } -void pcscf_rx_send_aar(uint8_t **rx_sid, const char *ip, - int qos_type, int flow_presence) +void pcscf_rx_send_aar(uint8_t **rx_sid, + test_sess_t *sess, int id_type, int qos_type, int flow_type) { int rv; int ret; @@ -80,14 +81,26 @@ void pcscf_rx_send_aar(uint8_t **rx_sid, const char *ip, struct session *session = NULL; int new; + test_ue_t *test_ue = NULL; + char *ipstr = NULL; + char *sip_uri = NULL; ogs_paa_t paa; ogs_ipsubnet_t ipsub; + ogs_assert(sess); + test_ue = sess->test_ue; + ogs_assert(test_ue); ogs_assert(rx_sid); - ogs_assert(ip); - rv = ogs_ipsubnet(&ipsub, ip, NULL); + ogs_assert(sess->ue_ip.ipv4); + ipstr = ogs_ipv4_to_string(sess->ue_ip.addr); + ogs_assert(ipstr); + sip_uri = ogs_msprintf("sip:%s:40491", ipstr); + ogs_assert(sip_uri); + + rv = ogs_ipsubnet(&ipsub, ipstr, NULL); ogs_assert(rv == OGS_OK); + ogs_free(ipstr); /* Create the request */ ret = fd_msg_new(ogs_diam_rx_cmd_aar, MSGFL_ALLOC_ETEID, &req); @@ -115,7 +128,7 @@ void pcscf_rx_send_aar(uint8_t **rx_sid, const char *ip, } else { /* Create a new session */ #define OGS_DIAM_RX_APP_SID_OPT "app_rx" - ret = fd_msg_new_session(req, (os0_t)OGS_DIAM_RX_APP_SID_OPT, + ret = fd_msg_new_session(req, (os0_t)OGS_DIAM_RX_APP_SID_OPT, CONSTSTRLEN(OGS_DIAM_RX_APP_SID_OPT)); ogs_assert(ret == 0); ret = fd_msg_sess_get(fd_g_config->cnf_dict, req, &session, NULL); @@ -138,11 +151,11 @@ void pcscf_rx_send_aar(uint8_t **rx_sid, const char *ip, /* Save Session-Id to PGW Session Context */ *rx_sid = sess_data->sid; } - + /* Set Origin-Host & Origin-Realm */ ret = fd_msg_add_origin(req, 0); ogs_assert(ret == 0); - + /* Set the Destination-Realm AVP */ ret = fd_msg_avp_new(ogs_diam_destination_realm, 0, &avp); ogs_assert(ret == 0); @@ -162,23 +175,51 @@ void pcscf_rx_send_aar(uint8_t **rx_sid, const char *ip, ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); ogs_assert(ret == 0); + /* Set Vendor-Specific-Application-Id AVP */ + ret = ogs_diam_message_vendor_specific_appid_set( + req, OGS_DIAM_RX_APPLICATION_ID); + ogs_assert(ret == 0); + + /* Set the AF-Application-Identifier AVP */ + ret = fd_msg_avp_new(ogs_diam_rx_af_application_identifier, 0, &avp); + ogs_assert(ret == 0); + val.os.data = (unsigned char *)("IMS Services"); + val.os.len = strlen("IMS Services"); + ret = fd_msg_avp_setvalue(avp, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); + + /* Set the Authroization-Lifetime AVP */ + ret = fd_msg_avp_new(ogs_diam_authorization_lifetime, 0, &avp); + ogs_assert(ret == 0); + val.i32 = 7200; + ret = fd_msg_avp_setvalue(avp, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); + /* Set Subscription-Id */ ret = fd_msg_avp_new(ogs_diam_rx_subscription_id, 0, &avp); ogs_assert(ret == 0); ret = fd_msg_avp_new(ogs_diam_rx_subscription_id_type, 0, &avpch1); ogs_assert(ret == 0); - val.i32 = OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_IMSI; - ret = fd_msg_avp_setvalue (avpch1, &val); + val.i32 = id_type; + ret = fd_msg_avp_setvalue(avpch1, &val); ogs_assert(ret == 0); ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); ogs_assert(ret == 0); - #define OGS_DIAM_RX_APP_IMSI_BCD "001010123456789" ret = fd_msg_avp_new(ogs_diam_rx_subscription_id_data, 0, &avpch1); ogs_assert(ret == 0); - val.os.data = (uint8_t *)OGS_DIAM_RX_APP_IMSI_BCD; - val.os.len = strlen(OGS_DIAM_RX_APP_IMSI_BCD); + if (id_type == OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_IMSI) { + val.os.data = (uint8_t *)test_ue->imsi; + val.os.len = strlen(test_ue->imsi); + } else if (id_type == OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_SIP_URI) { + val.os.data = (uint8_t *)sip_uri; + val.os.len = strlen(sip_uri); + } ret = fd_msg_avp_setvalue (avpch1, &val); ogs_assert(ret == 0); ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); @@ -187,6 +228,15 @@ void pcscf_rx_send_aar(uint8_t **rx_sid, const char *ip, ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); ogs_assert(ret == 0); + /* Set the Reservation-Priority AVP */ + ret = fd_msg_avp_new(ogs_diam_rx_reservation_priority, 0, &avp); + ogs_assert(ret == 0); + val.i32 = 0; + ret = fd_msg_avp_setvalue(avp, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); + if (ipsub.family == AF_INET) { /* Set Framed-IP-Address */ ret = fd_msg_avp_new(ogs_diam_rx_framed_ip_address, 0, &avp); @@ -206,7 +256,7 @@ void pcscf_rx_send_aar(uint8_t **rx_sid, const char *ip, memcpy(paa.addr6, ipsub.sub, OGS_IPV6_LEN); paa.pdn_type = 0x03; #define FRAMED_IPV6_PREFIX_LENGTH 128 /* from spec document */ - paa.len = FRAMED_IPV6_PREFIX_LENGTH; + paa.len = FRAMED_IPV6_PREFIX_LENGTH; val.os.data = (uint8_t*)&paa; val.os.len = OGS_PAA_IPV6_LEN; ret = fd_msg_avp_setvalue(avp, &val); @@ -235,8 +285,11 @@ void pcscf_rx_send_aar(uint8_t **rx_sid, const char *ip, ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); ogs_assert(ret == 0); - if (qos_type == 1) { - ret = fd_msg_avp_new(ogs_diam_rx_max_requested_bandwidth_dl, 0, &avpch1); + if (qos_type == 0) { + /* Nothing */ + } else if (qos_type == 1) { + ret = fd_msg_avp_new( + ogs_diam_rx_max_requested_bandwidth_dl, 0, &avpch1); ogs_assert(ret == 0); val.i32 = 96000; ret = fd_msg_avp_setvalue (avpch1, &val); @@ -244,7 +297,8 @@ void pcscf_rx_send_aar(uint8_t **rx_sid, const char *ip, ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); ogs_assert(ret == 0); - ret = fd_msg_avp_new(ogs_diam_rx_max_requested_bandwidth_ul, 0, &avpch1); + ret = fd_msg_avp_new( + ogs_diam_rx_max_requested_bandwidth_ul, 0, &avpch1); ogs_assert(ret == 0); val.i32 = 96000; ret = fd_msg_avp_setvalue (avpch1, &val); @@ -268,7 +322,8 @@ void pcscf_rx_send_aar(uint8_t **rx_sid, const char *ip, ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); ogs_assert(ret == 0); } else if (qos_type == 2) { - ret = fd_msg_avp_new(ogs_diam_rx_max_requested_bandwidth_dl, 0, &avpch1); + ret = fd_msg_avp_new( + ogs_diam_rx_max_requested_bandwidth_dl, 0, &avpch1); ogs_assert(ret == 0); val.i32 = 96000; ret = fd_msg_avp_setvalue (avpch1, &val); @@ -276,7 +331,8 @@ void pcscf_rx_send_aar(uint8_t **rx_sid, const char *ip, ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); ogs_assert(ret == 0); - ret = fd_msg_avp_new(ogs_diam_rx_max_requested_bandwidth_ul, 0, &avpch1); + ret = fd_msg_avp_new( + ogs_diam_rx_max_requested_bandwidth_ul, 0, &avpch1); ogs_assert(ret == 0); val.i32 = 96000; ret = fd_msg_avp_setvalue (avpch1, &val); @@ -284,7 +340,8 @@ void pcscf_rx_send_aar(uint8_t **rx_sid, const char *ip, ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); ogs_assert(ret == 0); - ret = fd_msg_avp_new(ogs_diam_rx_min_requested_bandwidth_dl, 0, &avpch1); + ret = fd_msg_avp_new( + ogs_diam_rx_min_requested_bandwidth_dl, 0, &avpch1); ogs_assert(ret == 0); val.i32 = 88000; ret = fd_msg_avp_setvalue (avpch1, &val); @@ -292,16 +349,20 @@ void pcscf_rx_send_aar(uint8_t **rx_sid, const char *ip, ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); ogs_assert(ret == 0); - ret = fd_msg_avp_new(ogs_diam_rx_min_requested_bandwidth_ul, 0, &avpch1); + ret = fd_msg_avp_new( + ogs_diam_rx_min_requested_bandwidth_ul, 0, &avpch1); ogs_assert(ret == 0); val.i32 = 88000; ret = fd_msg_avp_setvalue (avpch1, &val); ogs_assert(ret == 0); ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); ogs_assert(ret == 0); + } else { + ogs_fatal("Unknown qos-type[%d]", qos_type); + ogs_assert_if_reached(); } - if (flow_presence) { + if (flow_type == 1) { /* Set Media-Sub-Component #1 */ ret = fd_msg_avp_new(ogs_diam_rx_media_sub_component, 0, &avpch1); @@ -381,6 +442,9 @@ void pcscf_rx_send_aar(uint8_t **rx_sid, const char *ip, ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); ogs_assert(ret == 0); + } else { + ogs_fatal("Unknown flow-type[%d]", flow_type); + ogs_assert_if_reached(); } ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); @@ -388,8 +452,676 @@ void pcscf_rx_send_aar(uint8_t **rx_sid, const char *ip, ret = clock_gettime(CLOCK_REALTIME, &sess_data->ts); ogs_assert(ret == 0); - - /* Keep a pointer to the session data for debug purpose, + + /* Keep a pointer to the session data for debug purpose, + * in real life we would not need it */ + svg = sess_data; + + /* Store this value in the session */ + ret = fd_sess_state_store(pcscf_rx_reg, session, &sess_data); + ogs_assert(ret == 0); + ogs_assert(sess_data == NULL); + + /* Send the request */ + ret = fd_msg_send(&req, pcscf_rx_aaa_cb, svg); + ogs_assert(ret == 0); + + /* Increment the counter */ + ogs_assert(pthread_mutex_lock(&ogs_diam_logger_self()->stats_lock) == 0); + ogs_diam_logger_self()->stats.nb_sent++; + ogs_assert(pthread_mutex_unlock(&ogs_diam_logger_self()->stats_lock) == 0); + + /* Free string memory */ + ogs_free(sip_uri); +} + +void pcscf_rx_send_aar2(uint8_t **rx_sid, test_sess_t *sess, int id_type) +{ + int rv; + int ret; + + struct msg *req = NULL; + struct avp *avp; + struct avp *avpch1, *avpch2; + union avp_value val; + struct sess_state *sess_data = NULL, *svg; + struct session *session = NULL; + int new; + + test_ue_t *test_ue = NULL; + char *ipstr = NULL; + char *sip_uri = NULL; + ogs_paa_t paa; + ogs_ipsubnet_t ipsub; + + ogs_assert(sess); + test_ue = sess->test_ue; + ogs_assert(test_ue); + ogs_assert(rx_sid); + + ogs_assert(sess->ue_ip.ipv4); + ipstr = ogs_ipv4_to_string(sess->ue_ip.addr); + ogs_assert(ipstr); + sip_uri = ogs_msprintf("sip:%s:40491", ipstr); + ogs_assert(sip_uri); + + rv = ogs_ipsubnet(&ipsub, ipstr, NULL); + ogs_assert(rv == OGS_OK); + ogs_free(ipstr); + + /* Create the request */ + ret = fd_msg_new(ogs_diam_rx_cmd_aar, MSGFL_ALLOC_ETEID, &req); + ogs_assert(ret == 0); + { + struct msg_hdr * h; + ret = fd_msg_hdr( req, &h ); + ogs_assert(ret == 0); + h->msg_appl = OGS_DIAM_RX_APPLICATION_ID; + } + + /* Find Diameter Rx Session */ + if (*rx_sid) { + /* Retrieve session by Session-Id */ + size_t sidlen = strlen((char *)*rx_sid); + ret = fd_sess_fromsid_msg(*rx_sid, sidlen, &session, &new); + ogs_assert(ret == 0); + ogs_assert(new == 0); + + /* Add Session-Id to the message */ + ret = ogs_diam_message_session_id_set(req, *rx_sid, sidlen); + ogs_assert(ret == 0); + /* Save the session associated with the message */ + ret = fd_msg_sess_set(req, session); + } else { + /* Create a new session */ + #define OGS_DIAM_RX_APP_SID_OPT "app_rx" + ret = fd_msg_new_session(req, (os0_t)OGS_DIAM_RX_APP_SID_OPT, + CONSTSTRLEN(OGS_DIAM_RX_APP_SID_OPT)); + ogs_assert(ret == 0); + ret = fd_msg_sess_get(fd_g_config->cnf_dict, req, &session, NULL); + ogs_assert(ret == 0); + } + + /* Retrieve session state in this session */ + ret = fd_sess_state_retrieve(pcscf_rx_reg, session, &sess_data); + if (!sess_data) { + os0_t sid; + size_t sidlen; + + ret = fd_sess_getsid(session, &sid, &sidlen); + ogs_assert(ret == 0); + + /* Allocate new session state memory */ + sess_data = new_state(sid); + ogs_assert(sess_data); + + /* Save Session-Id to PGW Session Context */ + *rx_sid = sess_data->sid; + } + + /* Set Origin-Host & Origin-Realm */ + ret = fd_msg_add_origin(req, 0); + ogs_assert(ret == 0); + + /* Set the Destination-Realm AVP */ + ret = fd_msg_avp_new(ogs_diam_destination_realm, 0, &avp); + ogs_assert(ret == 0); + val.os.data = (unsigned char *)(fd_g_config->cnf_diamrlm); + val.os.len = strlen(fd_g_config->cnf_diamrlm); + ret = fd_msg_avp_setvalue(avp, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); + + /* Set the Auth-Application-Id AVP */ + ret = fd_msg_avp_new(ogs_diam_auth_application_id, 0, &avp); + ogs_assert(ret == 0); + val.i32 = OGS_DIAM_RX_APPLICATION_ID; + ret = fd_msg_avp_setvalue(avp, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); + + /* Set Vendor-Specific-Application-Id AVP */ + ret = ogs_diam_message_vendor_specific_appid_set( + req, OGS_DIAM_RX_APPLICATION_ID); + ogs_assert(ret == 0); + + /* Set the AF-Application-Identifier AVP */ + ret = fd_msg_avp_new(ogs_diam_rx_af_application_identifier, 0, &avp); + ogs_assert(ret == 0); + val.os.data = (unsigned char *)("IMS Services"); + val.os.len = strlen("IMS Services"); + ret = fd_msg_avp_setvalue(avp, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); + + /* Set the Authroization-Lifetime AVP */ + ret = fd_msg_avp_new(ogs_diam_authorization_lifetime, 0, &avp); + ogs_assert(ret == 0); + val.i32 = 7200; + ret = fd_msg_avp_setvalue(avp, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); + + /* Set Subscription-Id */ + ret = fd_msg_avp_new(ogs_diam_rx_subscription_id, 0, &avp); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_subscription_id_type, 0, &avpch1); + ogs_assert(ret == 0); + val.i32 = id_type; + ret = fd_msg_avp_setvalue(avpch1, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_subscription_id_data, 0, &avpch1); + ogs_assert(ret == 0); + if (id_type == OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_IMSI) { + val.os.data = (uint8_t *)test_ue->imsi; + val.os.len = strlen(test_ue->imsi); + } else if (id_type == OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_SIP_URI) { + val.os.data = (uint8_t *)sip_uri; + val.os.len = strlen(sip_uri); + } + ret = fd_msg_avp_setvalue (avpch1, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); + ogs_assert(ret == 0); + + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); + + /* Set the Reservation-Priority AVP */ + ret = fd_msg_avp_new(ogs_diam_rx_reservation_priority, 0, &avp); + ogs_assert(ret == 0); + val.i32 = 0; + ret = fd_msg_avp_setvalue(avp, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); + + /* Set Media-Component-Description #1 */ + ret = fd_msg_avp_new(ogs_diam_rx_media_component_description, 0, &avp); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_media_component_number, 0, &avpch1); + ogs_assert(ret == 0); + val.i32 = 1; + ret = fd_msg_avp_setvalue (avpch1, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); + ogs_assert(ret == 0); + + /* Set Media-Sub-Component #1 */ + ret = fd_msg_avp_new(ogs_diam_rx_media_sub_component, 0, &avpch1); + + ret = fd_msg_avp_new(ogs_diam_rx_flow_number, 0, &avpch2); + ogs_assert(ret == 0); + val.i32 = 1; + ret = fd_msg_avp_setvalue (avpch2, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avpch1, MSG_BRW_LAST_CHILD, avpch2); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_flow_description, 0, &avpch2); + ogs_assert(ret == 0); + #define TEST_OGS_DIAM_RX_FLOW_DESC5 \ + "permit out 17 from 45.45.0.3 50022 to 45.45.0.5 50026" + val.os.data = (uint8_t *)TEST_OGS_DIAM_RX_FLOW_DESC5; + val.os.len = strlen(TEST_OGS_DIAM_RX_FLOW_DESC5); + ret = fd_msg_avp_setvalue (avpch2, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avpch1, MSG_BRW_LAST_CHILD, avpch2); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_flow_description, 0, &avpch2); + ogs_assert(ret == 0); + #define TEST_OGS_DIAM_RX_FLOW_DESC6 \ + "permit in 17 from 45.45.0.5 50026 to 45.45.0.3 50022" + val.os.data = (uint8_t *)TEST_OGS_DIAM_RX_FLOW_DESC6; + val.os.len = strlen(TEST_OGS_DIAM_RX_FLOW_DESC6); + ret = fd_msg_avp_setvalue (avpch2, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avpch1, MSG_BRW_LAST_CHILD, avpch2); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_flow_description, 0, &avpch2); + ogs_assert(ret == 0); + #define TEST_OGS_DIAM_RX_FLOW_DESC7 \ + "permit out 17 from 45.45.0.3 50023 to 45.45.0.5 50027" + val.os.data = (uint8_t *)TEST_OGS_DIAM_RX_FLOW_DESC7; + val.os.len = strlen(TEST_OGS_DIAM_RX_FLOW_DESC7); + ret = fd_msg_avp_setvalue (avpch2, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avpch1, MSG_BRW_LAST_CHILD, avpch2); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_flow_description, 0, &avpch2); + ogs_assert(ret == 0); + #define TEST_OGS_DIAM_RX_FLOW_DESC8 \ + "permit in 17 from 45.45.0.5 50027 to 45.45.0.3 50023" + val.os.data = (uint8_t *)TEST_OGS_DIAM_RX_FLOW_DESC8; + val.os.len = strlen(TEST_OGS_DIAM_RX_FLOW_DESC8); + ret = fd_msg_avp_setvalue (avpch2, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avpch1, MSG_BRW_LAST_CHILD, avpch2); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_flow_usage, 0, &avpch2); + ogs_assert(ret == 0); + val.i32 = OGS_DIAM_RX_FLOW_USAGE_NO_INFORMATION; + ret = fd_msg_avp_setvalue (avpch2, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avpch1, MSG_BRW_LAST_CHILD, avpch2); + ogs_assert(ret == 0); + + ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_media_type, 0, &avpch1); + ogs_assert(ret == 0); + val.i32 = OGS_DIAM_RX_MEDIA_TYPE_AUDIO; + ret = fd_msg_avp_setvalue (avpch1, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_max_requested_bandwidth_dl, 0, &avpch1); + ogs_assert(ret == 0); + val.i32 = 41000; + ret = fd_msg_avp_setvalue (avpch1, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_max_requested_bandwidth_ul, 0, &avpch1); + ogs_assert(ret == 0); + val.i32 = 41000; + ret = fd_msg_avp_setvalue (avpch1, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_rs_bandwidth, 0, &avpch1); + ogs_assert(ret == 0); + val.i32 = 600; + ret = fd_msg_avp_setvalue (avpch1, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_rr_bandwidth, 0, &avpch1); + ogs_assert(ret == 0); + val.i32 = 2000; + ret = fd_msg_avp_setvalue (avpch1, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_codec_data, 0, &avpch1); + ogs_assert(ret == 0); + #define TEST_OGS_DIAM_RX_CODEC_DATA1 \ + "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" + val.os.data = (uint8_t *)TEST_OGS_DIAM_RX_CODEC_DATA1; + val.os.len = strlen(TEST_OGS_DIAM_RX_CODEC_DATA1) + 1; + ret = fd_msg_avp_setvalue (avpch1, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_codec_data, 0, &avpch1); + ogs_assert(ret == 0); + #define TEST_OGS_DIAM_RX_CODEC_DATA2 \ + "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" + val.os.data = (uint8_t *)TEST_OGS_DIAM_RX_CODEC_DATA2; + val.os.len = strlen(TEST_OGS_DIAM_RX_CODEC_DATA2) + 1; + ret = fd_msg_avp_setvalue (avpch1, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_flow_status, 0, &avpch1); + ogs_assert(ret == 0); + val.i32 = OGS_DIAM_RX_FLOW_STATUS_ENABLED; + ret = fd_msg_avp_setvalue (avpch1, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); + ogs_assert(ret == 0); + + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); + + /* Set Media-Component-Description #2 */ + ret = fd_msg_avp_new(ogs_diam_rx_media_component_description, 0, &avp); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_media_component_number, 0, &avpch1); + ogs_assert(ret == 0); + val.i32 = 2; + ret = fd_msg_avp_setvalue (avpch1, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); + ogs_assert(ret == 0); + + /* Set Media-Sub-Component #1 */ + ret = fd_msg_avp_new(ogs_diam_rx_media_sub_component, 0, &avpch1); + + ret = fd_msg_avp_new(ogs_diam_rx_flow_number, 0, &avpch2); + ogs_assert(ret == 0); + val.i32 = 2; + ret = fd_msg_avp_setvalue (avpch2, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avpch1, MSG_BRW_LAST_CHILD, avpch2); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_flow_description, 0, &avpch2); + ogs_assert(ret == 0); + #define TEST_OGS_DIAM_RX_FLOW_DESC9 \ + "permit out 17 from 45.45.0.3 60010 to 45.45.0.5 60010" + val.os.data = (uint8_t *)TEST_OGS_DIAM_RX_FLOW_DESC9; + val.os.len = strlen(TEST_OGS_DIAM_RX_FLOW_DESC9); + ret = fd_msg_avp_setvalue (avpch2, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avpch1, MSG_BRW_LAST_CHILD, avpch2); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_flow_description, 0, &avpch2); + ogs_assert(ret == 0); + #define TEST_OGS_DIAM_RX_FLOW_DESC10 \ + "permit in 17 from 45.45.0.5 60010 to 45.45.0.3 60010" + val.os.data = (uint8_t *)TEST_OGS_DIAM_RX_FLOW_DESC10; + val.os.len = strlen(TEST_OGS_DIAM_RX_FLOW_DESC10); + ret = fd_msg_avp_setvalue (avpch2, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avpch1, MSG_BRW_LAST_CHILD, avpch2); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_flow_description, 0, &avpch2); + ogs_assert(ret == 0); + #define TEST_OGS_DIAM_RX_FLOW_DESC11 \ + "permit out 17 from 45.45.0.3 60011 to 45.45.0.5 60011" + val.os.data = (uint8_t *)TEST_OGS_DIAM_RX_FLOW_DESC11; + val.os.len = strlen(TEST_OGS_DIAM_RX_FLOW_DESC11); + ret = fd_msg_avp_setvalue (avpch2, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avpch1, MSG_BRW_LAST_CHILD, avpch2); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_flow_description, 0, &avpch2); + ogs_assert(ret == 0); + #define TEST_OGS_DIAM_RX_FLOW_DESC12 \ + "permit in 17 from 45.45.0.5 60011 to 45.45.0.3 60011" + val.os.data = (uint8_t *)TEST_OGS_DIAM_RX_FLOW_DESC12; + val.os.len = strlen(TEST_OGS_DIAM_RX_FLOW_DESC12); + ret = fd_msg_avp_setvalue (avpch2, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avpch1, MSG_BRW_LAST_CHILD, avpch2); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_flow_usage, 0, &avpch2); + ogs_assert(ret == 0); + val.i32 = OGS_DIAM_RX_FLOW_USAGE_NO_INFORMATION; + ret = fd_msg_avp_setvalue (avpch2, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avpch1, MSG_BRW_LAST_CHILD, avpch2); + ogs_assert(ret == 0); + + ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_media_type, 0, &avpch1); + ogs_assert(ret == 0); + val.i32 = OGS_DIAM_RX_MEDIA_TYPE_VIDEO; + ret = fd_msg_avp_setvalue (avpch1, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_max_requested_bandwidth_dl, 0, &avpch1); + ogs_assert(ret == 0); + val.i32 = 401000; + ret = fd_msg_avp_setvalue (avpch1, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_max_requested_bandwidth_ul, 0, &avpch1); + ogs_assert(ret == 0); + val.i32 = 401000; + ret = fd_msg_avp_setvalue (avpch1, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_rs_bandwidth, 0, &avpch1); + ogs_assert(ret == 0); + val.i32 = 600; + ret = fd_msg_avp_setvalue (avpch1, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_rr_bandwidth, 0, &avpch1); + ogs_assert(ret == 0); + val.i32 = 2000; + ret = fd_msg_avp_setvalue (avpch1, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_codec_data, 0, &avpch1); + ogs_assert(ret == 0); + #define TEST_OGS_DIAM_RX_CODEC_DATA3 \ + "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" + val.os.data = (uint8_t *)TEST_OGS_DIAM_RX_CODEC_DATA3; + val.os.len = strlen(TEST_OGS_DIAM_RX_CODEC_DATA3) + 1; + ret = fd_msg_avp_setvalue (avpch1, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_codec_data, 0, &avpch1); + ogs_assert(ret == 0); + #define TEST_OGS_DIAM_RX_CODEC_DATA4 \ + "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" + val.os.data = (uint8_t *)TEST_OGS_DIAM_RX_CODEC_DATA4; + val.os.len = strlen(TEST_OGS_DIAM_RX_CODEC_DATA4) + 1; + ret = fd_msg_avp_setvalue (avpch1, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_flow_status, 0, &avpch1); + ogs_assert(ret == 0); + val.i32 = OGS_DIAM_RX_FLOW_STATUS_ENABLED; + ret = fd_msg_avp_setvalue (avpch1, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add (avp, MSG_BRW_LAST_CHILD, avpch1); + ogs_assert(ret == 0); + + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); + + if (ipsub.family == AF_INET) { + /* Set Framed-IP-Address */ + ret = fd_msg_avp_new(ogs_diam_rx_framed_ip_address, 0, &avp); + ogs_assert(ret == 0); + val.os.data = (uint8_t*)ipsub.sub; + val.os.len = OGS_IPV4_LEN; + ret = fd_msg_avp_setvalue(avp, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); + } else if (ipsub.family == AF_INET6) { + /* Set Framed-IPv6-Prefix */ + ret = fd_msg_avp_new(ogs_diam_rx_framed_ipv6_prefix, 0, &avp); + ogs_assert(ret == 0); + memset(&paa, 0, sizeof(ogs_paa_t)); + + memcpy(paa.addr6, ipsub.sub, OGS_IPV6_LEN); + paa.pdn_type = 0x03; +#define FRAMED_IPV6_PREFIX_LENGTH 128 /* from spec document */ + paa.len = FRAMED_IPV6_PREFIX_LENGTH; + val.os.data = (uint8_t*)&paa; + val.os.len = OGS_PAA_IPV6_LEN; + ret = fd_msg_avp_setvalue(avp, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); + } + + /* Set the Specific-Action AVP */ + ret = fd_msg_avp_new(ogs_diam_rx_specific_action, 0, &avp); + ogs_assert(ret == 0); + val.i32 = OGS_DIAM_RX_SPECIFIC_ACTION_CHARGING_CORRELATION_EXCHANGE; + ret = fd_msg_avp_setvalue(avp, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_specific_action, 0, &avp); + ogs_assert(ret == 0); + val.i32 = OGS_DIAM_RX_SPECIFIC_ACTION_INDICATION_OF_LOSS_OF_BEARER; + ret = fd_msg_avp_setvalue(avp, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_specific_action, 0, &avp); + ogs_assert(ret == 0); + val.i32 = OGS_DIAM_RX_SPECIFIC_ACTION_INDICATION_OF_RECOVERY_OF_BEARER; + ret = fd_msg_avp_setvalue(avp, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_specific_action, 0, &avp); + ogs_assert(ret == 0); + val.i32 = OGS_DIAM_RX_SPECIFIC_ACTION_INDICATION_OF_RELEASE_OF_BEARER; + ret = fd_msg_avp_setvalue(avp, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_specific_action, 0, &avp); + ogs_assert(ret == 0); + val.i32 = OGS_DIAM_RX_SPECIFIC_ACTION_INDICATION_OF_ESTABLISHMENT_OF_BEARER; + ret = fd_msg_avp_setvalue(avp, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_specific_action, 0, &avp); + ogs_assert(ret == 0); + val.i32 = OGS_DIAM_RX_SPECIFIC_ACTION_IP_CAN_CHANGE; + ret = fd_msg_avp_setvalue(avp, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); + + ret = fd_msg_avp_new(ogs_diam_rx_specific_action, 0, &avp); + ogs_assert(ret == 0); + val.i32 = OGS_DIAM_RX_SPECIFIC_ACTION_ACCESS_NETWORK_INFO_REPORT; + ret = fd_msg_avp_setvalue(avp, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); + + /* Set the Auth-Grace-Period AVP */ + ret = fd_msg_avp_new(ogs_diam_auth_grace_period, 0, &avp); + ogs_assert(ret == 0); + val.i32 = 0; + ret = fd_msg_avp_setvalue(avp, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); + + /* Set the Session-Timeout AVP */ + ret = fd_msg_avp_new(ogs_diam_session_timeout, 0, &avp); + ogs_assert(ret == 0); + val.i32 = 7200; + ret = fd_msg_avp_setvalue(avp, &val); + ogs_assert(ret == 0); + ret = fd_msg_avp_add(req, MSG_BRW_LAST_CHILD, avp); + ogs_assert(ret == 0); + + ret = clock_gettime(CLOCK_REALTIME, &sess_data->ts); + ogs_assert(ret == 0); + + /* Keep a pointer to the session data for debug purpose, * in real life we would not need it */ svg = sess_data; @@ -406,6 +1138,9 @@ void pcscf_rx_send_aar(uint8_t **rx_sid, const char *ip, ogs_assert(pthread_mutex_lock(&ogs_diam_logger_self()->stats_lock) == 0); ogs_diam_logger_self()->stats.nb_sent++; ogs_assert(pthread_mutex_unlock(&ogs_diam_logger_self()->stats_lock) == 0); + + /* Free string memory */ + ogs_free(sip_uri); } static void pcscf_rx_aaa_cb(void *data, struct msg **msg) @@ -700,12 +1435,12 @@ void pcscf_rx_send_str(uint8_t *rx_sid) /* Keep a pointer to the session data for debug purpose, * in real life we would not need it */ svg = sess_data; - + /* Store this value in the session */ ret = fd_sess_state_store(pcscf_rx_reg, session, &sess_data); ogs_assert(ret == 0); ogs_assert(sess_data == NULL); - + /* Send the request */ ret = fd_msg_send(&req, pcscf_rx_sta_cb, svg); ogs_assert(ret == 0); diff --git a/tests/volte/pcscf-fd-path.h b/tests/volte/pcscf-fd-path.h index 2a42a2fad..bd48a518b 100644 --- a/tests/volte/pcscf-fd-path.h +++ b/tests/volte/pcscf-fd-path.h @@ -24,11 +24,14 @@ extern "C" { #endif +#include "ogs-diameter-rx.h" + int pcscf_fd_init(void); void pcscf_fd_final(void); -void pcscf_rx_send_aar(uint8_t **rx_sid, const char *ip, - int qos_type, int flow_presence); +void pcscf_rx_send_aar(uint8_t **rx_sid, + test_sess_t *sess, int id_type, int qos_type, int flow_type); +void pcscf_rx_send_aar2(uint8_t **rx_sid, test_sess_t *sess, int id_type); void pcscf_rx_send_str(uint8_t *rx_sid); #ifdef __cplusplus diff --git a/tests/volte/rx-test.c b/tests/volte/rx-test.c index 9d0ea466b..efb7a038b 100644 --- a/tests/volte/rx-test.c +++ b/tests/volte/rx-test.c @@ -31,7 +31,6 @@ static void test1_func(abts_case *tc, void *data) ogs_pkbuf_t *recvbuf; ogs_s1ap_message_t message; - char *ipstr = NULL; uint8_t *rx_sid = NULL; ogs_nas_5gs_mobile_identity_suci_t mobile_identity_suci; @@ -366,11 +365,8 @@ static void test1_func(abts_case *tc, void *data) ogs_pkbuf_free(recvbuf); /* Send AA-Request */ - ogs_assert(sess->ue_ip.ipv4); - ipstr = ogs_ipv4_to_string(sess->ue_ip.addr); - ogs_assert(ipstr); - pcscf_rx_send_aar(&rx_sid, ipstr, 1, 1); - ogs_free(ipstr); + pcscf_rx_send_aar(&rx_sid, sess, + OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_IMSI, 1, 1); /* Receive E-RAB Setup Request + * Activate dedicated EPS bearer context request */ @@ -407,7 +403,8 @@ static void test1_func(abts_case *tc, void *data) ogs_pkbuf_free(recvbuf); /* Send AA-Request without Flow */ - pcscf_rx_send_aar(&rx_sid, ipstr, 2, 1); + pcscf_rx_send_aar(&rx_sid, sess, + OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_IMSI, 2, 1); /* Receive E-RAB Modify Request + * Modify EPS bearer context request */ @@ -623,7 +620,6 @@ static void test2_func(abts_case *tc, void *data) ogs_pkbuf_t *recvbuf; ogs_s1ap_message_t message; - char *ipstr = NULL; uint8_t *rx_sid = NULL; ogs_nas_5gs_mobile_identity_suci_t mobile_identity_suci; @@ -976,11 +972,8 @@ static void test2_func(abts_case *tc, void *data) ABTS_INT_EQUAL(tc, OGS_OK, rv); /* Send AA-Request */ - ogs_assert(sess->ue_ip.ipv4); - ipstr = ogs_ipv4_to_string(sess->ue_ip.addr); - ogs_assert(ipstr); - pcscf_rx_send_aar(&rx_sid, ipstr, 0, 1); - ogs_free(ipstr); + pcscf_rx_send_aar(&rx_sid, sess, + OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_IMSI, 0, 1); /* Receive downlink NAS transport + * Modify EPS bearer context request */ diff --git a/tests/volte/video-test.c b/tests/volte/video-test.c new file mode 100644 index 000000000..7bd2cbc0b --- /dev/null +++ b/tests/volte/video-test.c @@ -0,0 +1,1259 @@ +/* + * 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 "test-common.h" +#include "pcscf-fd-path.h" + +static void test1_func(abts_case *tc, void *data) +{ + int rv; + ogs_socknode_t *s1ap; + ogs_socknode_t *gtpu; + ogs_pkbuf_t *emmbuf; + ogs_pkbuf_t *esmbuf; + ogs_pkbuf_t *sendbuf; + ogs_pkbuf_t *recvbuf; + ogs_s1ap_message_t message; + + char *ipstr = NULL; + uint8_t *rx_sid = NULL; + + ogs_nas_5gs_mobile_identity_suci_t mobile_identity_suci; + test_ue_t *test_ue = NULL; + test_sess_t *sess = NULL; + test_bearer_t *bearer = NULL; + + const char *_k_string = "465b5ce8b199b49faa5f0a2ee238a6bc"; + uint8_t k[OGS_KEY_LEN]; + const char *_opc_string = "e8ed289deba952e4283b54e88e6183ca"; + uint8_t opc[OGS_KEY_LEN]; + + mongoc_collection_t *collection = NULL; + bson_t *doc = NULL; + int64_t count = 0; + bson_error_t error; + const char *json = + "{" + "\"_id\" : { \"$oid\" : \"310014158b8861d7605378c6\" }, " + "\"imsi\" : \"001010123456819\", " + "\"pdn\" : [" + "{" + "\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd32\" }," + "\"apn\" : \"internet\"," + "\"qos\" : {" + "\"qci\" : 9," + "\"arp\" : {" + "\"priority_level\" : 8," + "\"pre_emption_vulnerability\" : 1," + "\"pre_emption_capability\" : 1" + "}" + "}," + "\"type\" : 2" + "}," + "{" + "\"_id\" : { \"$oid\" : \"310014158b8861d7605378c7\" }, " + "\"apn\" : \"ims\", " + "\"pcc_rule\" : [" + "{" + "\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd2d\" }," + "\"qos\" : {" + "\"qci\" : 1," + "\"gbr\" : {" + "\"downlink\" : { \"$numberLong\" : \"82\" }," + "\"uplink\" : { \"$numberLong\" : \"82\" }" + "}," + "\"mbr\" : {" + "\"downlink\" : { \"$numberLong\" : \"82\" }," + "\"uplink\" : { \"$numberLong\" : \"82\" }" + "}," + "\"arp\" : {" + "\"priority_level\" : 2," + "\"pre_emption_vulnerability\" : 0," + "\"pre_emption_capability\" : 0 }" + "}" + "}," + "{" + "\"_id\" : { \"$oid\" : \"599eb929c850caabcbfdcd4d\" }," + "\"qos\" : {" + "\"qci\" : 2," + "\"gbr\" : {" + "\"downlink\" : { \"$numberLong\" : \"802\" }," + "\"uplink\" : { \"$numberLong\" : \"802\" }" + "}," + "\"mbr\" : {" + "\"downlink\" : { \"$numberLong\" : \"802\" }," + "\"uplink\" : { \"$numberLong\" : \"802\" }" + "}," + "\"arp\" : {" + "\"priority_level\" : 4," + "\"pre_emption_vulnerability\" : 0," + "\"pre_emption_capability\" : 0 }" + "}" + "}" + "]," + "\"ambr\" : {" + "\"uplink\" : { \"$numberLong\" : \"1000000\" }, " + "\"downlink\" : { \"$numberLong\" : \"1000000\" } " + "}," + "\"qos\" : { " + "\"qci\" : 6, " + "\"arp\" : { " + "\"priority_level\" : 6," + "\"pre_emption_vulnerability\" : 1, " + "\"pre_emption_capability\" : 1" + "} " + "}, " + "\"type\" : 2" + "}" + "]," + "\"ambr\" : { " + "\"uplink\" : { \"$numberLong\" : \"1000000\" }, " + "\"downlink\" : { \"$numberLong\" : \"1000000\" } " + "}," + "\"subscribed_rau_tau_timer\" : 12," + "\"network_access_mode\" : 2, " + "\"subscriber_status\" : 0, " + "\"access_restriction_data\" : 32, " + "\"security\" : { " + "\"k\" : \"465B5CE8 B199B49F AA5F0A2E E238A6BC\", " + "\"opc\" : \"E8ED289D EBA952E4 283B54E8 8E6183CA\", " + "\"amf\" : \"8000\", " + "\"sqn\" : { \"$numberLong\" : \"64\" } " + "}, " + "\"__v\" : 0 " + "}"; + + /* 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] = 0x10; + mobile_identity_suci.scheme_output[1] = 0x32; + mobile_identity_suci.scheme_output[2] = 0x54; + mobile_identity_suci.scheme_output[3] = 0x86; + mobile_identity_suci.scheme_output[4] = 0x91; + + test_ue = test_ue_add_by_suci(&mobile_identity_suci, 13); + ogs_assert(test_ue); + + test_ue->e_cgi.cell_id = 0x1079baf; + test_ue->nas.ksi = 0; + test_ue->nas.value = OGS_NAS_ATTACH_TYPE_COMBINED_EPS_IMSI_ATTACH; + + OGS_HEX(_k_string, strlen(_k_string), test_ue->k); + OGS_HEX(_opc_string, strlen(_opc_string), test_ue->opc); + + sess = test_sess_add_by_apn(test_ue, "internet"); + ogs_assert(sess); + + /* eNB connects to MME */ + s1ap = tests1ap_client(AF_INET); + ABTS_PTR_NOTNULL(tc, s1ap); + + /* eNB connects to SGW */ + gtpu = test_gtpu_server(1, AF_INET); + ABTS_PTR_NOTNULL(tc, gtpu); + + /* Send S1-Setup Reqeust */ + sendbuf = test_s1ap_build_s1_setup_request( + S1AP_ENB_ID_PR_macroENB_ID, 0x54f64); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive S1-Setup Response */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(NULL, recvbuf); + + /********** Insert Subscriber in Database */ + collection = mongoc_client_get_collection( + ogs_mongoc()->client, ogs_mongoc()->name, "subscribers"); + ABTS_PTR_NOTNULL(tc, collection); + doc = BCON_NEW("imsi", BCON_UTF8(test_ue->imsi)); + ABTS_PTR_NOTNULL(tc, doc); + + count = mongoc_collection_count ( + collection, MONGOC_QUERY_NONE, doc, 0, 0, NULL, &error); + if (count) { + ABTS_TRUE(tc, mongoc_collection_remove(collection, + MONGOC_REMOVE_SINGLE_REMOVE, doc, NULL, &error)) + } + bson_destroy(doc); + + doc = bson_new_from_json((const uint8_t *)json, -1, &error);; + ABTS_PTR_NOTNULL(tc, doc); + ABTS_TRUE(tc, mongoc_collection_insert(collection, + MONGOC_INSERT_NONE, doc, NULL, &error)); + bson_destroy(doc); + + doc = BCON_NEW("imsi", BCON_UTF8(test_ue->imsi)); + ABTS_PTR_NOTNULL(tc, doc); + do { + count = mongoc_collection_count ( + collection, MONGOC_QUERY_NONE, doc, 0, 0, NULL, &error); + } while (count == 0); + bson_destroy(doc); + + collection = mongoc_client_get_collection( + ogs_mongoc()->client, ogs_mongoc()->name, "subscribers"); + ABTS_PTR_NOTNULL(tc, collection); + + /* Send Attach Request */ + memset(&sess->pdn_connectivity_param, + 0, sizeof(sess->pdn_connectivity_param)); + sess->pdn_connectivity_param.eit = 1; + esmbuf = testesm_build_pdn_connectivity_request(sess); + ABTS_PTR_NOTNULL(tc, esmbuf); + + memset(&test_ue->attach_request_param, + 0, sizeof(test_ue->attach_request_param)); + test_ue->attach_request_param.integrity_protected = 1; + test_ue->attach_request_param.drx_parameter = 1; + test_ue->attach_request_param.ms_network_capability = 1; + test_ue->attach_request_param.tmsi_status = 1; + test_ue->attach_request_param.mobile_station_classmark_2 = 1; + test_ue->attach_request_param.ue_usage_setting = 1; + emmbuf = testemm_build_attach_request(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, emmbuf); + + memset(&test_ue->initial_ue_param, 0, sizeof(test_ue->initial_ue_param)); + sendbuf = test_s1ap_build_initial_ue_message( + test_ue, emmbuf, S1AP_RRC_Establishment_Cause_mo_Signalling, false); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Authentication Request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send Authentication response */ + emmbuf = testemm_build_authentication_response(test_ue); + ABTS_PTR_NOTNULL(tc, emmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, emmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Security mode Command */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send Security mode complete */ + test_ue->mobile_identity_imeisv_presence = true; + emmbuf = testemm_build_security_mode_complete(test_ue); + ABTS_PTR_NOTNULL(tc, emmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, emmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive ESM Information Request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send ESM Information Response */ + sess->esm_information_param.pco = 1; + esmbuf = testesm_build_esm_information_response(sess); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive Initial Context Setup Request + + * Attach Accept + + * Activate Default Bearer Context Request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send UE Capability Info Indication */ + sendbuf = tests1ap_build_ue_radio_capability_info_indication(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Initial Context Setup Response */ + sendbuf = test_s1ap_build_initial_context_setup_response(test_ue); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Attach Complete + Activate default EPS bearer cotext accept */ + test_ue->nr_cgi.cell_id = 0x1234502; + bearer = test_bearer_find_by_ue_ebi(test_ue, 5); + ogs_assert(bearer); + esmbuf = testesm_build_activate_default_eps_bearer_context_accept( + bearer, false); + ABTS_PTR_NOTNULL(tc, esmbuf); + emmbuf = testemm_build_attach_complete(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, emmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, emmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive EMM information */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send GTP-U ICMP Packet */ + rv = test_gtpu_send_ping(gtpu, bearer, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = test_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send PDN Connectivity Request */ + sess = test_sess_add_by_apn(test_ue, "ims"); + ogs_assert(sess); + sess->pti = 5; + + sess->pdn_connectivity_param.integrity_protected = 1; + sess->pdn_connectivity_param.ciphered = 1; + sess->pdn_connectivity_param.apn = 1; + sess->pdn_connectivity_param.pco = 1; + esmbuf = testesm_build_pdn_connectivity_request(sess); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive E-RAB Setup Request + + * Activate default EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send E-RAB Setup Response */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 6); + ogs_assert(bearer); + sendbuf = test_s1ap_build_e_rab_setup_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Activate default EPS bearer context accept */ + esmbuf = testesm_build_activate_default_eps_bearer_context_accept( + bearer, true); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send GTP-U ICMP Packet */ + rv = test_gtpu_send_ping(gtpu, bearer, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = test_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send AA-Request */ + rx_sid = NULL; + pcscf_rx_send_aar2(&rx_sid, sess, + OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_SIP_URI); + + /* Receive E-RAB Setup Request + + * Activate dedicated EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Receive E-RAB Setup Request + + * Activate dedicated EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send E-RAB Setup Response */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 7); + ogs_assert(bearer); + sendbuf = test_s1ap_build_e_rab_setup_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Activate dedicated EPS bearer context accept */ + esmbuf = testesm_build_activate_dedicated_eps_bearer_context_accept(bearer); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send E-RAB Setup Response */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 8); + ogs_assert(bearer); + sendbuf = test_s1ap_build_e_rab_setup_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Activate dedicated EPS bearer context accept */ + esmbuf = testesm_build_activate_dedicated_eps_bearer_context_accept(bearer); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* DELAY is needed in dedicated EPS bearer */ + ogs_msleep(100); + + /* Send GTP-U ICMP Packet */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 7); + ogs_assert(bearer); + rv = test_gtpu_send_ping(gtpu, bearer, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = test_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send GTP-U ICMP Packet */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 8); + ogs_assert(bearer); + rv = test_gtpu_send_ping(gtpu, bearer, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = test_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send Bearer resource modification request */ + sess->pti = 10; + bearer = test_bearer_find_by_ue_ebi(test_ue, 7); + ogs_assert(bearer); + esmbuf = testesm_build_bearer_resource_modification_request( + bearer, OGS_GTP_TFT_CODE_DELETE_PACKET_FILTERS_FROM_EXISTING, 0, + ESM_CAUSE_REGULAR_DEACTIVATION); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive E-RAB Release Command + + * Dectivate EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send E-RAB Release Response */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 7); + ogs_assert(bearer); + sendbuf = test_s1ap_build_e_rab_release_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Deactivate EPS bearer context accept */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 7); + ogs_assert(bearer); + esmbuf = testesm_build_deactivate_eps_bearer_context_accept(bearer); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* DELAY is needed before Session-Termination-Request */ + ogs_msleep(100); + + /* Send Session-Termination-Request */ + pcscf_rx_send_str(rx_sid); + + /* Receive E-RAB Release Command + + * Dectivate EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send E-RAB Release Response */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 8); + ogs_assert(bearer); + sendbuf = test_s1ap_build_e_rab_release_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Deactivate EPS bearer context accept */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 8); + ogs_assert(bearer); + esmbuf = testesm_build_deactivate_eps_bearer_context_accept(bearer); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send AA-Request */ + rx_sid = NULL; + pcscf_rx_send_aar2(&rx_sid, sess, + OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_SIP_URI); + + /* Receive E-RAB Setup Request + + * Activate dedicated EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Receive E-RAB Setup Request + + * Activate dedicated EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send E-RAB Setup Response */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 9); + ogs_assert(bearer); + sendbuf = test_s1ap_build_e_rab_setup_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Activate dedicated EPS bearer context accept */ + esmbuf = testesm_build_activate_dedicated_eps_bearer_context_accept(bearer); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send E-RAB Setup Response */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 10); + ogs_assert(bearer); + sendbuf = test_s1ap_build_e_rab_setup_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Activate dedicated EPS bearer context accept */ + esmbuf = testesm_build_activate_dedicated_eps_bearer_context_accept(bearer); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* DELAY is needed in dedicated EPS bearer */ + ogs_msleep(100); + + /* Send GTP-U ICMP Packet */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 9); + ogs_assert(bearer); + rv = test_gtpu_send_ping(gtpu, bearer, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = test_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send GTP-U ICMP Packet */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 10); + ogs_assert(bearer); + rv = test_gtpu_send_ping(gtpu, bearer, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = test_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send Bearer resource modification request */ + sess->pti = 20; + bearer = test_bearer_find_by_ue_ebi(test_ue, 9); + ogs_assert(bearer); + esmbuf = testesm_build_bearer_resource_modification_request( + bearer, OGS_GTP_TFT_CODE_DELETE_PACKET_FILTERS_FROM_EXISTING, 0, + ESM_CAUSE_REGULAR_DEACTIVATION); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive E-RAB Release Command + + * Dectivate EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send E-RAB Release Response */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 9); + ogs_assert(bearer); + sendbuf = test_s1ap_build_e_rab_release_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Deactivate EPS bearer context accept */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 9); + ogs_assert(bearer); + esmbuf = testesm_build_deactivate_eps_bearer_context_accept(bearer); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* DELAY is needed before Session-Termination-Request */ + ogs_msleep(100); + + /* Send Session-Termination-Request */ + pcscf_rx_send_str(rx_sid); + + /* Receive E-RAB Release Command + + * Dectivate EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send E-RAB Release Response */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 10); + ogs_assert(bearer); + sendbuf = test_s1ap_build_e_rab_release_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Deactivate EPS bearer context accept */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 10); + ogs_assert(bearer); + esmbuf = testesm_build_deactivate_eps_bearer_context_accept(bearer); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send AA-Request */ + rx_sid = NULL; + pcscf_rx_send_aar2(&rx_sid, sess, + OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_SIP_URI); + + /* Receive E-RAB Setup Request + + * Activate dedicated EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Receive E-RAB Setup Request + + * Activate dedicated EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send E-RAB Setup Response */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 11); + ogs_assert(bearer); + sendbuf = test_s1ap_build_e_rab_setup_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Activate dedicated EPS bearer context accept */ + esmbuf = testesm_build_activate_dedicated_eps_bearer_context_accept(bearer); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send E-RAB Setup Response */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 12); + ogs_assert(bearer); + sendbuf = test_s1ap_build_e_rab_setup_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Activate dedicated EPS bearer context accept */ + esmbuf = testesm_build_activate_dedicated_eps_bearer_context_accept(bearer); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* DELAY is needed in dedicated EPS bearer */ + ogs_msleep(100); + + /* Send GTP-U ICMP Packet */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 11); + ogs_assert(bearer); + rv = test_gtpu_send_ping(gtpu, bearer, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = test_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send GTP-U ICMP Packet */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 12); + ogs_assert(bearer); + rv = test_gtpu_send_ping(gtpu, bearer, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = test_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send Bearer resource modification request */ + sess->pti = 30; + bearer = test_bearer_find_by_ue_ebi(test_ue, 11); + ogs_assert(bearer); + esmbuf = testesm_build_bearer_resource_modification_request( + bearer, OGS_GTP_TFT_CODE_DELETE_PACKET_FILTERS_FROM_EXISTING, 0, + ESM_CAUSE_REGULAR_DEACTIVATION); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive E-RAB Release Command + + * Dectivate EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send E-RAB Release Response */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 11); + ogs_assert(bearer); + sendbuf = test_s1ap_build_e_rab_release_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Deactivate EPS bearer context accept */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 11); + ogs_assert(bearer); + esmbuf = testesm_build_deactivate_eps_bearer_context_accept(bearer); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* DELAY is needed before Session-Termination-Request */ + ogs_msleep(100); + + /* Send Session-Termination-Request */ + pcscf_rx_send_str(rx_sid); + + /* Receive E-RAB Release Command + + * Dectivate EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send E-RAB Release Response */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 12); + ogs_assert(bearer); + sendbuf = test_s1ap_build_e_rab_release_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Deactivate EPS bearer context accept */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 12); + ogs_assert(bearer); + esmbuf = testesm_build_deactivate_eps_bearer_context_accept(bearer); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send AA-Request */ + rx_sid = NULL; + pcscf_rx_send_aar2(&rx_sid, sess, + OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_SIP_URI); + + /* Receive E-RAB Setup Request + + * Activate dedicated EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Receive E-RAB Setup Request + + * Activate dedicated EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send E-RAB Setup Response */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 13); + ogs_assert(bearer); + sendbuf = test_s1ap_build_e_rab_setup_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Activate dedicated EPS bearer context accept */ + esmbuf = testesm_build_activate_dedicated_eps_bearer_context_accept(bearer); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send E-RAB Setup Response */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 14); + ogs_assert(bearer); + sendbuf = test_s1ap_build_e_rab_setup_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Activate dedicated EPS bearer context accept */ + esmbuf = testesm_build_activate_dedicated_eps_bearer_context_accept(bearer); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* DELAY is needed in dedicated EPS bearer */ + ogs_msleep(100); + + /* Send GTP-U ICMP Packet */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 13); + ogs_assert(bearer); + rv = test_gtpu_send_ping(gtpu, bearer, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = test_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send GTP-U ICMP Packet */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 14); + ogs_assert(bearer); + rv = test_gtpu_send_ping(gtpu, bearer, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = test_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send Bearer resource modification request */ + sess->pti = 40; + bearer = test_bearer_find_by_ue_ebi(test_ue, 13); + ogs_assert(bearer); + esmbuf = testesm_build_bearer_resource_modification_request( + bearer, OGS_GTP_TFT_CODE_DELETE_PACKET_FILTERS_FROM_EXISTING, 0, + ESM_CAUSE_REGULAR_DEACTIVATION); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive E-RAB Release Command + + * Dectivate EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send E-RAB Release Response */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 13); + ogs_assert(bearer); + sendbuf = test_s1ap_build_e_rab_release_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Deactivate EPS bearer context accept */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 13); + ogs_assert(bearer); + esmbuf = testesm_build_deactivate_eps_bearer_context_accept(bearer); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* DELAY is needed before Session-Termination-Request */ + ogs_msleep(100); + + /* Send Session-Termination-Request */ + pcscf_rx_send_str(rx_sid); + + /* Receive E-RAB Release Command + + * Dectivate EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send E-RAB Release Response */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 14); + ogs_assert(bearer); + sendbuf = test_s1ap_build_e_rab_release_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Deactivate EPS bearer context accept */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 14); + ogs_assert(bearer); + esmbuf = testesm_build_deactivate_eps_bearer_context_accept(bearer); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send AA-Request */ + rx_sid = NULL; + pcscf_rx_send_aar2(&rx_sid, sess, + OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_SIP_URI); + + /* Receive E-RAB Setup Request + + * Activate dedicated EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Receive E-RAB Setup Request + + * Activate dedicated EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send E-RAB Setup Response */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 15); + ogs_assert(bearer); + sendbuf = test_s1ap_build_e_rab_setup_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Activate dedicated EPS bearer context accept */ + esmbuf = testesm_build_activate_dedicated_eps_bearer_context_accept(bearer); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send E-RAB Setup Response */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 7); + ogs_assert(bearer); + sendbuf = test_s1ap_build_e_rab_setup_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Activate dedicated EPS bearer context accept */ + esmbuf = testesm_build_activate_dedicated_eps_bearer_context_accept(bearer); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* DELAY is needed in dedicated EPS bearer */ + ogs_msleep(100); + + /* Send GTP-U ICMP Packet */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 15); + ogs_assert(bearer); + rv = test_gtpu_send_ping(gtpu, bearer, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = test_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send GTP-U ICMP Packet */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 7); + ogs_assert(bearer); + rv = test_gtpu_send_ping(gtpu, bearer, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = test_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send Bearer resource modification request */ + sess->pti = 50; + bearer = test_bearer_find_by_ue_ebi(test_ue, 15); + ogs_assert(bearer); + esmbuf = testesm_build_bearer_resource_modification_request( + bearer, OGS_GTP_TFT_CODE_DELETE_PACKET_FILTERS_FROM_EXISTING, 0, + ESM_CAUSE_REGULAR_DEACTIVATION); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive E-RAB Release Command + + * Dectivate EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send E-RAB Release Response */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 15); + ogs_assert(bearer); + sendbuf = test_s1ap_build_e_rab_release_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Deactivate EPS bearer context accept */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 15); + ogs_assert(bearer); + esmbuf = testesm_build_deactivate_eps_bearer_context_accept(bearer); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* DELAY is needed before Session-Termination-Request */ + ogs_msleep(100); + + /* Send Session-Termination-Request */ + pcscf_rx_send_str(rx_sid); + + /* Receive E-RAB Release Command + + * Dectivate EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send E-RAB Release Response */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 7); + ogs_assert(bearer); + sendbuf = test_s1ap_build_e_rab_release_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Deactivate EPS bearer context accept */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 7); + ogs_assert(bearer); + esmbuf = testesm_build_deactivate_eps_bearer_context_accept(bearer); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send AA-Request */ + rx_sid = NULL; + pcscf_rx_send_aar2(&rx_sid, sess, + OGS_DIAM_RX_SUBSCRIPTION_ID_TYPE_END_USER_SIP_URI); + + /* Receive E-RAB Setup Request + + * Activate dedicated EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Receive E-RAB Setup Request + + * Activate dedicated EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send E-RAB Setup Response */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 8); + ogs_assert(bearer); + sendbuf = test_s1ap_build_e_rab_setup_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Activate dedicated EPS bearer context accept */ + esmbuf = testesm_build_activate_dedicated_eps_bearer_context_accept(bearer); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send E-RAB Setup Response */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 9); + ogs_assert(bearer); + sendbuf = test_s1ap_build_e_rab_setup_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Activate dedicated EPS bearer context accept */ + esmbuf = testesm_build_activate_dedicated_eps_bearer_context_accept(bearer); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* DELAY is needed in dedicated EPS bearer */ + ogs_msleep(100); + + /* Send GTP-U ICMP Packet */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 8); + ogs_assert(bearer); + rv = test_gtpu_send_ping(gtpu, bearer, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = test_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send GTP-U ICMP Packet */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 9); + ogs_assert(bearer); + rv = test_gtpu_send_ping(gtpu, bearer, TEST_PING_IPV4); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive GTP-U ICMP Packet */ + recvbuf = test_gtpu_read(gtpu); + ABTS_PTR_NOTNULL(tc, recvbuf); + ogs_pkbuf_free(recvbuf); + + /* Send Bearer resource modification request */ + sess->pti = 55; + bearer = test_bearer_find_by_ue_ebi(test_ue, 8); + ogs_assert(bearer); + esmbuf = testesm_build_bearer_resource_modification_request( + bearer, OGS_GTP_TFT_CODE_DELETE_PACKET_FILTERS_FROM_EXISTING, 0, + ESM_CAUSE_REGULAR_DEACTIVATION); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Receive E-RAB Release Command + + * Dectivate EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send E-RAB Release Response */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 8); + ogs_assert(bearer); + sendbuf = test_s1ap_build_e_rab_release_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Deactivate EPS bearer context accept */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 8); + ogs_assert(bearer); + esmbuf = testesm_build_deactivate_eps_bearer_context_accept(bearer); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* DELAY is needed before Session-Termination-Request */ + ogs_msleep(100); + + /* Send Session-Termination-Request */ + pcscf_rx_send_str(rx_sid); + + /* Receive E-RAB Release Command + + * Dectivate EPS bearer context request */ + recvbuf = testenb_s1ap_read(s1ap); + ABTS_PTR_NOTNULL(tc, recvbuf); + tests1ap_recv(test_ue, recvbuf); + + /* Send E-RAB Release Response */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 9); + ogs_assert(bearer); + sendbuf = test_s1ap_build_e_rab_release_response(bearer); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + /* Send Deactivate EPS bearer context accept */ + bearer = test_bearer_find_by_ue_ebi(test_ue, 9); + ogs_assert(bearer); + esmbuf = testesm_build_deactivate_eps_bearer_context_accept(bearer); + ABTS_PTR_NOTNULL(tc, esmbuf); + sendbuf = test_s1ap_build_uplink_nas_transport(test_ue, esmbuf); + ABTS_PTR_NOTNULL(tc, sendbuf); + rv = testenb_s1ap_send(s1ap, sendbuf); + ABTS_INT_EQUAL(tc, OGS_OK, rv); + + ogs_msleep(300); + + /********** Remove Subscriber in Database */ + doc = BCON_NEW("imsi", BCON_UTF8(test_ue->imsi)); + ABTS_PTR_NOTNULL(tc, doc); + ABTS_TRUE(tc, mongoc_collection_remove(collection, + MONGOC_REMOVE_SINGLE_REMOVE, doc, NULL, &error)) + bson_destroy(doc); + + mongoc_collection_destroy(collection); + + /* eNB disonncect from MME */ + testenb_s1ap_close(s1ap); + + /* eNB disonncect from SGW */ + test_gtpu_close(gtpu); + + 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; +}