From 1d8324af9f0336793e43f4d1d1c2ebe30b2d60da Mon Sep 17 00:00:00 2001 From: mitmitmitm Date: Thu, 23 Feb 2023 08:59:59 +0100 Subject: [PATCH] [PFCP] Support pfcp advertise address --- configs/open5gs/sgwc.yaml.in | 7 ++++++ configs/open5gs/sgwu.yaml.in | 7 ++++++ configs/open5gs/smf.yaml.in | 7 ++++++ configs/open5gs/upf.yaml.in | 7 ++++++ lib/pfcp/build.c | 20 ++++------------ lib/pfcp/context.c | 46 ++++++++++++++++++++++++++++++++++++ lib/pfcp/context.h | 2 ++ lib/pfcp/conv.c | 34 +++++++++++++++++++++++--- lib/pfcp/conv.h | 4 +--- src/sgwc/pfcp-path.c | 3 +++ src/sgwc/sxa-build.c | 5 +--- src/sgwu/pfcp-path.c | 3 +++ src/sgwu/sxa-build.c | 5 +--- src/smf/n4-build.c | 5 +--- src/smf/pfcp-path.c | 3 +++ src/upf/n4-build.c | 5 +--- src/upf/pfcp-path.c | 3 +++ 17 files changed, 128 insertions(+), 38 deletions(-) diff --git a/configs/open5gs/sgwc.yaml.in b/configs/open5gs/sgwc.yaml.in index c3ab48fd8..b87688187 100644 --- a/configs/open5gs/sgwc.yaml.in +++ b/configs/open5gs/sgwc.yaml.in @@ -70,6 +70,13 @@ logger: # option: # so_bindtodevice: vrf-blue # +# o Provide custom PFCP address to be advertised in PFCP association +# request/respond +# sgwc: +# pfcp: +# - addr: 0.0.0.0 +# advertise: open5gs-smf.svc.local +# sgwc: gtpc: - addr: 127.0.0.3 diff --git a/configs/open5gs/sgwu.yaml.in b/configs/open5gs/sgwu.yaml.in index 3f028babb..546a981b8 100644 --- a/configs/open5gs/sgwu.yaml.in +++ b/configs/open5gs/sgwu.yaml.in @@ -45,6 +45,13 @@ logger: # option: # so_bindtodevice: vrf-blue # +# o Provide custom PFCP address to be advertised in PFCP association +# request/respond +# sgwc: +# pfcp: +# - addr: 0.0.0.0 +# advertise: open5gs-smf.svc.local +# # # # o GTP-U Server(127.0.0.6:2152, [::1]:2152) diff --git a/configs/open5gs/smf.yaml.in b/configs/open5gs/smf.yaml.in index 724115ef1..647ea9723 100644 --- a/configs/open5gs/smf.yaml.in +++ b/configs/open5gs/smf.yaml.in @@ -274,6 +274,13 @@ sbi: # option: # so_bindtodevice: vrf-blue # +# o Provide custom PFCP address to be advertised to UPF in PFCP association +# request/respond +# smf: +# pfcp: +# - addr: 0.0.0.0 +# advertise: open5gs-smf.svc.local +# # # # o GTP-C Server(127.0.0.4:2123, [fd69:f21d:873c:fa::3]:2123) diff --git a/configs/open5gs/upf.yaml.in b/configs/open5gs/upf.yaml.in index be842cc69..b132a5b82 100644 --- a/configs/open5gs/upf.yaml.in +++ b/configs/open5gs/upf.yaml.in @@ -45,6 +45,13 @@ logger: # option: # so_bindtodevice: vrf-blue # +# o Provide custom PFCP address to be advertised to SMF in PFCP association +# request/respond +# upf: +# pfcp: +# - addr: 0.0.0.0 +# advertise: open5gs-smf.svc.local +# # > # # o GTP-U Server(127.0.0.7:2152, [::1]:2152) diff --git a/lib/pfcp/build.c b/lib/pfcp/build.c index d287eecd8..55ed2e4a9 100644 --- a/lib/pfcp/build.c +++ b/lib/pfcp/build.c @@ -94,10 +94,7 @@ ogs_pkbuf_t *ogs_pfcp_cp_build_association_setup_request(uint8_t type) req = &pfcp_message->pfcp_association_setup_request; - rv = ogs_pfcp_sockaddr_to_node_id( - ogs_pfcp_self()->pfcp_addr, ogs_pfcp_self()->pfcp_addr6, - ogs_app()->parameter.prefer_ipv4, - &node_id, &node_id_len); + rv = ogs_pfcp_sockaddr_to_node_id(&node_id, &node_id_len); if (rv != OGS_OK) { ogs_error("ogs_pfcp_sockaddr_to_node_id() failed"); ogs_free(pfcp_message); @@ -142,10 +139,7 @@ ogs_pkbuf_t *ogs_pfcp_cp_build_association_setup_response(uint8_t type, rsp = &pfcp_message->pfcp_association_setup_response; - rv = ogs_pfcp_sockaddr_to_node_id( - ogs_pfcp_self()->pfcp_addr, ogs_pfcp_self()->pfcp_addr6, - ogs_app()->parameter.prefer_ipv4, - &node_id, &node_id_len); + rv = ogs_pfcp_sockaddr_to_node_id(&node_id, &node_id_len); if (rv != OGS_OK) { ogs_error("ogs_pfcp_sockaddr_to_node_id() failed"); ogs_free(pfcp_message); @@ -197,10 +191,7 @@ ogs_pkbuf_t *ogs_pfcp_up_build_association_setup_request(uint8_t type) req = &pfcp_message->pfcp_association_setup_request; - rv = ogs_pfcp_sockaddr_to_node_id( - ogs_pfcp_self()->pfcp_addr, ogs_pfcp_self()->pfcp_addr6, - ogs_app()->parameter.prefer_ipv4, - &node_id, &node_id_len); + rv = ogs_pfcp_sockaddr_to_node_id(&node_id, &node_id_len); if (rv != OGS_OK) { ogs_error("ogs_pfcp_sockaddr_to_node_id() failed"); ogs_free(pfcp_message); @@ -268,10 +259,7 @@ ogs_pkbuf_t *ogs_pfcp_up_build_association_setup_response(uint8_t type, rsp = &pfcp_message->pfcp_association_setup_response; - rv = ogs_pfcp_sockaddr_to_node_id( - ogs_pfcp_self()->pfcp_addr, ogs_pfcp_self()->pfcp_addr6, - ogs_app()->parameter.prefer_ipv4, - &node_id, &node_id_len); + rv = ogs_pfcp_sockaddr_to_node_id(&node_id, &node_id_len); if (rv != OGS_OK) { ogs_error("ogs_pfcp_sockaddr_to_node_id() failed"); ogs_free(pfcp_message); diff --git a/lib/pfcp/context.c b/lib/pfcp/context.c index 428a8f747..3b615bf99 100644 --- a/lib/pfcp/context.c +++ b/lib/pfcp/context.c @@ -165,6 +165,8 @@ int ogs_pfcp_context_parse_config(const char *local, const char *remote) int family = AF_UNSPEC; int i, num = 0; const char *hostname[OGS_MAX_NUM_OF_HOSTNAME]; + int num_of_advertise = 0; + const char *advertise[OGS_MAX_NUM_OF_HOSTNAME]; uint16_t port = self.pfcp_port; const char *dev = NULL; ogs_sockaddr_t *addr = NULL; @@ -224,6 +226,27 @@ int ogs_pfcp_context_parse_config(const char *local, const char *remote) } while ( ogs_yaml_iter_type(&hostname_iter) == YAML_SEQUENCE_NODE); + } else if (!strcmp(pfcp_key, "advertise")) { + ogs_yaml_iter_t hostname_iter; + ogs_yaml_iter_recurse(&pfcp_iter, + &hostname_iter); + ogs_assert(ogs_yaml_iter_type(&hostname_iter) != + YAML_MAPPING_NODE); + + do { + if (ogs_yaml_iter_type(&hostname_iter) == + YAML_SEQUENCE_NODE) { + if (!ogs_yaml_iter_next( + &hostname_iter)) + break; + } + + ogs_assert(num < OGS_MAX_NUM_OF_HOSTNAME); + advertise[num_of_advertise++] = + ogs_yaml_iter_value(&hostname_iter); + } while ( + ogs_yaml_iter_type(&hostname_iter) == + YAML_SEQUENCE_NODE); } else if (!strcmp(pfcp_key, "port")) { const char *v = ogs_yaml_iter_value(&pfcp_iter); if (v) { @@ -263,6 +286,27 @@ int ogs_pfcp_context_parse_config(const char *local, const char *remote) ogs_freeaddrinfo(addr); } + addr = NULL; + for (i = 0; i < num_of_advertise; i++) { + rv = ogs_addaddrinfo(&addr, + family, advertise[i], port, 0); + ogs_assert(rv == OGS_OK); + } + + if (addr) { + if (ogs_app()->parameter.no_ipv4 == 0 && + !self.pfcp_advertise) { + ogs_copyaddrinfo(&self.pfcp_advertise, addr); + ogs_filteraddrinfo(&self.pfcp_advertise, AF_INET); + } + if (ogs_app()->parameter.no_ipv6 == 0 && + !self.pfcp_advertise6) { + ogs_copyaddrinfo(&self.pfcp_advertise6, addr); + ogs_filteraddrinfo(&self.pfcp_advertise6, AF_INET); + } + ogs_freeaddrinfo(addr); + } + if (dev) { rv = ogs_socknode_probe( ogs_app()->parameter.no_ipv4 ? @@ -465,6 +509,8 @@ int ogs_pfcp_context_parse_config(const char *local, const char *remote) } while ( ogs_yaml_iter_type(&hostname_iter) == YAML_SEQUENCE_NODE); + } else if (!strcmp(pfcp_key, "advertise")) { + /* Nothing in client */ } else if (!strcmp(pfcp_key, "port")) { const char *v = ogs_yaml_iter_value(&pfcp_iter); if (v) port = atoi(v); diff --git a/lib/pfcp/context.h b/lib/pfcp/context.h index 81f260d63..dcc6cda1f 100644 --- a/lib/pfcp/context.h +++ b/lib/pfcp/context.h @@ -48,6 +48,8 @@ typedef struct ogs_pfcp_context_s { ogs_list_t pfcp_list; /* PFCP IPv4 Server List */ ogs_list_t pfcp_list6; /* PFCP IPv6 Server List */ + ogs_sockaddr_t *pfcp_advertise; /* PFCP Advertise Addr */ + ogs_sockaddr_t *pfcp_advertise6; ogs_sock_t *pfcp_sock; /* PFCP IPv4 Socket */ ogs_sock_t *pfcp_sock6; /* PFCP IPv6 Socket */ ogs_sockaddr_t *pfcp_addr; /* PFCP IPv4 Address */ diff --git a/lib/pfcp/conv.c b/lib/pfcp/conv.c index 67b3a181e..222b36ee2 100644 --- a/lib/pfcp/conv.c +++ b/lib/pfcp/conv.c @@ -19,17 +19,45 @@ #include "ogs-pfcp.h" -int ogs_pfcp_sockaddr_to_node_id( - ogs_sockaddr_t *addr, ogs_sockaddr_t *addr6, int prefer_ipv4, - ogs_pfcp_node_id_t *node_id, int *len) +int ogs_pfcp_sockaddr_to_node_id(ogs_pfcp_node_id_t *node_id, int *len) { const int hdr_len = 1; char *hostname = NULL; + ogs_sockaddr_t *advertise = ogs_pfcp_self()->pfcp_advertise; + ogs_sockaddr_t *advertise6 = ogs_pfcp_self()->pfcp_advertise6; + ogs_sockaddr_t *addr = ogs_pfcp_self()->pfcp_addr; + ogs_sockaddr_t *addr6 = ogs_pfcp_self()->pfcp_addr6; + int prefer_ipv4 = ogs_app()->parameter.prefer_ipv4; + ogs_assert(node_id); memset(node_id, 0, sizeof *node_id); + if (advertise || advertise6) { + hostname = ogs_gethostname(advertise ? advertise : advertise6); + if (hostname) { + node_id->type = OGS_PFCP_NODE_ID_FQDN; + *len = ogs_fqdn_build(node_id->fqdn, + hostname, strlen(hostname)) + hdr_len; + + return OGS_OK; + } + } + + if (advertise && (prefer_ipv4 || !advertise6)) { + node_id->type = OGS_PFCP_NODE_ID_IPV4; + node_id->addr = advertise->sin.sin_addr.s_addr; + *len = OGS_IPV4_LEN + hdr_len; + return OGS_OK; + } + if (advertise6) { + node_id->type = OGS_PFCP_NODE_ID_IPV6; + memcpy(node_id->addr6, advertise6->sin6.sin6_addr.s6_addr, OGS_IPV6_LEN); + *len = OGS_IPV6_LEN + hdr_len; + return OGS_OK; + } + if (addr) { hostname = ogs_gethostname(addr); if (hostname) { diff --git a/lib/pfcp/conv.h b/lib/pfcp/conv.h index 2b74fad0f..af29dffa8 100644 --- a/lib/pfcp/conv.h +++ b/lib/pfcp/conv.h @@ -28,9 +28,7 @@ extern "C" { #endif -int ogs_pfcp_sockaddr_to_node_id( - ogs_sockaddr_t *addr, ogs_sockaddr_t *addr6, int prefer_ipv4, - ogs_pfcp_node_id_t *node_id, int *len); +int ogs_pfcp_sockaddr_to_node_id(ogs_pfcp_node_id_t *node_id, int *len); int ogs_pfcp_f_seid_to_sockaddr( ogs_pfcp_f_seid_t *f_seid, uint16_t port, ogs_sockaddr_t **list); diff --git a/src/sgwc/pfcp-path.c b/src/sgwc/pfcp-path.c index e7106187d..24d27cb6b 100644 --- a/src/sgwc/pfcp-path.c +++ b/src/sgwc/pfcp-path.c @@ -156,6 +156,9 @@ void sgwc_pfcp_close(void) ogs_list_for_each(&ogs_pfcp_self()->pfcp_peer_list, pfcp_node) pfcp_node_fsm_fini(pfcp_node); + ogs_freeaddrinfo(ogs_pfcp_self()->pfcp_advertise); + ogs_freeaddrinfo(ogs_pfcp_self()->pfcp_advertise6); + ogs_socknode_remove_all(&ogs_pfcp_self()->pfcp_list); ogs_socknode_remove_all(&ogs_pfcp_self()->pfcp_list6); } diff --git a/src/sgwc/sxa-build.c b/src/sgwc/sxa-build.c index 4c1d22821..795e9661b 100644 --- a/src/sgwc/sxa-build.c +++ b/src/sgwc/sxa-build.c @@ -48,10 +48,7 @@ ogs_pkbuf_t *sgwc_sxa_build_session_establishment_request( req = &pfcp_message->pfcp_session_establishment_request; /* Node ID */ - rv = ogs_pfcp_sockaddr_to_node_id( - ogs_pfcp_self()->pfcp_addr, ogs_pfcp_self()->pfcp_addr6, - ogs_app()->parameter.prefer_ipv4, - &node_id, &len); + rv = ogs_pfcp_sockaddr_to_node_id(&node_id, &len); if (rv != OGS_OK) { ogs_error("ogs_pfcp_sockaddr_to_node_id() failed"); ogs_free(pfcp_message); diff --git a/src/sgwu/pfcp-path.c b/src/sgwu/pfcp-path.c index 8d60c8a83..1a63fbacc 100644 --- a/src/sgwu/pfcp-path.c +++ b/src/sgwu/pfcp-path.c @@ -156,6 +156,9 @@ void sgwu_pfcp_close(void) ogs_list_for_each(&ogs_pfcp_self()->pfcp_peer_list, pfcp_node) pfcp_node_fsm_fini(pfcp_node); + ogs_freeaddrinfo(ogs_pfcp_self()->pfcp_advertise); + ogs_freeaddrinfo(ogs_pfcp_self()->pfcp_advertise6); + ogs_socknode_remove_all(&ogs_pfcp_self()->pfcp_list); ogs_socknode_remove_all(&ogs_pfcp_self()->pfcp_list6); } diff --git a/src/sgwu/sxa-build.c b/src/sgwu/sxa-build.c index 8c0fb5939..ef585f979 100644 --- a/src/sgwu/sxa-build.c +++ b/src/sgwu/sxa-build.c @@ -43,10 +43,7 @@ ogs_pkbuf_t *sgwu_sxa_build_session_establishment_response(uint8_t type, rsp = &pfcp_message->pfcp_session_establishment_response; /* Node ID */ - rv = ogs_pfcp_sockaddr_to_node_id( - ogs_pfcp_self()->pfcp_addr, ogs_pfcp_self()->pfcp_addr6, - ogs_app()->parameter.prefer_ipv4, - &node_id, &len); + rv = ogs_pfcp_sockaddr_to_node_id(&node_id, &len); if (rv != OGS_OK) { ogs_error("ogs_pfcp_sockaddr_to_node_id() failed"); ogs_free(pfcp_message); diff --git a/src/smf/n4-build.c b/src/smf/n4-build.c index bc4b2c261..4ce171cd8 100644 --- a/src/smf/n4-build.c +++ b/src/smf/n4-build.c @@ -56,10 +56,7 @@ ogs_pkbuf_t *smf_n4_build_session_establishment_request( req = &pfcp_message->pfcp_session_establishment_request; /* Node ID */ - rv = ogs_pfcp_sockaddr_to_node_id( - ogs_pfcp_self()->pfcp_addr, ogs_pfcp_self()->pfcp_addr6, - ogs_app()->parameter.prefer_ipv4, - &node_id, &len); + rv = ogs_pfcp_sockaddr_to_node_id(&node_id, &len); if (rv != OGS_OK) { ogs_error("ogs_pfcp_sockaddr_to_node_id() failed"); ogs_free(pfcp_message); diff --git a/src/smf/pfcp-path.c b/src/smf/pfcp-path.c index 6178d335f..a636f18c3 100644 --- a/src/smf/pfcp-path.c +++ b/src/smf/pfcp-path.c @@ -196,6 +196,9 @@ void smf_pfcp_close(void) ogs_list_for_each(&ogs_pfcp_self()->pfcp_peer_list, pfcp_node) pfcp_node_fsm_fini(pfcp_node); + ogs_freeaddrinfo(ogs_pfcp_self()->pfcp_advertise); + ogs_freeaddrinfo(ogs_pfcp_self()->pfcp_advertise6); + ogs_socknode_remove_all(&ogs_pfcp_self()->pfcp_list); ogs_socknode_remove_all(&ogs_pfcp_self()->pfcp_list6); } diff --git a/src/upf/n4-build.c b/src/upf/n4-build.c index d491487f2..005e4a9d3 100644 --- a/src/upf/n4-build.c +++ b/src/upf/n4-build.c @@ -44,10 +44,7 @@ ogs_pkbuf_t *upf_n4_build_session_establishment_response(uint8_t type, rsp = &pfcp_message->pfcp_session_establishment_response; /* Node ID */ - ogs_pfcp_sockaddr_to_node_id( - ogs_pfcp_self()->pfcp_addr, ogs_pfcp_self()->pfcp_addr6, - ogs_app()->parameter.prefer_ipv4, - &node_id, &len); + ogs_pfcp_sockaddr_to_node_id(&node_id, &len); rsp->node_id.presence = 1; rsp->node_id.data = &node_id; rsp->node_id.len = len; diff --git a/src/upf/pfcp-path.c b/src/upf/pfcp-path.c index 9224956cc..4e64d6b74 100644 --- a/src/upf/pfcp-path.c +++ b/src/upf/pfcp-path.c @@ -159,6 +159,9 @@ void upf_pfcp_close(void) ogs_list_for_each(&ogs_pfcp_self()->pfcp_peer_list, pfcp_node) pfcp_node_fsm_fini(pfcp_node); + ogs_freeaddrinfo(ogs_pfcp_self()->pfcp_advertise); + ogs_freeaddrinfo(ogs_pfcp_self()->pfcp_advertise6); + ogs_socknode_remove_all(&ogs_pfcp_self()->pfcp_list); ogs_socknode_remove_all(&ogs_pfcp_self()->pfcp_list6); }