Projects
osmocom:nightly
osmo-hnbgw
Log In
Username
Password
Error getting diff: tar:
×
We truncated the diff of some files because they were too big. If you want to see the full diff for every file,
click here
.
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 43
View file
osmo-hnbgw.spec
Changed
@@ -17,14 +17,14 @@ %define _lto_cflags %{nil} Name: osmo-hnbgw -Requires: osmocom-nightly = 202208080002 -Version: 1.3.0.5.b7ff.202208080002 +Requires: osmocom-nightly = 202208090002 +Version: 1.3.0.7.44f5.202208090002 Release: 0 Summary: OsmoHNBGW: Osmocom's Base Station Controller for 2G CS mobile networks License: AGPL-3.0-or-later AND GPL-2.0-or-later Group: Hardware/Mobile URL: https://osmocom.org/projects/osmohnbgw -Source: osmo-hnbgw_1.3.0.5.b7ff.202208080002.tar.xz +Source: osmo-hnbgw_1.3.0.7.44f5.202208090002.tar.xz Source1: rpmlintrc BuildRequires: automake >= 1.9 BuildRequires: libtool >= 2
View file
osmo-hnbgw_1.3.0.5.b7ff.202208080002.dsc -> osmo-hnbgw_1.3.0.7.44f5.202208090002.dsc
Changed
@@ -2,7 +2,7 @@ Source: osmo-hnbgw Binary: osmo-hnbgw, osmo-hnbgw-dbg, osmo-hnbgw-doc Architecture: any all -Version: 1.3.0.5.b7ff.202208080002 +Version: 1.3.0.7.44f5.202208090002 Maintainer: Osmocom team <openbsc@lists.osmocom.org> Homepage: https://projects.osmocom.org/projects/osmo-hnbgw Standards-Version: 3.9.8 @@ -14,8 +14,8 @@ osmo-hnbgw-dbg deb debug extra arch=any osmo-hnbgw-doc deb doc optional arch=all Checksums-Sha1: - 3d28a9ce8578b3074a92653f10c7ca7218d72bd6 58404 osmo-hnbgw_1.3.0.5.b7ff.202208080002.tar.xz + 1c945b5cb0432f0a7d8b82b172ac1036c6f5caff 69876 osmo-hnbgw_1.3.0.7.44f5.202208090002.tar.xz Checksums-Sha256: - ddfe530467e8f528208fe4dfed08c1f54fae97c2177d28e0137f38aaf594f9d0 58404 osmo-hnbgw_1.3.0.5.b7ff.202208080002.tar.xz + 22f1d1cc8e36eb66f920f460834cef890d454db3e173b8e925881528be125e24 69876 osmo-hnbgw_1.3.0.7.44f5.202208090002.tar.xz Files: - 23f21a0e6e282c8a8b9926beb1289899 58404 osmo-hnbgw_1.3.0.5.b7ff.202208080002.tar.xz + a732e0fdc11497d5b2b3aaedc903fce6 69876 osmo-hnbgw_1.3.0.7.44f5.202208090002.tar.xz
View file
osmo-hnbgw_1.3.0.5.b7ff.202208080002.tar.xz/.tarball-version -> osmo-hnbgw_1.3.0.7.44f5.202208090002.tar.xz/.tarball-version
Changed
@@ -1 +1 @@ -1.3.0.5-b7ff.202208080002 +1.3.0.7-44f5.202208090002
View file
osmo-hnbgw_1.3.0.5.b7ff.202208080002.tar.xz/configure.ac -> osmo-hnbgw_1.3.0.7.44f5.202208090002.tar.xz/configure.ac
Changed
@@ -61,6 +61,8 @@ PKG_CHECK_MODULES(LIBOSMORANAP, libosmo-ranap >= 1.3.0) PKG_CHECK_MODULES(LIBOSMOHNBAP, libosmo-hnbap >= 1.3.0) PKG_CHECK_MODULES(LIBOSMOMGCPCLIENT, libosmo-mgcp-client >= 1.10.0) +PKG_CHECK_MODULES(LIBOSMOGTLV, libosmo-gtlv >= 0.1.0) +PKG_CHECK_MODULES(LIBOSMOPFCP, libosmo-pfcp >= 0.1.0) dnl checks for header files AC_HEADER_STDC
View file
osmo-hnbgw_1.3.0.5.b7ff.202208080002.tar.xz/contrib/jenkins.sh -> osmo-hnbgw_1.3.0.7.44f5.202208090002.tar.xz/contrib/jenkins.sh
Changed
@@ -33,6 +33,7 @@ osmo-build-dep.sh libosmo-abis osmo-build-dep.sh libosmo-netif osmo-build-dep.sh libosmo-sccp +osmo-build-dep.sh libosmo-pfcp osmo-build-dep.sh libasn1c osmo-build-dep.sh osmo-iuh osmo-build-dep.sh osmo-mgw
View file
osmo-hnbgw_1.3.0.5.b7ff.202208080002.tar.xz/contrib/osmo-hnbgw.spec.in -> osmo-hnbgw_1.3.0.7.44f5.202208090002.tar.xz/contrib/osmo-hnbgw.spec.in
Changed
@@ -17,7 +17,7 @@ %define _lto_cflags %{nil} Name: osmo-hnbgw -Requires: osmocom-nightly = 202208080002 +Requires: osmocom-nightly = 202208090002 Version: @VERSION@ Release: 0 Summary: OsmoHNBGW: Osmocom's Base Station Controller for 2G CS mobile networks
View file
osmo-hnbgw_1.3.0.5.b7ff.202208080002.tar.xz/debian/changelog -> osmo-hnbgw_1.3.0.7.44f5.202208090002.tar.xz/debian/changelog
Changed
@@ -1,8 +1,8 @@ -osmo-hnbgw (1.3.0.5.b7ff.202208080002) unstable; urgency=medium +osmo-hnbgw (1.3.0.7.44f5.202208090002) unstable; urgency=medium * Automatically generated changelog entry for building the Osmocom nightly feed - -- Osmocom OBS scripts <info@osmocom.org> Mon, 08 Aug 2022 00:03:03 +0000 + -- Osmocom OBS scripts <info@osmocom.org> Tue, 09 Aug 2022 00:02:46 +0000 osmo-hnbgw (1.3.0) unstable; urgency=medium
View file
osmo-hnbgw_1.3.0.5.b7ff.202208080002.tar.xz/debian/control -> osmo-hnbgw_1.3.0.7.44f5.202208090002.tar.xz/debian/control
Changed
@@ -30,7 +30,7 @@ Package: osmo-hnbgw Architecture: any Multi-Arch: foreign -Depends: osmocom-nightly (= 202208080002), ${misc:Depends}, ${shlibs:Depends} +Depends: osmocom-nightly (= 202208090002), ${misc:Depends}, ${shlibs:Depends} Recommends: osmo-mgw Description: OsmoHNBGW: Osmocom Home Node B Gateway @@ -38,14 +38,14 @@ Section: debug Architecture: any Multi-Arch: same -Depends: osmocom-nightly (= 202208080002), osmo-hnbgw (= ${binary:Version}), ${misc:Depends} +Depends: osmocom-nightly (= 202208090002), osmo-hnbgw (= ${binary:Version}), ${misc:Depends} Description: OsmoHNBGW: Osmocom Home Node B Gateway Package: osmo-hnbgw-doc Architecture: all Section: doc Priority: optional -Depends: osmocom-nightly (= 202208080002), ${misc:Depends} +Depends: osmocom-nightly (= 202208090002), ${misc:Depends} Description: ${misc:Package} PDF documentation Various manuals: user manual, VTY reference manual and/or protocol/interface manuals.
View file
osmo-hnbgw_1.3.0.5.b7ff.202208080002.tar.xz/include/osmocom/hnbgw/Makefile.am -> osmo-hnbgw_1.3.0.7.44f5.202208090002.tar.xz/include/osmocom/hnbgw/Makefile.am
Changed
@@ -2,4 +2,8 @@ vty.h \ context_map.h hnbgw.h hnbgw_cn.h \ hnbgw_hnbap.h hnbgw_rua.h hnbgw_ranap.h \ - ranap_rab_ass.h mgw_fsm.h tdefs.h + ranap_rab_ass.h mgw_fsm.h tdefs.h \ + hnbgw_pfcp.h \ + ps_rab_ass_fsm.h \ + ps_rab_fsm.h \ + $(NULL)
View file
osmo-hnbgw_1.3.0.5.b7ff.202208080002.tar.xz/include/osmocom/hnbgw/context_map.h -> osmo-hnbgw_1.3.0.7.44f5.202208090002.tar.xz/include/osmocom/hnbgw/context_map.h
Changed
@@ -6,6 +6,13 @@ struct msgb; +#define LOG_MAP(HNB_CTX_MAP, SUBSYS, LEVEL, FMT, ARGS...) \ + LOGHNB((HNB_CTX_MAP) ? (HNB_CTX_MAP)->hnb_ctx : NULL, \ + SUBSYS, LEVEL, "RUA-%u %s: " FMT, \ + (HNB_CTX_MAP) ? (HNB_CTX_MAP)->rua_ctx_id : 0, \ + (HNB_CTX_MAP) ? ((HNB_CTX_MAP)->is_ps ? "PS" : "CS") : "NULL", \ + ##ARGS) \ + enum hnbgw_context_map_state { MAP_S_NULL, MAP_S_ACTIVE, /* currently active map */ @@ -44,6 +51,20 @@ /* FSM instance for the MGW */ struct osmo_fsm_inst *mgw_fi; + + /* FSMs handling RANAP RAB assignments for PS. list of struct ps_rab_ass. For PS RAB Assignment, each Request + * and gets one ps_rab_ass FSM and each Response gets one ps_rab_ass FSM. The reason is that theoretically, each + * such message can contain any number and any combination of RAB IDs, and Request and Response don't + * necessarily match the RAB IDs contained. In practice I only ever see a single RAB matching in Request and + * Response, but we cannot rely on that to always be true. The state of each RAB's PFCP negotiation is kept + * separately in the list hnbgw_context_map.ps_rabs, and as soon as all RABs appearing in a PS RAB Assignment + * message have completed their PFCP setup, we can replace the GTP info for the RAB IDs and forward the RAB + * Assignment Request to HNB / the RAB Assignment Response to CN. */ + struct llist_head ps_rab_ass; + + /* All PS RABs and their GTP tunnel mappings. list of struct ps_rab. Each ps_rab FSM handles the PFCP + * communication for one particular RAB ID. */ + struct llist_head ps_rabs; };
View file
osmo-hnbgw_1.3.0.5.b7ff.202208080002.tar.xz/include/osmocom/hnbgw/hnbgw.h -> osmo-hnbgw_1.3.0.7.44f5.202208090002.tar.xz/include/osmocom/hnbgw/hnbgw.h
Changed
@@ -19,8 +19,8 @@ DMGW, }; -#define LOGHNB(x, ss, lvl, fmt, args ...) \ - LOGP(ss, lvl, "%s " fmt, hnb_context_name(x), ## args) +#define LOGHNB(HNB_CTX, ss, lvl, fmt, args ...) \ + LOGP(ss, lvl, "%s " fmt, hnb_context_name(HNB_CTX), ## args) enum hnb_ctrl_node { CTRL_NODE_HNB = _LAST_CTRL_NODE, @@ -136,6 +136,12 @@ bool log_prefix_hnb_id; unsigned int max_sccp_cr_payload_len; struct mgcp_client_conf *mgcp_client; + struct { + char *local_addr; + uint16_t local_port; + char *remote_addr; + uint16_t remote_port; + } pfcp; } config; /*! SCTP listen socket for incoming connections */ struct osmo_stream_srv_link *iuh; @@ -155,6 +161,11 @@ struct osmo_sccp_addr iups_remote_addr; } sccp; struct mgcp_client *mgcp_client; + + struct { + struct osmo_pfcp_endpoint *ep; + struct osmo_pfcp_cp_peer *cp_peer; + } pfcp; }; extern void *talloc_asn1_ctx; @@ -178,3 +189,13 @@ int hnbgw_vty_go_parent(struct vty *vty); bool hnbgw_requires_empty_sccp_cr(struct hnb_gw *gw, unsigned int ranap_msg_len); + +/* Return true when the user configured GTP mapping to be enabled, by configuring a PFCP link to a UPF. + * Return false when the user configured to skip GTP mapping and RANAP PS RAB Requests/Responses should be passed thru + * 1:1. + * GTP mapping means that there are two GTP tunnels, one towards HNB and one towards CN, and we forward payloads between + * the two tunnels, mapping the TEIDs and GTP addresses. */ +static inline bool hnb_gw_is_gtp_mapping_enabled(const struct hnb_gw *gw) +{ + return gw->config.pfcp.remote_addr != NULL; +}
View file
osmo-hnbgw_1.3.0.7.44f5.202208090002.tar.xz/include/osmocom/hnbgw/hnbgw_pfcp.h
Added
@@ -0,0 +1,5 @@ +#pragma once + +struct hnb_gw; + +int hnbgw_pfcp_init(struct hnb_gw *hnb_gw);
View file
osmo-hnbgw_1.3.0.7.44f5.202208090002.tar.xz/include/osmocom/hnbgw/ps_rab_ass_fsm.h
Added
@@ -0,0 +1,14 @@ +#pragma once + +#include <osmocom/ranap/ranap_ies_defs.h> + +enum ps_rab_ass_fsm_event { + PS_RAB_ASS_EV_LOCAL_F_TEIDS_RX, + PS_RAB_ASS_EV_RAB_ASS_RESP, + PS_RAB_ASS_EV_RAB_ESTABLISHED, + PS_RAB_ASS_EV_RAB_FAIL, +}; + +int hnbgw_gtpmap_rx_rab_ass_req(struct hnbgw_context_map *map, struct osmo_prim_hdr *oph, ranap_message *message); +int hnbgw_gtpmap_rx_rab_ass_resp(struct hnbgw_context_map *map, struct osmo_prim_hdr *oph, ranap_message *message); +void hnbgw_gtpmap_release(struct hnbgw_context_map *map);
View file
osmo-hnbgw_1.3.0.7.44f5.202208090002.tar.xz/include/osmocom/hnbgw/ps_rab_fsm.h
Added
@@ -0,0 +1,102 @@ +#pragma once + +#include <osmocom/core/linuxlist.h> +#include <osmocom/core/socket.h> +#include <osmocom/core/use_count.h> +#include <osmocom/pfcp/pfcp_msg.h> + +/* A GTP tunnel has two endpoints, each endpoint has an IP address and a Tunnel Endpoint ID. So two struct addr_teid + * identify one GTP tunnel. For GTP mapping between HNB and CN, we have two tunnels, see also struct half_gtp_map. The + * combination of IP address and TEID is also known as F-TEID (fully qualified TEID). */ +struct addr_teid { + bool present; + struct osmo_sockaddr addr; + uint32_t teid; +}; + +/* One half_gtp_map represents one GTP tunnel, either on the HNB side or on the CN side. Two struct half_gtp_map make up + * a GTP mapping between HNB and CN. One half_gtp_map for the Access (HNB) side, one for the Core (CN) side. The PFCP + * PDR (Packet Detection Rule) identifies packets coming in on the GTP tunnel the half_gtp_map represents, while the + * PFCP FAR (Forwarding Action Rule) identifies the GTP destination, i.e. the other side's GTP tunnel. So a + * half_gtp_map.far_id is closely tied to the other half_gtp_map, and makes little sense on its own. + * + * half_gtp_map | half_gtp_map + * Access HNBGW+UPF Core + * remote local | local remote + * -->PDR-FAR-->| + * |<--FAR-PDR<-- + * + * See ps_rab.core, ps_rab.access. + */ +struct half_gtp_map { + /* GTP endpoint, obtained from incoming RAB Assignment Request/Response. + * This is the remote side as seen from the UPF's point of view. + * For example, ps_rab.core.remote is the CN GTP that the RAB Assignment Request told us. + * ps_rab.access.remote is the HNB GTP that RAB Assignment Response told us. */ + struct addr_teid remote; + /* UPF GTP endpoint, obtained from PFCP Session Establishment Response. */ + struct addr_teid local; + /* PFCP Packet Detection Rule id that detects GTP-U packets coming from Core/Access */ + uint16_t pdr_id; + /* PFCP Forward Action Rule id that forwards GTP-U packets to Access/Core */ + uint32_t far_id; + /* Whether the RANAP message this RAB's remote address was obtained from had the address encoded in x213_nsap */ + bool use_x213_nsap; +}; + +/* A PS RAB's PFCP state. For the related RANAP state, see struct ps_rab_ass instead. */ +struct ps_rab { + /* Instance of ps_rab_fsm. */ + struct osmo_fsm_inst *fi; + + /* backpointer */ + struct hnb_gw *hnb_gw; + + /* List entry and backpointer. + * If map == NULL, do not call llist_del(&entry): the hnbgw_context_map may deallocate before the PFCP release + * is complete, in which case it sets map = NULL. */ + struct llist_head entry; + struct hnbgw_context_map *map; + + /* RAB-ID used in RANAP RAB AssignmentRequest and Response messages */ + uint8_t rab_id; + /* Backpointer to the ps_rab_ass_fsm for the RAB Assignment Request from Core that created this RAB. + * There are two separate RAB Assignment FSMs responsible for this RAB, one for the Request message and one for + * the Response message. Each RAB Assignment FSM may be responsible for N other RABs besides this one. */ + struct osmo_fsm_inst *req_fi; + /* Backpointer to the ps_rab_ass_fsm for the RAB Assignment Response from Access that confirmed this RAB. */ + struct osmo_fsm_inst *resp_fi; + + /* PFCP session controlling the GTP mapping for this RAB */ + uint64_t cp_seid; + struct osmo_pfcp_ie_f_seid up_f_seid; + bool release_requested; + + /* 'local' and 'remote' refer to the GTP information from the UPF's point of view: + * HNB UPF CN + * access.remote <---> access.local | core.local <---> core.remote + */ + struct half_gtp_map core; + struct half_gtp_map access; + + struct osmo_use_count use_count; +}; + +struct ps_rab *ps_rab_start(struct hnbgw_context_map *map, uint8_t rab_id, + const struct addr_teid *core_f_teid, bool use_x213_nsap, + struct osmo_fsm_inst *req_fi); + +struct ps_rab *ps_rab_get(struct hnbgw_context_map *map, uint8_t rab_id); +bool ps_rab_is_established(const struct ps_rab *rab); +void ps_rab_release(struct ps_rab *rab); + +struct ps_rab_rx_args { + struct addr_teid f_teid; + bool use_x213_nsap; + struct osmo_fsm_inst *notify_fi; +}; +int ps_rab_rx_access_remote_f_teid(struct hnbgw_context_map *map, uint8_t rab_id, + const struct ps_rab_rx_args *args); + +struct ps_rab *ps_rab_find_by_seid(struct hnb_gw *hnb_gw, uint64_t seid, bool is_cp_seid); +void ps_rab_pfcp_set_msg_ctx(struct ps_rab *rab, struct osmo_pfcp_msg *m);
View file
osmo-hnbgw_1.3.0.5.b7ff.202208080002.tar.xz/include/osmocom/hnbgw/tdefs.h -> osmo-hnbgw_1.3.0.7.44f5.202208090002.tar.xz/include/osmocom/hnbgw/tdefs.h
Changed
@@ -3,4 +3,5 @@ #include <osmocom/core/tdef.h> extern struct osmo_tdef mgw_fsm_T_defs; +extern struct osmo_tdef ps_T_defs; extern struct osmo_tdef_group hnbgw_tdef_group;
View file
osmo-hnbgw_1.3.0.5.b7ff.202208080002.tar.xz/include/osmocom/hnbgw/vty.h -> osmo-hnbgw_1.3.0.7.44f5.202208090002.tar.xz/include/osmocom/hnbgw/vty.h
Changed
@@ -8,5 +8,6 @@ IUCS_NODE, IUPS_NODE, MGCP_NODE, + PFCP_NODE, };
View file
osmo-hnbgw_1.3.0.5.b7ff.202208080002.tar.xz/src/osmo-hnbgw/Makefile.am -> osmo-hnbgw_1.3.0.7.44f5.202208090002.tar.xz/src/osmo-hnbgw/Makefile.am
Changed
@@ -20,6 +20,8 @@ $(LIBOSMORANAP_CFLAGS) \ $(LIBOSMOHNBAP_CFLAGS) \ $(LIBOSMOMGCPCLIENT_CFLAGS) \ + $(LIBOSMOGTLV_CFLAGS) \ + $(LIBOSMOPFCP_CFLAGS) \ $(NULL) AM_LDFLAGS = \ @@ -35,11 +37,14 @@ hnbgw_hnbap.c \ hnbgw_rua.c \ hnbgw_ranap.c \ + hnbgw_pfcp.c \ hnbgw_vty.c \ context_map.c \ hnbgw_cn.c \ ranap_rab_ass.c \ mgw_fsm.c \ + ps_rab_ass_fsm.c \ + ps_rab_fsm.c \ tdefs.c \ $(NULL) @@ -58,4 +63,6 @@ $(LIBOSMOMGCPCLIENT_LIBS) \ $(LIBSCTP_LIBS) \ $(LIBOSMOMGCPCLIENT_LIBS) \ + $(LIBOSMOGTLV_LIBS) \ + $(LIBOSMOPFCP_LIBS) \ $(NULL)
View file
osmo-hnbgw_1.3.0.5.b7ff.202208080002.tar.xz/src/osmo-hnbgw/context_map.c -> osmo-hnbgw_1.3.0.7.44f5.202208090002.tar.xz/src/osmo-hnbgw/context_map.c
Changed
@@ -28,6 +28,7 @@ #include <osmocom/hnbgw/hnbgw_rua.h> #include <osmocom/hnbgw/context_map.h> #include <osmocom/hnbgw/mgw_fsm.h> +#include <osmocom/hnbgw/ps_rab_ass_fsm.h> const struct value_string hnbgw_context_map_state_names = { {MAP_S_NULL , "not-initialized"}, @@ -102,6 +103,8 @@ map->rua_ctx_id = rua_ctx_id; map->is_ps = is_ps; map->scu_conn_id = new_scu_conn_id; + INIT_LLIST_HEAD(&map->ps_rab_ass); + INIT_LLIST_HEAD(&map->ps_rabs); /* put it into both lists */ llist_add_tail(&map->hnb_list, &hnb->map_list); @@ -147,6 +150,8 @@ void context_map_deactivate(struct hnbgw_context_map *map) { + LOG_MAP(map, DMAIN, LOGL_NOTICE, "Deactivating\n"); + /* set the state to reserved. We still show up in the list and * avoid re-allocation of the context-id until we are cleaned up * by the context_map garbage collector timer */ @@ -160,6 +165,8 @@ mgw_fsm_release(map); OSMO_ASSERT(map->mgw_fi == NULL); } + + hnbgw_gtpmap_release(map); } static struct osmo_timer_list context_map_tmr; @@ -181,6 +188,7 @@ case MAP_S_RESERVED2: /* second time we see this reserved * entry: remove it */ + LOG_MAP(map, DMAIN, LOGL_NOTICE, "Deallocating\n"); map->state = MAP_S_NULL; llist_del(&map->cn_list); llist_del(&map->hnb_list);
View file
osmo-hnbgw_1.3.0.5.b7ff.202208080002.tar.xz/src/osmo-hnbgw/hnbgw.c -> osmo-hnbgw_1.3.0.7.44f5.202208090002.tar.xz/src/osmo-hnbgw/hnbgw.c
Changed
@@ -61,10 +61,13 @@ #include <osmocom/sigtran/protocol/m3ua.h> #include <osmocom/sigtran/sccp_sap.h> +#include <osmocom/pfcp/pfcp_proto.h> + #include <osmocom/hnbgw/hnbgw.h> #include <osmocom/hnbgw/hnbgw_hnbap.h> #include <osmocom/hnbgw/hnbgw_rua.h> #include <osmocom/hnbgw/hnbgw_cn.h> +#include <osmocom/hnbgw/hnbgw_pfcp.h> #include <osmocom/hnbgw/context_map.h> static const char * const osmo_hnbgw_copyright = @@ -101,6 +104,8 @@ gw->config.mgcp_client = talloc_zero(tall_hnb_ctx, struct mgcp_client_conf); mgcp_client_conf_init(gw->config.mgcp_client); + gw->config.pfcp.remote_port = OSMO_PFCP_PORT; + return gw; } @@ -713,6 +718,9 @@ return -EINVAL; } + /* If UPF is configured, set up PFCP socket and send Association Setup Request to UPF */ + hnbgw_pfcp_init(g_hnb_gw); + if (hnbgw_cmdline_config.daemonize) { rc = osmo_daemonize(); if (rc < 0) {
View file
osmo-hnbgw_1.3.0.5.b7ff.202208080002.tar.xz/src/osmo-hnbgw/hnbgw_cn.c -> osmo-hnbgw_1.3.0.7.44f5.202208090002.tar.xz/src/osmo-hnbgw/hnbgw_cn.c
Changed
@@ -29,12 +29,15 @@ #include <osmocom/sigtran/sccp_sap.h> #include <osmocom/sigtran/sccp_helpers.h> +#include <osmocom/pfcp/pfcp_cp_peer.h> + #include <osmocom/hnbgw/hnbgw.h> #include <osmocom/hnbgw/hnbgw_rua.h> #include <osmocom/ranap/ranap_ies_defs.h> #include <osmocom/ranap/ranap_msg_factory.h> #include <osmocom/hnbgw/context_map.h> #include <osmocom/hnbgw/mgw_fsm.h> +#include <osmocom/hnbgw/ps_rab_ass_fsm.h> #include <osmocom/ranap/RANAP_ProcedureCode.h> #include <osmocom/ranap/ranap_common.h> #include <osmocom/ranap/ranap_common_ran.h> @@ -353,6 +356,7 @@ struct hnbgw_context_map *map; ranap_message *message; int rc; + struct hnb_gw *hnb_gw = cnlink->gw; /* Usually connection-oriented data is always passed transparently towards the specific HNB, via a RUA * connection identified by conn_id. An exception is made for RANAP RAB AssignmentRequest and @@ -365,12 +369,12 @@ return 0; } - /* Intercept RAB Assignment Request, Setup MGW FSM */ - if (!map->is_ps) { - message = talloc_zero(map, ranap_message); - rc = ranap_ran_rx_co_decode(map, message, msgb_l2(oph->msg), msgb_l2len(oph->msg)); - - if (rc == 0) { + /* Intercept RAB Assignment Request, to map RTP and GTP between access and core */ + message = talloc_zero(map, ranap_message); + rc = ranap_ran_rx_co_decode(map, message, msgb_l2(oph->msg), msgb_l2len(oph->msg)); + if (rc == 0) { + if (!map->is_ps) { + /* Circuit-Switched. Set up mapping of RTP ports via MGW */ switch (message->procedureCode) { case RANAP_ProcedureCode_id_RAB_Assignment: /* mgw_fsm_alloc_and_handle_rab_ass_req() takes ownership of (ranap) message */ @@ -381,11 +385,33 @@ mgw_fsm_release(map); break; } - ranap_ran_rx_co_free(message); - } + } else { + /* Packet-Switched. Set up mapping of GTP ports via UPF */ + switch (message->procedureCode) { - talloc_free(message); + case RANAP_ProcedureCode_id_RAB_Assignment: + /* If a UPF is configured, handle the RAB Assignment via ps_rab_ass_fsm, and replace the + * GTP F-TEIDs in the RAB Assignment message before passing it on to RUA. */ + if (hnb_gw_is_gtp_mapping_enabled(hnb_gw)) { + LOGP(DMAIN, LOGL_DEBUG, + "RAB Assignment: setting up GTP tunnel mapping via UPF %s\n", + osmo_sockaddr_to_str_c(OTC_SELECT, &hnb_gw->pfcp.cp_peer->remote_addr)); + return hnbgw_gtpmap_rx_rab_ass_req(map, oph, message); + } + /* If no UPF is configured, directly forward the message as-is (no GTP mapping). */ + LOGP(DMAIN, LOGL_DEBUG, "RAB Assignment: no UPF configured, forwarding as-is\n"); + break; + + case RANAP_ProcedureCode_id_Iu_Release: + /* An IU Release will terminate the PFCP sessions for all RABs (ps_rab FSM instances). + * Terminate all RABs and forward the IU Release directly by rua_tx_dt() below. */ + hnbgw_gtpmap_release(map); + break; + } + } + ranap_ran_rx_co_free(message); } + talloc_free(message); return rua_tx_dt(map->hnb_ctx, map->is_ps, map->rua_ctx_id, msgb_l2(oph->msg), msgb_l2len(oph->msg));
View file
osmo-hnbgw_1.3.0.7.44f5.202208090002.tar.xz/src/osmo-hnbgw/hnbgw_pfcp.c
Added
@@ -0,0 +1,148 @@ +/* PFCP link to UPF for osmo-hnbgw */ +/* (C) 2022 by sysmocom s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved + * + * Author: Neels Janosch Hofmeyr <nhofmeyr@sysmocom.de> + * + * 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include <osmocom/core/sockaddr_str.h> +#include <osmocom/pfcp/pfcp_endpoint.h> +#include <osmocom/pfcp/pfcp_cp_peer.h> + +#include <osmocom/hnbgw/hnbgw.h> +#include <osmocom/hnbgw/context_map.h> +#include <osmocom/hnbgw/ps_rab_fsm.h> + +static void pfcp_set_msg_ctx(struct osmo_pfcp_endpoint *ep, struct osmo_pfcp_msg *m, struct osmo_pfcp_msg *req) +{ + struct hnb_gw *hnb_gw = osmo_pfcp_endpoint_get_priv(ep); + + if (!m->ctx.peer_fi) + osmo_pfcp_cp_peer_set_msg_ctx(hnb_gw->pfcp.cp_peer, m); + + /* If this is a response to an earlier request, just take the msg context from the request message. + * In osmo-hnbgw, a session_fi always points at a ps_rab FSM. */ + if (!m->ctx.session_fi && req && req->ctx.session_fi) + ps_rab_pfcp_set_msg_ctx(req->ctx.session_fi->priv, m); + + /* Otherwise iterate all PS RABs in all hnb contexts matching on the SEID. This rarely happens at all: for tx, + * ps_rab_new_pfcp_msg_tx() already sets the msg ctx, and for rx, we only expect to receive PFCP Responses, + * which are handled above. The only time this will happen is when the UPF shuts down and sends a Deletion. */ + if (!m->ctx.session_fi && m->h.seid_present && m->h.seid != 0) { + struct ps_rab *rab = ps_rab_find_by_seid(hnb_gw, m->h.seid, m->rx); + if (rab) + ps_rab_pfcp_set_msg_ctx(rab, m); + } +} + +static void pfcp_rx_msg(struct osmo_pfcp_endpoint *ep, struct osmo_pfcp_msg *m, struct osmo_pfcp_msg *req) +{ + switch (m->h.message_type) { + + /* We only expect responses to requests. Those are handled by osmo_pfcp_msg.ctx.resp_cb. */ + + /* TODO: handle graceful shutdown from UPF (Session Modification? Deletion?) */ + + default: + LOGP(DLPFCP, LOGL_ERROR, "rx unexpected PFCP message: %s\n", + osmo_pfcp_message_type_str(m->h.message_type)); + return; + } +} + +int hnbgw_pfcp_init(struct hnb_gw *hnb_gw) +{ + struct osmo_pfcp_endpoint_cfg cfg; + struct osmo_pfcp_endpoint *ep; + struct osmo_sockaddr_str local_addr_str; + struct osmo_sockaddr_str upf_addr_str; + struct osmo_sockaddr upf_addr; + + if (!hnb_gw_is_gtp_mapping_enabled(hnb_gw)) { + LOGP(DLPFCP, LOGL_NOTICE, "No UPF configured, NOT setting up PFCP, NOT mapping GTP via UPF\n"); + return 0; + } + LOGP(DLPFCP, LOGL_DEBUG, "%p cfg: pfcp remote-addr %s\n", hnb_gw, hnb_gw->config.pfcp.remote_addr); + + if (!hnb_gw->config.pfcp.local_addr) { + LOGP(DLPFCP, LOGL_ERROR, "Configuration error: missing local PFCP address, required for Node Id\n"); + return -1; + } + + cfg = (struct osmo_pfcp_endpoint_cfg){ + .set_msg_ctx_cb = pfcp_set_msg_ctx, + .rx_msg_cb = pfcp_rx_msg, + .priv = hnb_gw, + }; + + /* Set up PFCP endpoint's local node id from local IP address. Parse address string into local_addr_str... */ + if (osmo_sockaddr_str_from_str(&local_addr_str, hnb_gw->config.pfcp.local_addr, hnb_gw->config.pfcp.local_port)) { + LOGP(DLPFCP, LOGL_ERROR, "Error in PFCP local IP: %s\n", + osmo_quote_str_c(OTC_SELECT, hnb_gw->config.pfcp.local_addr, -1)); + return -1; + } + /* ...and convert to osmo_sockaddr, write to ep->cfg */ + if (osmo_sockaddr_str_to_sockaddr(&local_addr_str, &cfg.local_addr.u.sas)) { + LOGP(DLPFCP, LOGL_ERROR, "Error in PFCP local IP: %s\n", + osmo_quote_str_c(OTC_SELECT, hnb_gw->config.pfcp.local_addr, -1)); + return -1; + } + /* also store the local addr as local Node ID */ + if (osmo_pfcp_ie_node_id_from_osmo_sockaddr(&cfg.local_node_id, &cfg.local_addr)) { + LOGP(DLPFCP, LOGL_ERROR, "Error in PFCP local IP: %s\n", + osmo_quote_str_c(OTC_SELECT, hnb_gw->config.pfcp.local_addr, -1)); + return -1; + } + + hnb_gw->pfcp.ep = ep = osmo_pfcp_endpoint_create(hnb_gw, &cfg); + if (!ep) { + LOGP(DLPFCP, LOGL_ERROR, "Failed to allocate PFCP endpoint\n"); + return -1; + } + + /* Set up remote PFCP address to reach UPF at. First parse the string into upf_addr_str. */ + if (osmo_sockaddr_str_from_str(&upf_addr_str, hnb_gw->config.pfcp.remote_addr, hnb_gw->config.pfcp.remote_port)) { + LOGP(DLPFCP, LOGL_ERROR, "Error in PFCP remote IP: %s\n", + osmo_quote_str_c(OTC_SELECT, hnb_gw->config.pfcp.remote_addr, -1)); + return -1; + } + /* then convert upf_addr_str to osmo_sockaddr */ + if (osmo_sockaddr_str_to_sockaddr(&upf_addr_str, &upf_addr.u.sas)) { + LOGP(DLPFCP, LOGL_ERROR, "Error in PFCP remote IP: %s\n", + osmo_quote_str_c(OTC_SELECT, hnb_gw->config.pfcp.remote_addr, -1)); + return -1; + } + + /* Start the socket */ + if (osmo_pfcp_endpoint_bind(ep)) { + LOGP(DLPFCP, LOGL_ERROR, "Cannot bind PFCP endpoint\n"); + return -1; + } + + /* Associate with UPF */ + hnb_gw->pfcp.cp_peer = osmo_pfcp_cp_peer_alloc(hnb_gw, ep, &upf_addr); + if (!hnb_gw->pfcp.cp_peer) { + LOGP(DLPFCP, LOGL_ERROR, "Cannot allocate PFCP CP Peer FSM\n"); + return -1; + } + if (osmo_pfcp_cp_peer_associate(hnb_gw->pfcp.cp_peer)) { + LOGP(DLPFCP, LOGL_ERROR, "Cannot start PFCP CP Peer FSM\n"); + return -1; + } + + return 0; +}
View file
osmo-hnbgw_1.3.0.5.b7ff.202208080002.tar.xz/src/osmo-hnbgw/hnbgw_rua.c -> osmo-hnbgw_1.3.0.7.44f5.202208090002.tar.xz/src/osmo-hnbgw/hnbgw_rua.c
Changed
@@ -39,6 +39,7 @@ #include <osmocom/hnbgw/context_map.h> #include <osmocom/hnbap/HNBAP_CN-DomainIndicator.h> #include <osmocom/hnbgw/mgw_fsm.h> +#include <osmocom/hnbgw/ps_rab_ass_fsm.h> #include <osmocom/ranap/RANAP_ProcedureCode.h> #include <osmocom/ranap/ranap_common.h> #include <osmocom/ranap/ranap_common_cn.h> @@ -273,15 +274,19 @@ /* If there is data, see if it is a RAB Assignment message where we need to change the user plane information, * for RTP mapping via MGW (soon also GTP mapping via UPF). */ - if (data && len && map && !map->is_ps && !release_context_map) { + if (data && len && map && !release_context_map) { message = talloc_zero(map, ranap_message); rc = ranap_cn_rx_co_decode(map, message, msgb_l2(prim->oph.msg), msgb_l2len(prim->oph.msg)); if (rc == 0) { switch (message->procedureCode) { case RANAP_ProcedureCode_id_RAB_Assignment: - /* mgw_fsm_handle_rab_ass_resp() takes ownership of prim->oph and (ranap) message */ - return mgw_fsm_handle_rab_ass_resp(map, &prim->oph, message); + if (!map->is_ps) { + /* mgw_fsm_handle_rab_ass_resp() takes ownership of prim->oph and (ranap) message */ + return mgw_fsm_handle_rab_ass_resp(map, &prim->oph, message); + } + /* ps_rab_ass_fsm takes ownership of prim->oph and RANAP message */ + return hnbgw_gtpmap_rx_rab_ass_resp(map, &prim->oph, message); } ranap_cn_rx_co_free(message); }
View file
osmo-hnbgw_1.3.0.5.b7ff.202208080002.tar.xz/src/osmo-hnbgw/hnbgw_vty.c -> osmo-hnbgw_1.3.0.7.44f5.202208090002.tar.xz/src/osmo-hnbgw/hnbgw_vty.c
Changed
@@ -362,6 +362,47 @@ return CMD_SUCCESS; } +static struct cmd_node pfcp_node = { + PFCP_NODE, + "%s(config-hnbgw-pfcp)# ", + 1, +}; + +DEFUN(cfg_hnbgw_pfcp, cfg_hnbgw_pfcp_cmd, + "pfcp", "Configure PFCP for GTP tunnel mapping") +{ + vty->node = PFCP_NODE; + return CMD_SUCCESS; +} + +DEFUN(cfg_pfcp_remote_addr, cfg_pfcp_remote_addr_cmd, + "remote-addr IP_ADDR", + "Remote UPF's listen IP address; where to send PFCP requests\n" + "IP address\n") +{ + osmo_talloc_replace_string(g_hnb_gw, &g_hnb_gw->config.pfcp.remote_addr, argv0); + LOGP(DLPFCP, LOGL_NOTICE, "%p cfg: pfcp remote-addr %s\n", g_hnb_gw, g_hnb_gw->config.pfcp.remote_addr); + return CMD_SUCCESS; +} + +DEFUN(cfg_pfcp_local_addr, cfg_pfcp_local_addr_cmd, + "local-addr IP_ADDR", + "Local address for PFCP\n" + "IP address\n") +{ + osmo_talloc_replace_string(g_hnb_gw, &g_hnb_gw->config.pfcp.local_addr, argv0); + return CMD_SUCCESS; +} + +DEFUN(cfg_pfcp_local_port, cfg_pfcp_local_port_cmd, + "local-port <1-65535>", + "Local port for PFCP\n" + "IP port\n") +{ + g_hnb_gw->config.pfcp.local_port = atoi(argv0); + return CMD_SUCCESS; +} + static int config_write_hnbgw(struct vty *vty) { vty_out(vty, "hnbgw%s", VTY_NEWLINE); @@ -425,6 +466,17 @@ return CMD_SUCCESS; } +static int config_write_hnbgw_pfcp(struct vty *vty) +{ + vty_out(vty, " pfcp%s", VTY_NEWLINE); + if (g_hnb_gw->config.pfcp.local_addr) + vty_out(vty, " local-addr %s%s", g_hnb_gw->config.pfcp.local_addr, VTY_NEWLINE); + if (g_hnb_gw->config.pfcp.remote_addr) + vty_out(vty, " remote-addr %s%s", g_hnb_gw->config.pfcp.remote_addr, VTY_NEWLINE); + + return CMD_SUCCESS; +} + void hnbgw_vty_init(struct hnb_gw *gw, void *tall_ctx) { g_hnb_gw = gw; @@ -463,6 +515,12 @@ install_element(HNBGW_NODE, &cfg_hnbgw_mgcp_cmd); install_node(&mgcp_node, config_write_hnbgw_mgcp); + install_node(&pfcp_node, config_write_hnbgw_pfcp); + install_element(HNBGW_NODE, &cfg_hnbgw_pfcp_cmd); + install_element(PFCP_NODE, &cfg_pfcp_local_addr_cmd); + install_element(PFCP_NODE, &cfg_pfcp_local_port_cmd); + install_element(PFCP_NODE, &cfg_pfcp_remote_addr_cmd); + mgcp_client_vty_init(tall_hnb_ctx, MGCP_NODE, g_hnb_gw->config.mgcp_client); osmo_tdef_vty_groups_init(HNBGW_NODE, hnbgw_tdef_group); }
View file
osmo-hnbgw_1.3.0.7.44f5.202208090002.tar.xz/src/osmo-hnbgw/ps_rab_ass_fsm.c
Added
@@ -0,0 +1,686 @@ +/* Handle RANAP PS RAB Assignment */ +/* (C) 2022 by sysmocom s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved + * + * Author: Neels Janosch Hofmeyr <nhofmeyr@sysmocom.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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. + */ + +#include <errno.h> + +#include <asn1c/asn1helpers.h> + +#include <osmocom/core/msgb.h> +#include <osmocom/core/utils.h> +#include <osmocom/core/prim.h> + +#include <osmocom/core/fsm.h> +#include <osmocom/core/byteswap.h> +#include <arpa/inet.h> +#include <osmocom/core/logging.h> +#include <osmocom/core/sockaddr_str.h> +#include <osmocom/core/tdef.h> + +#include <osmocom/ranap/ranap_common.h> +#include <osmocom/ranap/ranap_common_cn.h> +#include <osmocom/ranap/ranap_common_ran.h> +#include <osmocom/ranap/ranap_msg_factory.h> + +#include <osmocom/ranap/ranap_ies_defs.h> +#include <osmocom/ranap/iu_helpers.h> + +#include <osmocom/pfcp/pfcp_msg.h> +#include <osmocom/pfcp/pfcp_endpoint.h> +#include <osmocom/pfcp/pfcp_cp_peer.h> + +#include <osmocom/hnbgw/hnbgw.h> +#include <osmocom/hnbgw/context_map.h> +#include <osmocom/hnbgw/ranap_rab_ass.h> +#include <osmocom/hnbgw/ps_rab_fsm.h> + +#include <osmocom/hnbgw/hnbgw_rua.h> + +#include <osmocom/hnbgw/tdefs.h> + +#define PORT_GTP1_U 2152 + +#define LOG_PS_RAB_ASS(RAB_ASS, LOGL, FMT, ARGS...) \ + LOGPFSML((RAB_ASS) ? (RAB_ASS)->fi : NULL, LOGL, FMT, ##ARGS) + +enum ps_rab_ass_fsm_event { + PS_RAB_ASS_EV_LOCAL_F_TEIDS_RX, + PS_RAB_ASS_EV_RAB_ASS_RESP, + PS_RAB_ASS_EV_RAB_ESTABLISHED, + PS_RAB_ASS_EV_RAB_FAIL, +}; + +static const struct value_string ps_rab_ass_fsm_event_names = { + OSMO_VALUE_STRING(PS_RAB_ASS_EV_LOCAL_F_TEIDS_RX), + OSMO_VALUE_STRING(PS_RAB_ASS_EV_RAB_ASS_RESP), + OSMO_VALUE_STRING(PS_RAB_ASS_EV_RAB_ESTABLISHED), + OSMO_VALUE_STRING(PS_RAB_ASS_EV_RAB_FAIL), + {} +}; + +enum ps_rab_ass_state { + PS_RAB_ASS_ST_RX_RAB_ASS_MSG, + PS_RAB_ASS_ST_WAIT_LOCAL_F_TEIDS, + PS_RAB_ASS_ST_RX_RAB_ASS_RESP, + PS_RAB_ASS_ST_WAIT_RABS_ESTABLISHED, +}; + +/* Represents one RANAP PS RAB Assignment Request and Response dialog. + * There may be any number of PS RAB Assignment Requests, each with any number of RABs being established. We need to + * manage these asynchronously and flexibly: + * - RABs may be assigned in a group and released one by one, or vice versa; + * - we can only forward a RAB Assignment Request / Response when all RABs appearing in it have been set up by the UPF. + * + * This structure manages the RAB Assignment procedures, and the currently set up RABs: + * + * - hnbgw_context_map + * - .ps_rab_ass: list of PS RAB Assignment procedures + * - ps_rab_ass_fsm: one RANAP PS RAB Assignment procedure + * - ... + * - .ps_rabs: list of individual PS RABs + * - ps_rab_fsm: one GTP mapping with PFCP session to the UPF, for a single RAB + * - ... + * + * This ps_rab_ass_fsm lives from a received RAB Assignment Request up to the sent RAB Assignment Response; it + * deallocates when all the RABs have been set up. + * + * The ps_rab_ass_fsm sets up ps_rab_fsm instances, which live longer: up until a RAB or conn release is performed. + */ +struct ps_rab_ass { + struct llist_head entry; + + struct osmo_fsm_inst *fi; + + /* backpointer */ + struct hnbgw_context_map *map; + + ranap_message *ranap_rab_ass_req_message; + + ranap_message *ranap_rab_ass_resp_message; + struct osmo_prim_hdr *ranap_rab_ass_resp_oph; + + /* A RAB Assignment may contain more than one RAB. Each RAB sets up a distinct ps_rab_fsm (aka PFCP session) and + * reports back about local F-TEIDs assigned by the UPF. This gives the nr of RAB events we expect from + * ps_rab_fsms, without iterating the RAB Assignment message every time (minor optimisation). */ + int rabs_count; + int rabs_done_count; +}; + +struct osmo_tdef_state_timeout ps_rab_ass_fsm_timeouts32 = { + /* PS_RAB_ASS_ST_WAIT_LOCAL_F_TEIDS is terminated by PFCP timeouts via ps_rab_fsm */ + /* PS_RAB_ASS_ST_WAIT_RABS_ESTABLISHED is terminated by PFCP timeouts via ps_rab_fsm */ +}; + +#define ps_rab_ass_fsm_state_chg(state) \ + osmo_tdef_fsm_inst_state_chg(fi, state, ps_rab_ass_fsm_timeouts, ps_T_defs, -1) + +static struct osmo_fsm ps_rab_ass_fsm; + +static struct ps_rab_ass *ps_rab_ass_alloc(struct hnbgw_context_map *map) +{ + struct ps_rab_ass *rab_ass; + struct osmo_fsm_inst *fi; + + fi = osmo_fsm_inst_alloc(&ps_rab_ass_fsm, map, map, LOGL_DEBUG, NULL); + OSMO_ASSERT(fi); + osmo_fsm_inst_update_id_f_sanitize(fi, '-', "%s-RUA-%u", hnb_context_name(map->hnb_ctx), map->rua_ctx_id); + + rab_ass = talloc(fi, struct ps_rab_ass); + OSMO_ASSERT(rab_ass); + *rab_ass = (struct ps_rab_ass){ + .fi = fi, + .map = map, + }; + fi->priv = rab_ass; + + llist_add_tail(&rab_ass->entry, &map->ps_rab_ass); + return rab_ass; +} + +static void ps_rab_ass_failure(struct ps_rab_ass *rab_ass) +{ + LOG_PS_RAB_ASS(rab_ass, LOGL_ERROR, "PS RAB Assignment failed\n"); + + /* TODO: send unsuccessful RAB Assignment Response to Core? */ + /* TODO: remove RAB from Access? */ + + osmo_fsm_inst_term(rab_ass->fi, OSMO_FSM_TERM_REGULAR, NULL); +} + +/* Add a single RAB from a RANAP PS RAB Assignment Request's list of RABs */ +static int ps_rab_setup_core_remote(struct ps_rab_ass *rab_ass, RANAP_ProtocolIE_FieldPair_t *protocol_ie_field_pair) +{ + struct hnbgw_context_map *map = rab_ass->map; + uint8_t rab_id; + struct addr_teid f_teid = {}; + bool use_x213_nsap; + struct ps_rab *rab; + + RANAP_RAB_SetupOrModifyItemFirst_t first; + RANAP_TransportLayerAddress_t *transp_layer_addr; + RANAP_TransportLayerInformation_t *tli; + int rc; + + if (protocol_ie_field_pair->id != RANAP_ProtocolIE_ID_id_RAB_SetupOrModifyItem) + return -1; + + /* Extract information about the GTP Core side */ + rc = ranap_decode_rab_setupormodifyitemfirst(&first, + &protocol_ie_field_pair->firstValue); + if (rc < 0) + goto error_exit; + + rab_id = first.rAB_ID.buf0; + + /* Decode GTP endpoint IP-Address */ + tli = first.transportLayerInformation; + transp_layer_addr = &tli->transportLayerAddress; + rc = ranap_transp_layer_addr_decode2(&f_teid.addr, &use_x213_nsap, transp_layer_addr); + if (rc < 0) + goto error_exit; + osmo_sockaddr_set_port(&f_teid.addr.u.sa, PORT_GTP1_U); + + /* Decode the GTP remote TEID */ + if (tli->iuTransportAssociation.present != RANAP_IuTransportAssociation_PR_gTP_TEI) { + rc = -1; + goto error_exit;
View file
osmo-hnbgw_1.3.0.7.44f5.202208090002.tar.xz/src/osmo-hnbgw/ps_rab_fsm.c
Added
@@ -0,0 +1,819 @@ +/* Handle PFCP communication with the UPF for a single RAB. */ +/* (C) 2022 by sysmocom s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved + * + * Author: Neels Janosch Hofmeyr <nhofmeyr@sysmocom.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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. + */ + +#include <errno.h> + +#include <osmocom/core/tdef.h> + +#include <osmocom/pfcp/pfcp_endpoint.h> +#include <osmocom/pfcp/pfcp_cp_peer.h> + +#include <osmocom/hnbgw/hnbgw.h> +#include <osmocom/hnbgw/context_map.h> +#include <osmocom/hnbgw/tdefs.h> +#include <osmocom/hnbgw/ps_rab_fsm.h> +#include <osmocom/hnbgw/ps_rab_ass_fsm.h> + +#define LOG_PS_RAB(RAB, LOGL, FMT, ARGS...) \ + LOGPFSML((RAB) ? (RAB)->fi : NULL, LOGL, FMT, ##ARGS) + +enum ps_rab_state { + PS_RAB_ST_RX_CORE_REMOTE_F_TEID, + PS_RAB_ST_WAIT_PFCP_EST_RESP, + PS_RAB_ST_WAIT_ACCESS_REMOTE_F_TEID, + PS_RAB_ST_WAIT_PFCP_MOD_RESP, + PS_RAB_ST_ESTABLISHED, + PS_RAB_ST_WAIT_PFCP_DEL_RESP, + PS_RAB_ST_WAIT_USE_COUNT, +}; + +enum ps_rab_event { + PS_RAB_EV_PFCP_EST_RESP, + PS_RAB_EV_RX_ACCESS_REMOTE_F_TEID, + PS_RAB_EV_PFCP_MOD_RESP, + PS_RAB_EV_PFCP_DEL_RESP, + PS_RAB_EV_USE_COUNT_ZERO, +}; + +static const struct value_string ps_rab_fsm_event_names = { + OSMO_VALUE_STRING(PS_RAB_EV_PFCP_EST_RESP), + OSMO_VALUE_STRING(PS_RAB_EV_RX_ACCESS_REMOTE_F_TEID), + OSMO_VALUE_STRING(PS_RAB_EV_PFCP_MOD_RESP), + OSMO_VALUE_STRING(PS_RAB_EV_PFCP_DEL_RESP), + OSMO_VALUE_STRING(PS_RAB_EV_USE_COUNT_ZERO), + {} +}; + +struct osmo_tdef_state_timeout ps_rab_fsm_timeouts32 = { + /* PS_RAB_ST_WAIT_PFCP_EST_RESP is terminated by PFCP timeouts via resp_cb() */ + /* PS_RAB_ST_WAIT_ACCESS_REMOTE_F_TEID is terminated by ps_rab_ass_fsm */ + /* PS_RAB_ST_WAIT_PFCP_MOD_RESP is terminated by PFCP timeouts via resp_cb() */ + /* PS_RAB_ST_WAIT_PFCP_DEL_RESP is terminated by PFCP timeouts via resp_cb() */ +}; + +enum pdr_far_id { + ID_CORE_TO_ACCESS = 1, + ID_ACCESS_TO_CORE = 2, +}; + + +#define ps_rab_fsm_state_chg(state) \ + osmo_tdef_fsm_inst_state_chg(fi, state, ps_rab_fsm_timeouts, ps_T_defs, -1) + +#define PS_RAB_USE_ACTIVE "active" + +static struct osmo_fsm ps_rab_fsm; + +static int ps_rab_fsm_use_cb(struct osmo_use_count_entry *e, int32_t old_use_count, const char *file, int line); + +static struct ps_rab *ps_rab_alloc(struct hnbgw_context_map *map, uint8_t rab_id) +{ + struct osmo_fsm_inst *fi; + struct ps_rab *rab; + + /* Allocate with the global hnb_gw, so that we can gracefully handle PFCP release even if a hnb_ctx gets + * deallocated. */ + fi = osmo_fsm_inst_alloc(&ps_rab_fsm, map->hnb_ctx->gw, NULL, LOGL_DEBUG, NULL); + OSMO_ASSERT(fi); + osmo_fsm_inst_update_id_f_sanitize(fi, '-', "%s-RUA-%u-RAB-%u", hnb_context_name(map->hnb_ctx), map->rua_ctx_id, + rab_id); + + rab = talloc(fi, struct ps_rab); + OSMO_ASSERT(rab); + *rab = (struct ps_rab){ + .fi = fi, + .hnb_gw = map->hnb_ctx->gw, + .map = map, + .rab_id = rab_id, + .use_count = { + .talloc_object = rab, + .use_cb = ps_rab_fsm_use_cb, + }, + }; + fi->priv = rab; + + osmo_use_count_get_put(&rab->use_count, PS_RAB_USE_ACTIVE, 1); + + llist_add_tail(&rab->entry, &map->ps_rabs); + return rab; +} + +/* Iterate all ps_rab instances of all context maps and return the one matching the given SEID. + * If is_cp_seid == true, match seid with rab->cp_seid (e.g. for received PFCP messages). + * Otherwise match seid with rab->up_f_seid.seid (e.g. for sent PFCP messages). */ +struct ps_rab *ps_rab_find_by_seid(struct hnb_gw *hnb_gw, uint64_t seid, bool is_cp_seid) +{ + struct hnb_context *hnb; + llist_for_each_entry(hnb, &hnb_gw->hnb_list, list) { + struct hnbgw_context_map *map; + llist_for_each_entry(map, &hnb->map_list, hnb_list) { + struct ps_rab *rab; + llist_for_each_entry(rab, &map->ps_rabs, entry) { + uint64_t rab_seid = is_cp_seid ? rab->cp_seid : rab->up_f_seid.seid; + if (rab_seid == seid) + return rab; + } + } + } + return NULL; +} + +void ps_rab_pfcp_set_msg_ctx(struct ps_rab *rab, struct osmo_pfcp_msg *m) +{ + if (m->ctx.session_fi) + return; + m->ctx.session_fi = rab->fi; + m->ctx.session_use_count = &rab->use_count; + m->ctx.session_use_token = "PFCP_MSG"; + osmo_use_count_get_put(m->ctx.session_use_count, m->ctx.session_use_token, 1); +} + +static struct osmo_pfcp_msg *ps_rab_new_pfcp_msg_req(struct ps_rab *rab, enum osmo_pfcp_message_type msg_type) +{ + struct hnb_gw *hnb_gw = rab->hnb_gw; + struct osmo_pfcp_msg *m = osmo_pfcp_cp_peer_new_req(hnb_gw->pfcp.cp_peer, msg_type); + + m->h.seid_present = true; + m->h.seid = rab->up_f_seid.seid; + ps_rab_pfcp_set_msg_ctx(rab, m); + return m; +} + +struct ps_rab *ps_rab_get(struct hnbgw_context_map *map, uint8_t rab_id) +{ + struct ps_rab *rab; + llist_for_each_entry(rab, &map->ps_rabs, entry) { + if (rab->rab_id != rab_id) + continue; + return rab; + } + return NULL; +} + +bool ps_rab_is_established(const struct ps_rab *rab) +{ + return rab && rab->fi->state == PS_RAB_ST_ESTABLISHED; +} + +void ps_rab_failure(struct ps_rab *rab) +{ + if (rab->req_fi) + osmo_fsm_inst_dispatch(rab->req_fi, PS_RAB_ASS_EV_RAB_FAIL, rab); + if (rab->resp_fi) + osmo_fsm_inst_dispatch(rab->resp_fi, PS_RAB_ASS_EV_RAB_FAIL, rab); + ps_rab_release(rab); +} + +struct ps_rab *ps_rab_start(struct hnbgw_context_map *map, uint8_t rab_id, + const struct addr_teid *core_f_teid, bool use_x213_nsap, + struct osmo_fsm_inst *req_fi) +{ + struct osmo_fsm_inst *fi; + struct ps_rab *rab; + + rab = ps_rab_alloc(map, rab_id); + fi = rab->fi; + rab->req_fi = req_fi; + rab->core.remote = *core_f_teid; + rab->core.use_x213_nsap = use_x213_nsap; + + /* Got the RAB's Core side GTP info. Route the GTP for via the local UPF. + * Establish a PFCP session with the UPF: tell it about the Core side GTP endpoint and request local F-TEIDs. */ + if (ps_rab_fsm_state_chg(PS_RAB_ST_WAIT_PFCP_EST_RESP)) { + osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, NULL); + return NULL; + }
View file
osmo-hnbgw_1.3.0.5.b7ff.202208080002.tar.xz/src/osmo-hnbgw/tdefs.c -> osmo-hnbgw_1.3.0.7.44f5.202208090002.tar.xz/src/osmo-hnbgw/tdefs.c
Changed
@@ -15,6 +15,7 @@ */ #include <osmocom/hnbgw/tdefs.h> +#include <osmocom/pfcp/pfcp_endpoint.h> struct osmo_tdef mgw_fsm_T_defs = { {.T = -1001, .default_val = 5, .desc = "Timeout for HNB side call-leg (to-HNB) creation" }, @@ -25,7 +26,14 @@ { } }; +struct osmo_tdef ps_T_defs = { + {.T = -1002, .default_val = 10, .desc = "Timeout for the HNB to respond to PS RAB Assignment Request" }, + { } +}; + struct osmo_tdef_group hnbgw_tdef_group = { {.name = "mgw", .tdefs = mgw_fsm_T_defs, .desc = "MGW (Media Gateway) interface" }, + {.name = "ps", .tdefs = ps_T_defs, .desc = "timers for Packet Switched domain" }, + {.name = "pfcp", .tdefs = osmo_pfcp_tdefs, .desc = "PFCP timers" }, { } };
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.