diff --git a/configs/open5gs/pcrf.yaml.in b/configs/open5gs/pcrf.yaml.in index 5b9349c41..67bb14a1e 100644 --- a/configs/open5gs/pcrf.yaml.in +++ b/configs/open5gs/pcrf.yaml.in @@ -41,7 +41,7 @@ pcrf: # prefer_ipv4: true # # o Legacy support for pre-release LTE 11 devices to do calling -# - Replace IPv4/v6 local addr field in AAR Media-Subcomponent AVP by any +# - Replace IPv4/v6 local addr field in AAR Media-Subcomponent AVP by any and port # no_ipv4v6_local_addr_in_packet_filter: true # parameter: diff --git a/src/pcrf/pcrf-rx-path.c b/src/pcrf/pcrf-rx-path.c index 5d07bc1d3..b14cb5998 100644 --- a/src/pcrf/pcrf-rx-path.c +++ b/src/pcrf/pcrf-rx-path.c @@ -93,7 +93,7 @@ static int pcrf_rx_aar_cb( struct msg **msg, struct avp *avp, int rv; int ret; int len; - char *from_str, *to_str, *rx_flow; + char *from_str, *to_str, *rx_flow, *to_port, *to_ip, *from_ip, *from_port; struct msg *ans, *qry; struct avp *avpch1, *avpch2, *avpch3; @@ -285,7 +285,7 @@ static int pcrf_rx_aar_cb( struct msg **msg, struct avp *avp, /* IE (IPV4-local-addr field ) is not supported on * the LTE pre release-11 UEs. In order for the call * to work the local address in packet filter must - * be replaced by any. + * be replaced by 'any local port'. */ if (ogs_app()-> parameter.no_ipv4v6_local_addr_in_packet_filter @@ -296,6 +296,10 @@ static int pcrf_rx_aar_cb( struct msg **msg, struct avp *avp, from_str = NULL; to_str = NULL; + to_ip = NULL; + to_port = NULL; + from_ip = NULL; + from_port = NULL; from_str = strstr(rx_flow, "from"); ogs_assert(from_str); to_str = strstr(rx_flow, "to"); @@ -304,24 +308,67 @@ static int pcrf_rx_aar_cb( struct msg **msg, struct avp *avp, if (!strncmp(rx_flow, "permit out", strlen("permit out"))) { - flow->description = ogs_malloc(len - - strlen(to_str) + strlen("to any")+1); + to_ip = strstr(to_str, " "); + if (to_ip != NULL) { + // Exclude the starting whitespace + to_ip += 1; + + to_port = strstr(to_ip, " "); + // Test for no port + if (to_port != NULL) { + flow->description = ogs_malloc(len + - strlen(to_str) + strlen("to any") + + strlen(to_port) + 1); + } else { + flow->description = ogs_malloc(len + - strlen(to_str) + strlen("to any") + 1); + } + } strncat(flow->description, rx_flow, len - strlen(to_str)); strcat(flow->description, "to any"); + if (to_port != NULL) { + strncat(flow->description, + to_port, strlen(to_port)); + } } else if (!strncmp(rx_flow, "permit in", strlen("permit in"))) { - flow->description = ogs_malloc( - len - strlen(from_str) + strlen(to_str) - + strlen("from any ")+1); + from_ip = strstr(from_str, " "); + if (from_ip != NULL) { + // Exclude the starting whitespace + from_ip += 1; + + from_port = strstr(from_ip, " "); + // Test for no port + whether from_port is at "to" + // without any from port + if (from_port != NULL && + strncmp(from_port, " to", 3)) { + flow->description = ogs_malloc( + len - strlen(from_str) + strlen(to_str) + + strlen("from any") + 1 + + (strlen(from_port) - strlen(to_str))); + } else { + flow->description = ogs_malloc( + len - strlen(from_str) + strlen(to_str) + + strlen("from any ") + 1); + } + } strncat(flow->description, rx_flow, len - strlen(from_str)); - strcat(flow->description, "from any "); + if (from_port != NULL && + strncmp(from_port, " to", 3)) { + strcat(flow->description, "from any"); + strncat(flow->description, + from_port, + strlen(from_port) - strlen(to_str)); + } else { + strcat(flow->description, "from any "); + } strncat(flow->description, to_str, strlen(to_str)); diff --git a/src/smf/binding.c b/src/smf/binding.c index 95a88000c..c1d1e5448 100644 --- a/src/smf/binding.c +++ b/src/smf/binding.c @@ -95,7 +95,7 @@ static void encode_traffic_flow_template( while (pf) { tft->pf[i].direction = pf->direction; tft->pf[i].identifier = pf->identifier - 1; - tft->pf[i].precedence = i+1; + tft->pf[i].precedence = pf->precedence; ogs_pf_content_from_ipfw_rule( pf->direction, &tft->pf[i].content, &pf->ipfw_rule); @@ -120,6 +120,9 @@ void smf_bearer_binding(smf_sess_t *sess) ogs_pkbuf_t *pkbuf = NULL; smf_bearer_t *bearer = NULL; + int total_num_of_pcc_rules = 0; + smf_bearer_t *pf_bearer = NULL; + ogs_pcc_rule_t *pcc_rule = &sess->pcc_rule[i]; int bearer_created = 0; int qos_presence = 0; @@ -240,6 +243,11 @@ void smf_bearer_binding(smf_sess_t *sess) dl_pdr->num_of_flow = 0; ul_pdr->num_of_flow = 0; + // Compute total number of PCC rules for per DNN (used to set precedence) + ogs_list_for_each(&sess->bearer_list, pf_bearer) { + total_num_of_pcc_rules += ogs_list_count(&pf_bearer->pf_list); + } + for (j = 0; j < pcc_rule->num_of_flow; j++) { ogs_flow_t *flow = &pcc_rule->flow[j]; smf_pf_t *pf = NULL; @@ -263,6 +271,7 @@ void smf_bearer_binding(smf_sess_t *sess) pf->direction = flow->direction; pf->flow_description = ogs_strdup(flow->description); + pf->precedence = total_num_of_pcc_rules + j; rv = ogs_ipfw_compile_rule( &pf->ipfw_rule, pf->flow_description); diff --git a/src/smf/context.h b/src/smf/context.h index 81b3083ed..b9fdd6da2 100644 --- a/src/smf/context.h +++ b/src/smf/context.h @@ -134,6 +134,8 @@ ED3(uint8_t spare:2;, uint8_t direction:2;, uint8_t identifier:4;) + uint8_t precedence; + uint8_t *identifier_node; /* Pool-Node for Identifier */ ogs_ipfw_rule_t ipfw_rule;