diff --git a/lib/core/ogs-list.h b/lib/core/ogs-list.h index 14071de29..6d5a694b7 100644 --- a/lib/core/ogs-list.h +++ b/lib/core/ogs-list.h @@ -64,15 +64,30 @@ static ogs_inline void *ogs_list_prev(void *lnode) return node->prev; } +#define ogs_list_entry(ptr, type, member) ogs_container_of(ptr, type, member) + #define ogs_list_for_each(list, node) \ for (node = ogs_list_first(list); (node); \ node = ogs_list_next(node)) +#define ogs_list_for_each_entry(list, node, member) \ + for (node = ogs_list_entry(ogs_list_first(list), typeof(*node), member); \ + (&node->member); \ + node = ogs_list_entry( \ + ogs_list_next(&node->member), typeof(*node), member)) + #define ogs_list_for_each_safe(list, n, node) \ for (node = ogs_list_first(list); \ (node) && (n = ogs_list_next(node), 1); \ node = n) +#define ogs_list_for_each_entry_safe(list, n, node, member) \ + for (node = ogs_list_entry(ogs_list_first(list), typeof(*node), member); \ + (&node->member) && \ + (n = ogs_list_entry( \ + ogs_list_next(&node->member), typeof(*node), member), 1); \ + node = n) + static ogs_inline void ogs_list_prepend(ogs_list_t *list, void *lnode) { ogs_list_t *node = lnode; diff --git a/src/smf/binding.c b/src/smf/binding.c index 0e3b95bed..f1cac5e72 100644 --- a/src/smf/binding.c +++ b/src/smf/binding.c @@ -82,13 +82,13 @@ static void bearer_timeout(ogs_gtp_xact_t *xact, void *data) * TFT : Local REMOTE */ static void encode_traffic_flow_template( - ogs_gtp_tft_t *tft, ogs_list_t *pf_list, uint8_t tft_operation_code) + ogs_gtp_tft_t *tft, smf_bearer_t *bearer, uint8_t tft_operation_code) { int i; smf_pf_t *pf = NULL; ogs_assert(tft); - ogs_assert(pf_list); + ogs_assert(bearer); memset(tft, 0, sizeof(*tft)); tft->code = tft_operation_code; @@ -96,11 +96,11 @@ static void encode_traffic_flow_template( i = 0; if (tft_operation_code != OGS_GTP_TFT_CODE_DELETE_EXISTING_TFT && tft_operation_code != OGS_GTP_TFT_CODE_NO_TFT_OPERATION) { - pf = ogs_list_first(pf_list); - while (pf) { + ogs_list_for_each_entry(&bearer->pf_to_add_list, pf, to_add_node) { tft->pf[i].identifier = pf->identifier - 1; - /* Deletion of packet filters from existing requires only the identifier */ + /* Deletion of packet filters + * from existing requires only the identifier */ if (tft_operation_code != OGS_GTP_TFT_CODE_DELETE_PACKET_FILTERS_FROM_EXISTING) { @@ -112,8 +112,6 @@ static void encode_traffic_flow_template( } i++; - - pf = ogs_list_next(pf); } } tft->num_of_packet_filter = i; @@ -145,9 +143,6 @@ void smf_bearer_binding(smf_sess_t *sess) if (pcc_rule->type == OGS_PCC_RULE_TYPE_INSTALL) { ogs_pfcp_pdr_t *dl_pdr = NULL, *ul_pdr = NULL; - ogs_list_t pf_to_add_list; - ogs_list_init(&pf_to_add_list); - bearer = smf_bearer_find_by_pcc_rule_name(sess, pcc_rule->name); if (!bearer) { if (pcc_rule->num_of_flow == 0) { @@ -248,6 +243,8 @@ void smf_bearer_binding(smf_sess_t *sess) dl_pdr->num_of_flow = 0; ul_pdr->num_of_flow = 0; + ogs_list_init(&bearer->pf_to_add_list); + for (j = 0; j < pcc_rule->num_of_flow; j++) { ogs_flow_t *flow = &pcc_rule->flow[j]; smf_pf_t *pf = NULL; @@ -255,6 +252,11 @@ void smf_bearer_binding(smf_sess_t *sess) ogs_expect_or_return(flow); ogs_expect_or_return(flow->description); + if (smf_pf_find_by_flow( + bearer, flow->direction, flow->description) != NULL) { + continue; + } + if (flow->direction == OGS_FLOW_DOWNLINK_ONLY) { dl_pdr->flow_description[dl_pdr->num_of_flow++] = flow->description; @@ -266,11 +268,6 @@ void smf_bearer_binding(smf_sess_t *sess) flow->direction); } - if (smf_pf_find_by_flow( - bearer, flow->direction, flow->description) != NULL) { - continue; - } - pf = smf_pf_add(bearer); ogs_assert(pf); @@ -303,7 +300,7 @@ void smf_bearer_binding(smf_sess_t *sess) break; } - ogs_list_add(&pf_to_add_list, pf); + ogs_list_add(&bearer->pf_to_add_list, &pf->to_add_node); } if (bearer_created == 1) { @@ -339,11 +336,9 @@ void smf_bearer_binding(smf_sess_t *sess) memset(&tft, 0, sizeof tft); if (pcc_rule->num_of_flow) encode_traffic_flow_template( - &tft, &pf_to_add_list, + &tft, bearer, OGS_GTP_TFT_CODE_ADD_PACKET_FILTERS_TO_EXISTING_TFT); - ogs_list_empty(&pf_to_add_list); - memset(&h, 0, sizeof(ogs_gtp_header_t)); h.type = OGS_GTP_UPDATE_BEARER_REQUEST_TYPE; h.teid = sess->sgw_s5c_teid; @@ -416,7 +411,7 @@ void smf_gtp_send_create_bearer_request(smf_bearer_t *bearer) h.teid = sess->sgw_s5c_teid; memset(&tft, 0, sizeof tft); - encode_traffic_flow_template(&tft, &bearer->pf_list, OGS_GTP_TFT_CODE_CREATE_NEW_TFT); + encode_traffic_flow_template(&tft, bearer, OGS_GTP_TFT_CODE_CREATE_NEW_TFT); pkbuf = smf_s5c_build_create_bearer_request(h.type, bearer, &tft); ogs_expect_or_return(pkbuf); @@ -456,9 +451,6 @@ void smf_qos_flow_binding(smf_sess_t *sess, ogs_sbi_stream_t *stream) if (pcc_rule->type == OGS_PCC_RULE_TYPE_INSTALL) { ogs_pfcp_pdr_t *dl_pdr = NULL, *ul_pdr = NULL; - ogs_list_t pf_to_add_list; - ogs_list_init(&pf_to_add_list); - qos_flow = smf_qos_flow_find_by_pcc_rule_id(sess, pcc_rule->id); if (!qos_flow) { if (pcc_rule->num_of_flow == 0) { @@ -537,6 +529,8 @@ void smf_qos_flow_binding(smf_sess_t *sess, ogs_sbi_stream_t *stream) dl_pdr->num_of_flow = 0; ul_pdr->num_of_flow = 0; + ogs_list_init(&qos_flow->pf_to_add_list); + for (j = 0; j < pcc_rule->num_of_flow; j++) { ogs_flow_t *flow = &pcc_rule->flow[j]; smf_pf_t *pf = NULL; @@ -544,6 +538,11 @@ void smf_qos_flow_binding(smf_sess_t *sess, ogs_sbi_stream_t *stream) ogs_expect_or_return(flow); ogs_expect_or_return(flow->description); + if (smf_pf_find_by_flow( + qos_flow, flow->direction, flow->description) != NULL) { + continue; + } + if (flow->direction == OGS_FLOW_DOWNLINK_ONLY) { dl_pdr->flow_description[dl_pdr->num_of_flow++] = flow->description; @@ -555,11 +554,6 @@ void smf_qos_flow_binding(smf_sess_t *sess, ogs_sbi_stream_t *stream) flow->direction); } - if (smf_pf_find_by_flow( - qos_flow, flow->direction, flow->description) != NULL) { - continue; - } - pf = smf_pf_add(qos_flow); ogs_assert(pf); @@ -592,7 +586,7 @@ void smf_qos_flow_binding(smf_sess_t *sess, ogs_sbi_stream_t *stream) break; } - ogs_list_add(&pf_to_add_list, pf); + ogs_list_add(&qos_flow->pf_to_add_list, &pf->to_add_node); } if (qos_flow_created == 1) { @@ -631,11 +625,9 @@ void smf_qos_flow_binding(smf_sess_t *sess, ogs_sbi_stream_t *stream) memset(&tft, 0, sizeof tft); if (pcc_rule->num_of_flow) encode_traffic_flow_template( - &tft, &pf_to_add_list, + &tft, qos_flow, OGS_GTP_TFT_CODE_ADD_PACKET_FILTERS_TO_EXISTING_TFT); - ogs_list_empty(&pf_to_add_list); - memset(&h, 0, sizeof(ogs_gtp_header_t)); h.type = OGS_GTP_UPDATE_BEARER_REQUEST_TYPE; h.teid = sess->sgw_s5c_teid; diff --git a/src/smf/context.h b/src/smf/context.h index 826b81963..29e9b55b0 100644 --- a/src/smf/context.h +++ b/src/smf/context.h @@ -128,6 +128,7 @@ typedef struct smf_sess_s smf_sess_t; typedef struct smf_pf_s { ogs_lnode_t lnode; + ogs_lnode_t to_add_node; ED3(uint8_t spare:2;, uint8_t direction:2;, @@ -176,6 +177,7 @@ typedef struct smf_bearer_s { /* Packet Filter List */ ogs_list_t pf_list; + ogs_list_t pf_to_add_list; smf_sess_t *sess; } smf_bearer_t;