From f6439b998c4b99c9f860b8040a34f232f6b2f34e Mon Sep 17 00:00:00 2001 From: mitmitmitm Date: Wed, 18 Jan 2023 12:33:50 +0100 Subject: [PATCH] [SMF] Handle framed routes, forward them to UPF and PCF --- lib/pfcp/build.c | 8 +++++++ lib/proto/types.h | 5 +++++ src/smf/context.c | 8 +++++++ src/smf/npcf-build.c | 37 +++++++++++++++++++++++++++++++++ src/smf/npcf-handler.c | 47 ++++++++++++++++++++++++++++++++++++++++++ src/smf/nudm-handler.c | 32 ++++++++++++++++++++++++++++ 6 files changed, 137 insertions(+) diff --git a/lib/pfcp/build.c b/lib/pfcp/build.c index 723153f38..0d4f64e58 100644 --- a/lib/pfcp/build.c +++ b/lib/pfcp/build.c @@ -314,6 +314,14 @@ void ogs_pfcp_build_create_pdr( message->pdi.ue_ip_address.len = pdr->ue_ip_addr_len; } + for (j = 0; j < OGS_MAX_NUM_OF_FRAMED_ROUTES_IN_PDI; j++) { + if (!pdr->ipv4_framed_routes || !pdr->ipv4_framed_routes[j]) + break; + message->pdi.framed_route[j].presence = 1; + message->pdi.framed_route[j].data = pdr->ipv4_framed_routes[j]; + message->pdi.framed_route[j].len = strlen(pdr->ipv4_framed_routes[j]); + } + if (pdr->f_teid_len) { memcpy(&pdrbuf[i].f_teid, &pdr->f_teid, pdr->f_teid_len); pdrbuf[i].f_teid.teid = htobe32(pdr->f_teid.teid); diff --git a/lib/proto/types.h b/lib/proto/types.h index 8328b7818..f31d42838 100644 --- a/lib/proto/types.h +++ b/lib/proto/types.h @@ -453,6 +453,9 @@ typedef struct ogs_pcc_rule_s { (__pCCrULE)->num_of_flow = 0; \ } while(0) + +typedef struct OpenAPI_list_s OpenAPI_list_t; + /********************************** * PDN Structure */ typedef struct ogs_session_s { @@ -484,6 +487,8 @@ typedef struct ogs_session_s { ogs_paa_t paa; ogs_ip_t ue_ip; + OpenAPI_list_t *ipv4_framed_routes; + OpenAPI_list_t *ipv6_framed_routes; ogs_ip_t smf_ip; } ogs_session_t; diff --git a/src/smf/context.c b/src/smf/context.c index 8b8eab4e4..7ebc3d0b0 100644 --- a/src/smf/context.c +++ b/src/smf/context.c @@ -1696,6 +1696,7 @@ void smf_sess_remove(smf_sess_t *sess) int i; smf_ue_t *smf_ue = NULL; smf_event_t e; + OpenAPI_lnode_t *node; char buf1[OGS_ADDRSTRLEN]; char buf2[OGS_ADDRSTRLEN]; @@ -1760,6 +1761,13 @@ void smf_sess_remove(smf_sess_t *sess) if (sess->session.name) ogs_free(sess->session.name); + OpenAPI_list_for_each(sess->session.ipv4_framed_routes, node) + OpenAPI_frame_route_info_free(node->data); + OpenAPI_list_for_each(sess->session.ipv6_framed_routes, node) + OpenAPI_frame_route_info_free(node->data); + OpenAPI_list_free(sess->session.ipv4_framed_routes); + OpenAPI_list_free(sess->session.ipv6_framed_routes); + if (sess->upf_n3_addr) ogs_freeaddrinfo(sess->upf_n3_addr); if (sess->upf_n3_addr6) diff --git a/src/smf/npcf-build.c b/src/smf/npcf-build.c index 7e882861e..8ece2a237 100644 --- a/src/smf/npcf-build.c +++ b/src/smf/npcf-build.c @@ -107,6 +107,40 @@ ogs_sbi_request_t *smf_npcf_smpolicycontrol_build_create( } } + if (sess->session.ipv4_framed_routes) { + OpenAPI_list_t *FrameRouteList = OpenAPI_list_create(); + OpenAPI_lnode_t *node; + + OpenAPI_list_for_each(sess->session.ipv4_framed_routes, node) { + OpenAPI_frame_route_info_t *route = node->data; + if (!route) + continue; + if (!route->ipv4_mask) { + ogs_error("Invalid FrameRouteInfo"); + continue; + } + OpenAPI_list_add(FrameRouteList, ogs_strdup(route->ipv4_mask)); + } + SmPolicyContextData.ipv4_frame_route_list = FrameRouteList; + } + + if (sess->session.ipv6_framed_routes) { + OpenAPI_list_t *FrameRouteList = OpenAPI_list_create(); + OpenAPI_lnode_t *node; + + OpenAPI_list_for_each(sess->session.ipv6_framed_routes, node) { + OpenAPI_frame_route_info_t *route = node->data; + if (!route) + continue; + if (!route->ipv6_prefix) { + ogs_error("Invalid FrameRouteInfo"); + continue; + } + OpenAPI_list_add(FrameRouteList, ogs_strdup(route->ipv6_prefix)); + } + SmPolicyContextData.ipv6_frame_route_list = FrameRouteList; + } + if (OGS_SBI_FEATURES_IS_SET(sess->smpolicycontrol_features, OGS_SBI_NPCF_SMPOLICYCONTROL_DN_AUTHORIZATION)) { if (sess->session.ambr.uplink) { @@ -191,6 +225,9 @@ end: if (SmPolicyContextData.ipv6_address_prefix) ogs_free(SmPolicyContextData.ipv6_address_prefix); + OpenAPI_clear_and_free_string_list(SmPolicyContextData.ipv4_frame_route_list); + OpenAPI_clear_and_free_string_list(SmPolicyContextData.ipv6_frame_route_list); + return request; } diff --git a/src/smf/npcf-handler.c b/src/smf/npcf-handler.c index d44cc43da..c1cbbe344 100644 --- a/src/smf/npcf-handler.c +++ b/src/smf/npcf-handler.c @@ -492,6 +492,53 @@ bool smf_npcf_smpolicycontrol_handle_create( ogs_pfcp_paa_to_ue_ip_addr(&sess->session.paa, &ul_pdr->ue_ip_addr, &ul_pdr->ue_ip_addr_len)); + if (sess->session.ipv4_framed_routes && + sess->pfcp_node->up_function_features.frrt) { + OpenAPI_frame_route_info_t *FrameRouteInfo = NULL; + int i = 0; + OpenAPI_list_for_each(sess->session.ipv4_framed_routes, node) { + FrameRouteInfo = node->data; + if (i >= OGS_MAX_NUM_OF_FRAMED_ROUTES_IN_PDI) + break; + if (!FrameRouteInfo) + continue; + if (!FrameRouteInfo->ipv4_mask) { + ogs_error("Invalid FrameRouteInfo"); + continue; + } + if (!dl_pdr->ipv4_framed_routes) { + dl_pdr->ipv4_framed_routes = + ogs_calloc(OGS_MAX_NUM_OF_FRAMED_ROUTES_IN_PDI, + sizeof(dl_pdr->ipv4_framed_routes[0])); + ogs_assert(dl_pdr->ipv4_framed_routes); + } + dl_pdr->ipv4_framed_routes[i++] = ogs_strdup(FrameRouteInfo->ipv4_mask); + } + } + + if (sess->session.ipv6_framed_routes && + sess->pfcp_node->up_function_features.frrt) { + OpenAPI_frame_route_info_t *FrameRouteInfo = NULL; + int i = 0; + OpenAPI_list_for_each(sess->session.ipv6_framed_routes, node) { + FrameRouteInfo = node->data; + if (i >= OGS_MAX_NUM_OF_FRAMED_ROUTES_IN_PDI) + continue; + if (!FrameRouteInfo) + continue; + if (!FrameRouteInfo->ipv6_prefix) { + ogs_error("Invalid FrameRouteInfo"); + continue; + } + if (!dl_pdr->ipv6_framed_routes) { + dl_pdr->ipv6_framed_routes = + ogs_malloc(OGS_MAX_NUM_OF_FRAMED_ROUTES_IN_PDI); + ogs_assert(dl_pdr->ipv6_framed_routes); + } + dl_pdr->ipv6_framed_routes[i++] = ogs_strdup(FrameRouteInfo->ipv6_prefix); + } + } + ogs_info("UE SUPI[%s] DNN[%s] IPv4[%s] IPv6[%s]", smf_ue->supi, sess->session.name, sess->ipv4 ? OGS_INET_NTOP(&sess->ipv4->addr, buf1) : "", diff --git a/src/smf/nudm-handler.c b/src/smf/nudm-handler.c index c663cfb72..69b64eba5 100644 --- a/src/smf/nudm-handler.c +++ b/src/smf/nudm-handler.c @@ -45,6 +45,8 @@ bool smf_nudm_sdm_handle_get(smf_sess_t *sess, ogs_sbi_stream_t *stream, OpenAPI_ambr_t *sessionAmbr = NULL; OpenAPI_list_t *staticIpAddress = NULL; OpenAPI_ip_address_t *ipAddress = NULL; + OpenAPI_list_t *ipv4FrameRouteList = NULL; + OpenAPI_list_t *ipv6FrameRouteList = NULL; OpenAPI_lnode_t *node = NULL, *node2 = NULL; ogs_assert(sess); @@ -242,6 +244,36 @@ bool smf_nudm_sdm_handle_get(smf_sess_t *sess, ogs_sbi_stream_t *stream, } } + ipv4FrameRouteList = dnnConfiguration->ipv4_frame_route_list; + if (ipv4FrameRouteList) { + if (sess->session.ipv4_framed_routes) { + OpenAPI_list_for_each(sess->session.ipv4_framed_routes, node2) + OpenAPI_frame_route_info_free(node2->data); + OpenAPI_list_clear(sess->session.ipv4_framed_routes); + } else { + sess->session.ipv4_framed_routes = OpenAPI_list_create(); + } + OpenAPI_list_for_each(ipv4FrameRouteList, node2) { + OpenAPI_list_add(sess->session.ipv4_framed_routes, + OpenAPI_frame_route_info_copy(NULL, node2->data)); + } + } + + ipv6FrameRouteList = dnnConfiguration->ipv6_frame_route_list; + if (ipv6FrameRouteList) { + if (sess->session.ipv6_framed_routes) { + OpenAPI_list_for_each(sess->session.ipv6_framed_routes, node2) + OpenAPI_frame_route_info_free(node2->data); + OpenAPI_list_clear(sess->session.ipv6_framed_routes); + } else { + sess->session.ipv6_framed_routes = OpenAPI_list_create(); + } + OpenAPI_list_for_each(ipv6FrameRouteList, node2) { + OpenAPI_list_add(sess->session.ipv6_framed_routes, + OpenAPI_frame_route_info_copy(NULL, node2->data)); + } + } + /* Succeeded to get PDU Session */ if (!sess->session.name) sess->session.name = ogs_strdup(dnnConfigurationMap->key);