neels has submitted this change. ( https://gerrit.osmocom.org/c/osmo-upf/+/28306 )
Change subject: move libosmo-pfcp to libosmo-pfcp.git ......................................................................
move libosmo-pfcp to libosmo-pfcp.git
The first user of this is osmo-hnbgw, to implement GTP mapping via a UPF.
Related: SYS#5895 Change-Id: I1464cdd846b00707b0abba9126aa5bb784b7caf1 --- M configure.ac M include/osmocom/Makefile.am D include/osmocom/pfcp/Makefile.am D include/osmocom/pfcp/pfcp_endpoint.h D include/osmocom/pfcp/pfcp_ies_custom.h D include/osmocom/pfcp/pfcp_msg.h D include/osmocom/pfcp/pfcp_proto.h D include/osmocom/pfcp/pfcp_strs.h M src/Makefile.am D src/libosmo-pfcp/Makefile.am D src/libosmo-pfcp/gen__pfcp_ies_auto.c D src/libosmo-pfcp/pfcp_endpoint.c D src/libosmo-pfcp/pfcp_ies_custom.c D src/libosmo-pfcp/pfcp_msg.c D src/libosmo-pfcp/pfcp_strs.c M tests/Makefile.am D tests/libosmo-pfcp/Makefile.am D tests/libosmo-pfcp/pfcp_test.c D tests/libosmo-pfcp/pfcp_test.ok M tests/testsuite.at 20 files changed, 1 insertion(+), 4,755 deletions(-)
Approvals: pespin: Looks good to me, but someone else must approve laforge: Looks good to me, approved Jenkins Builder: Verified
diff --git a/configure.ac b/configure.ac index 9ee5011..fe41cc9 100644 --- a/configure.ac +++ b/configure.ac @@ -43,6 +43,7 @@ PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.5.0) PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.5.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 @@ -198,14 +199,11 @@ AC_OUTPUT( include/Makefile include/osmocom/Makefile - include/osmocom/pfcp/Makefile include/osmocom/upf/Makefile src/Makefile - src/libosmo-pfcp/Makefile src/osmo-upf/Makefile tests/Makefile tests/atlocal - tests/libosmo-pfcp/Makefile doc/Makefile doc/examples/Makefile doc/manuals/Makefile diff --git a/include/osmocom/Makefile.am b/include/osmocom/Makefile.am index 5a1276e..3f929f1 100644 --- a/include/osmocom/Makefile.am +++ b/include/osmocom/Makefile.am @@ -1,4 +1,3 @@ SUBDIRS = \ - pfcp \ upf \ $(NULL) diff --git a/include/osmocom/pfcp/Makefile.am b/include/osmocom/pfcp/Makefile.am deleted file mode 100644 index a9bdeab..0000000 --- a/include/osmocom/pfcp/Makefile.am +++ /dev/null @@ -1,22 +0,0 @@ -pfcp_HEADERS = \ - pfcp_endpoint.h \ - pfcp_ies_custom.h \ - pfcp_ies_auto.h \ - pfcp_msg.h \ - pfcp_proto.h \ - pfcp_strs.h \ - $(NULL) - -pfcpdir = $(includedir)/osmocom/pfcp - -BUILT_SOURCES = \ - pfcp_ies_auto.h \ - $(NULL) - -CLEANFILES = \ - pfcp_ies_auto.h \ - $(NULL) - -pfcp_ies_auto.h: $(top_srcdir)/src/libosmo-pfcp/gen__pfcp_ies_auto.c - $(MAKE) -C $(top_builddir)/src/libosmo-pfcp gen__pfcp_ies_auto - $(top_builddir)/src/libosmo-pfcp/gen__pfcp_ies_auto h > $(builddir)/pfcp_ies_auto.h diff --git a/include/osmocom/pfcp/pfcp_endpoint.h b/include/osmocom/pfcp/pfcp_endpoint.h deleted file mode 100644 index acc878e..0000000 --- a/include/osmocom/pfcp/pfcp_endpoint.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * (C) 2021-2022 by sysmocom - s.f.m.c. GmbH info@sysmocom.de - * All Rights Reserved. - * - * Author: Neels Janosch Hofmeyr nhofmeyr@sysmocom.de - * - * SPDX-License-Identifier: GPL-2.0+ - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. - * - */ - -#pragma once - -#include <osmocom/core/socket.h> -#include <osmocom/core/select.h> -#include <osmocom/core/tdef.h> - -#include <osmocom/pfcp/pfcp_msg.h> - -struct osmo_pfcp_endpoint; -struct osmo_fsm_inst; - -#define OSMO_PFCP_TIMER_HEARTBEAT_REQ -19 -#define OSMO_PFCP_TIMER_HEARTBEAT_RESP -20 -#define OSMO_PFCP_TIMER_GRACEFUL_REL -21 -#define OSMO_PFCP_TIMER_T1 -22 -#define OSMO_PFCP_TIMER_N1 -23 -#define OSMO_PFCP_TIMER_KEEP_RESP -24 -#define OSMO_PFCP_TIMER_ASSOC_RETRY -26 - -extern struct osmo_tdef osmo_pfcp_tdefs[]; - -/* Ownership of m remains with the caller / m will be deallocated by the caller. - * \param ep The PFCP endpoint that received and decoded the message. - * \param m The message that was received. - * \param req If m is a PFCP Response to an earlier Request, req is that request message. Otherwise req is NULL. - */ -typedef void (*osmo_pfcp_endpoint_cb)(struct osmo_pfcp_endpoint *ep, struct osmo_pfcp_msg *m, - struct osmo_pfcp_msg *req); - -/* Send/receive PFCP messages to/from remote PFCP endpoints. */ -struct osmo_pfcp_endpoint { - struct { - /* Local address */ - struct osmo_sockaddr local_addr; - /* Local PFCP Node ID, as sent in outgoing messages' Node ID IE */ - struct osmo_pfcp_ie_node_id local_node_id; - - /* Timer definitions to use, if any. See t1_ms, keep_resp_ms. Use osmo_pfcp_tdefs by default. It is - * convenient to add osmo_pfcp_tdefs as one of your program's osmo_tdef_group entries and call - * osmo_tdef_vty_init() to expose PFCP timers on the VTY. */ - const struct osmo_tdef *tdefs; - } cfg; - - /* PFCP socket */ - struct osmo_fd pfcp_fd; - - /* The time at which this endpoint last restarted, as seconds since unix epoch. */ - uint32_t recovery_time_stamp; - - /* State for determining the next sequence number for transmitting a request message */ - uint32_t seq_nr_state; - - /* This function is called just after decoding and before handling the message. - * This function may set ctx.peer_fi and ctx.session_fi, used for logging context during message decoding. - * The caller may also use these fi pointers to reduce lookup iterations in rx_msg(). - */ - osmo_pfcp_endpoint_cb set_msg_ctx; - - /* Callback to receive single incoming PFCP messages from a remote peer, already decoded. */ - osmo_pfcp_endpoint_cb rx_msg; - - /* application-private data */ - void *priv; - - /* All transmitted PFCP Request messages, list of osmo_pfcp_queue_entry. - * For a transmitted Request message, wait for a matching Response from a remote peer; if none arrives, - * retransmit (see n1 and t1_ms). */ - struct llist_head sent_requests; - /* All transmitted PFCP Response messages, list of osmo_pfcp_queue_entry. - * For a transmitted Response message, keep it in the queue for a fixed amount of time. If the peer retransmits - * the original Request, do not dispatch the Request, but respond with the queued message directly. */ - struct llist_head sent_responses; -}; - -struct osmo_pfcp_endpoint *osmo_pfcp_endpoint_create(void *ctx, void *priv); -int osmo_pfcp_endpoint_bind(struct osmo_pfcp_endpoint *ep); -void osmo_pfcp_endpoint_close(struct osmo_pfcp_endpoint *ep); -void osmo_pfcp_endpoint_free(struct osmo_pfcp_endpoint **ep); - -int osmo_pfcp_endpoint_tx(struct osmo_pfcp_endpoint *ep, struct osmo_pfcp_msg *m); -int osmo_pfcp_endpoint_tx_data(struct osmo_pfcp_endpoint *ep, struct osmo_pfcp_msg *m); -int osmo_pfcp_endpoint_tx_heartbeat_req(struct osmo_pfcp_endpoint *ep, const struct osmo_sockaddr *remote_addr); - -void osmo_pfcp_endpoint_invalidate_ctx(struct osmo_pfcp_endpoint *ep, struct osmo_fsm_inst *deleted_fi); diff --git a/include/osmocom/pfcp/pfcp_ies_custom.h b/include/osmocom/pfcp/pfcp_ies_custom.h deleted file mode 100644 index 08e62d1..0000000 --- a/include/osmocom/pfcp/pfcp_ies_custom.h +++ /dev/null @@ -1,166 +0,0 @@ -/* Definitions for decoded PFCP IEs, to be used by the auto-generated pfcp_ies_auto.c. */ -/* - * (C) 2021-2022 by sysmocom - s.f.m.c. GmbH info@sysmocom.de - * All Rights Reserved. - * - * Author: Neels Janosch Hofmeyr nhofmeyr@sysmocom.de - * - * SPDX-License-Identifier: GPL-2.0+ - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. - * - */ - -#pragma once - -#include <osmocom/core/socket.h> - -#include <osmocom/pfcp/pfcp_proto.h> - -/* Common pattern used in various PFCP IEs. */ -struct osmo_pfcp_ip_addrs { - bool v4_present; - struct osmo_sockaddr v4; - bool v6_present; - struct osmo_sockaddr v6; -}; - -int osmo_pfcp_ip_addrs_set(struct osmo_pfcp_ip_addrs *dst, const struct osmo_sockaddr *addr); - -/* 3GPP TS 29.244 8.2.38, IETF RFC 1035 3.1 */ -struct osmo_pfcp_ie_node_id { - enum osmo_pfcp_node_id_type type; - union { - struct osmo_sockaddr ip; - /* Fully qualified domain name in "dot" notation ("host.example.com") */ - char fqdn[254]; - }; -}; - -int osmo_pfcp_ie_node_id_to_str_buf(char *buf, size_t buflen, const struct osmo_pfcp_ie_node_id *node_id); -char *osmo_pfcp_ie_node_id_to_str_c(void *ctx, const struct osmo_pfcp_ie_node_id *node_id); - -bool osmo_pfcp_bits_get(const uint8_t *bits, unsigned int bitpos); -void osmo_pfcp_bits_set(uint8_t *bits, unsigned int bitpos, bool val); -int osmo_pfcp_bits_to_str_buf(char *buf, size_t buflen, const uint8_t *bits, const struct value_string *bit_strs); -char *osmo_pfcp_bits_to_str_c(void *ctx, const uint8_t *bits, const struct value_string *bit_str); - -/* 3GPP TS 29.244 8.2.25 - * Usage: - * struct osmo_pfcp_ie_up_function_features x; - * osmo_pfcp_bits_set(x.bits, OSMO_PFCP_UP_FEAT_BUNDL, true); - * if (osmo_pfcp_bits_get(x.bits, OSMO_PFCP_UP_FEAT_BUNDL)) - * foo(); - * printf("%s\n", osmo_pfcp_bits_to_str_c(x.bits, osmo_pfcp_up_feature_strs)); - */ -struct osmo_pfcp_ie_up_function_features { - uint8_t bits[6]; -}; - -/* 3GPP TS 29.244 8.2.58 - * struct osmo_pfcp_ie_cp_function_features x; - * osmo_pfcp_bits_set(x.bits, OSMO_PFCP_CP_FEAT_BUNDL, true); - * if (osmo_pfcp_bits_get(x.bits, OSMO_PFCP_CP_FEAT_BUNDL)) - * foo(); - * printf("%s\n", osmo_pfcp_bits_to_str_c(x.bits, osmo_pfcp_cp_feature_strs)); - */ -struct osmo_pfcp_ie_cp_function_features { - uint8_t bits[1]; -}; - -/* 3GPP TS 29.244 8.2.37 */ -struct osmo_pfcp_ie_f_seid { - uint64_t seid; - struct osmo_pfcp_ip_addrs ip_addr; -}; - -void osmo_pfcp_ie_f_seid_set(struct osmo_pfcp_ie_f_seid *f_seid, uint64_t seid, - const struct osmo_sockaddr *remote_addr); - -/* 3GPP TS 29.244 8.3.2 */ -struct osmo_pfcp_ie_f_teid { - bool choose_flag; - union { - struct { - uint32_t teid; - struct osmo_pfcp_ip_addrs ip_addr; - } fixed; - struct { - bool ipv4_addr; - bool ipv6_addr; - bool choose_id_present; - uint8_t choose_id; - } choose; - }; -}; - -/* 3GPP TS 29.244 8.2.62 */ -struct osmo_pfcp_ie_ue_ip_address { - bool chv6; - bool chv4; - bool ip_is_destination; - struct osmo_pfcp_ip_addrs ip_addr; - bool ipv6_prefix_delegation_bits_present; - uint8_t ipv6_prefix_delegation_bits; - bool ipv6_prefix_length_present; - uint8_t ipv6_prefix_length; -}; - -/* 3GPP TS 29.244 8.2.26. - * Usage: - * struct osmo_pfcp_ie_apply_action x; - * osmo_pfcp_bits_set(x.bits, OSMO_PFCP_APPLY_ACTION_FORW, true); - * if (osmo_pfcp_bits_get(x.bits, OSMO_PFCP_APPLY_ACTION_FORW)) - * foo(); - * printf("%s\n", osmo_pfcp_bits_to_str_c(x.bits, osmo_pfcp_apply_action_strs)); - */ -struct osmo_pfcp_ie_apply_action { - uint8_t bits[2]; -}; - -struct osmo_pfcp_ie_network_inst { - /* A domain name may have up to 253 characters; plus nul. */ - char str[253+1]; -}; - -struct osmo_pfcp_ie_activate_predefined_rules { - char str[256]; -}; - -/* 3GPP TS 29.244 8.2.56 */ -struct osmo_pfcp_ie_outer_header_creation { - /* desc_bits Usage: - * osmo_pfcp_bits_set(x.desc_bits, OSMO_PFCP_OUTER_HEADER_CREATION_GTP_U_UDP_IPV4, true); - * if (osmo_pfcp_bits_get(x.desc_bits, OSMO_PFCP_OUTER_HEADER_CREATION_GTP_U_UDP_IPV4)) - * foo(); - * printf("%s\n", osmo_pfcp_bits_to_str_c(x.desc_bits, osmo_pfcp_outer_header_creation_strs)); - */ - uint8_t desc_bits[2]; - bool teid_present; - uint32_t teid; - struct osmo_pfcp_ip_addrs ip_addr; - bool port_number_present; - uint16_t port_number; - bool c_tag_present; - uint32_t c_tag; - bool s_tag_present; - uint32_t s_tag; -}; - -/* 3GPP TS 29.244 8.2.64. */ -struct osmo_pfcp_ie_outer_header_removal { - enum osmo_pfcp_outer_header_removal_desc desc; - bool gtp_u_extension_header_del_present; - uint8_t gtp_u_extension_header_del_bits[1]; -}; diff --git a/include/osmocom/pfcp/pfcp_msg.h b/include/osmocom/pfcp/pfcp_msg.h deleted file mode 100644 index 2833408..0000000 --- a/include/osmocom/pfcp/pfcp_msg.h +++ /dev/null @@ -1,200 +0,0 @@ -/* PFCP message encoding and decoding */ -/* - * (C) 2021-2022 by sysmocom - s.f.m.c. GmbH info@sysmocom.de - * All Rights Reserved. - * - * Author: Neels Janosch Hofmeyr nhofmeyr@sysmocom.de - * - * SPDX-License-Identifier: GPL-2.0+ - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. - * - */ - -#pragma once - -#include <stdint.h> -#include <stdbool.h> -#include <inttypes.h> - -#include <osmocom/core/socket.h> -#include <osmocom/core/msgb.h> -#include <osmocom/core/fsm.h> - -#include <osmocom/pfcp/pfcp_proto.h> -#include <osmocom/pfcp/pfcp_ies_auto.h> -#include <osmocom/pfcp/pfcp_strs.h> - -struct msgb; -struct osmo_t16l16v_ie; -struct osmo_pfcp_msg; - -#define OSMO_PFCP_MSGB_ALLOC_SIZE 2048 - -#define OSMO_LOG_PFCP_MSG_SRC(M, LEVEL, file, line, FMT, ARGS...) do { \ - struct osmo_fsm_inst *_fi = (M) ? ((M)->ctx.session_fi ?: (M)->ctx.peer_fi) : NULL; \ - enum osmo_pfcp_cause *cause = osmo_pfcp_msg_cause(M); \ - if ((M)->h.seid_present) { \ - LOGPFSMSLSRC(_fi, DLPFCP, LEVEL, file, line, \ - "%s%s PFCP seq-%u SEID-0x%"PRIx64" %s%s%s: " FMT, \ - _fi ? "" : osmo_sockaddr_to_str_c(OTC_SELECT, &(M)->remote_addr), \ - (M)->rx ? "-rx->" : "<-tx-", (M)->h.sequence_nr, \ - (M)->h.seid, \ - osmo_pfcp_message_type_str((M)->h.message_type), cause ? ": " : "", \ - cause ? osmo_pfcp_cause_str(*cause) : "", ##ARGS); \ - } else { \ - LOGPFSMSLSRC(_fi, DLPFCP, LEVEL, file, line, \ - "%s%s PFCP seq-%u %s%s%s: " FMT, \ - _fi ? "" : osmo_sockaddr_to_str_c(OTC_SELECT, &(M)->remote_addr), \ - (M)->rx ? "-rx->" : "<-tx-", (M)->h.sequence_nr, \ - osmo_pfcp_message_type_str((M)->h.message_type), cause ? ": " : "", \ - cause ? osmo_pfcp_cause_str(*cause) : "", ##ARGS); \ - } \ - } while (0) - -#define OSMO_LOG_PFCP_MSG(M, LEVEL, FMT, ARGS...) \ - OSMO_LOG_PFCP_MSG_SRC(M, LEVEL, __FILE__, __LINE__, FMT, ##ARGS) - -struct osmo_pfcp_header_parsed { - uint8_t version; - enum osmo_pfcp_message_type message_type; - uint32_t sequence_nr; - bool priority_present; - uint8_t priority; - bool seid_present; - uint64_t seid; -}; - -/* For PFCP requests, notify when a PFCP response has arrived, or when the PFCP response timed out. - * When rx_resp == NULL, receiving a response timed out or the response could not be decoded. - * On error, errmsg may convey a human readable error message. - * Return 1 to also pass rx_resp to osmo_pfcp_endpoint->rx_msg(), return 0 to mark rx_resp handled and not pass it to - * rx_msg() (to save lookup iterations). Return negative on error, rx_resp is dropped. - * Find in req the original osmo_pfcp_msg instance; in req->ctx.priv, arbitrary user data may be passed. - * For example: - * - * static int on_foo_resp(struct osmo_pfcp_msg *req, struct osmo_pfcp_msg *rx_resp, const char *errmsg) - * { - * struct something *obj = req->ctx.priv; - * if (!rx_resp) { - * handle_error(); - * return 0; - * } - * handle_response(obj, rx_resp); - * return 0; - * } - * - * int do_request(struct something *obj) - * { - * struct osmo_pfcp_msg *req; - * req = osmo_pfcp_msg_alloc_tx(pfcp_ep, &upf_addr, &pfcp_ep->cfg.local_node_id, NULL, OSMO_PFCP_MSGT_FOO); - * req->h.seid_present = true; - * req->h.seid = remote_seid; - * req->ies.foo... = ...; - * req->ctx.on_resp = on_foo_resp; - * req->ctx.priv = obj; - * return osmo_pfcp_endpoint_tx(pfcp_ep, req); - * } - */ -typedef int (*osmo_pfcp_resp_cb)(struct osmo_pfcp_msg *req, struct osmo_pfcp_msg *rx_resp, const char *errmsg); - -struct osmo_pfcp_msg { - /* Peer's remote address. Received from this peer, or should be sent to this peer. */ - struct osmo_sockaddr remote_addr; - /* True when this message was received from a remote; false when this message is going to be sent. */ - bool rx; - /* True when this message is a Response message type; false if Request. This is set by - * osmo_pfcp_msg_decode() for received messages, and by osmo_pfcp_msg_alloc_tx */ - bool is_response; - - struct osmo_pfcp_header_parsed h; - - int ofs_cause; - int ofs_node_id; - - /* The union of decoded IEs from all supported PFCP message types. The union and its structure is defined in - * pfcp_ies_auto.h, which is generated by gen__pfcp_ies_auto.c. - */ - union osmo_pfcp_ies ies; - - /* Context information about this message, used for logging */ - struct { - /* Peer FSM instance that this message is received from / sent to. This can be set in the - * osmo_pfcp_endpoint->set_msg_ctx() implementation, up to the caller. If present, this is used for - * logging context, and can also be used by the caller to reduce lookup iterations. */ - struct osmo_fsm_inst *peer_fi; - struct osmo_use_count *peer_use_count; - const char *peer_use_token; - - /* Session FSM instance that this message is received from / sent to. This can be set in the - * osmo_pfcp_endpoint->set_msg_ctx() implementation, up to the caller. If present, this is used for - * logging context, and can also be used by the caller to reduce lookup iterations. */ - struct osmo_fsm_inst *session_fi; - struct osmo_use_count *session_use_count; - const char *session_use_token; - - osmo_pfcp_resp_cb resp_cb; - void *priv; - } ctx; - - /* When a message gets encoded, the encoded packet is cached here for possible retransmissions. */ - struct msgb *encoded; -}; - -/* Given a &osmo_pfcp_msg->ies pointer, return the &osmo_pfcp_msg. - * In the TLV API, only the 'ies' union is passed around as argument. This macro is useful in error callbacks to obtain - * the related osmo_pfcp_msg and thus the logging context pointers (ctx.peer_fi and ctx.session_fi). */ -#define OSMO_PFCP_MSG_FOR_IES(IES_P) ((struct osmo_pfcp_msg *)((char *)IES_P - offsetof(struct osmo_pfcp_msg, ies))) - -bool osmo_pfcp_msgtype_is_response(enum osmo_pfcp_message_type message_type); - -int osmo_pfcp_ie_f_teid_to_str_buf(char *buf, size_t len, const struct osmo_pfcp_ie_f_teid *ft); -char *osmo_pfcp_ie_f_teid_to_str_c(void *ctx, const struct osmo_pfcp_ie_f_teid *ft); - -int osmo_pfcp_msg_encode(struct msgb *msg, const struct osmo_pfcp_msg *pfcp_msg); - -int osmo_pfcp_msg_decode_header(struct osmo_gtlv_load *tlv, struct osmo_pfcp_msg *m, - const struct msgb *msg); -int osmo_pfcp_msg_decode_tlv(struct osmo_pfcp_msg *m, struct osmo_gtlv_load *tlv); - -struct osmo_pfcp_msg *osmo_pfcp_msg_alloc_rx(void *ctx, const struct osmo_sockaddr *remote_addr); -struct osmo_pfcp_msg *osmo_pfcp_msg_alloc_tx(void *ctx, const struct osmo_sockaddr *remote_addr, - const struct osmo_pfcp_ie_node_id *local_node_id, - const struct osmo_pfcp_msg *in_reply_to, - enum osmo_pfcp_message_type msg_type); - -void osmo_pfcp_msg_invalidate_ctx(struct osmo_pfcp_msg *m, struct osmo_fsm_inst *deleted_fi); - -void osmo_pfcp_msg_free(struct osmo_pfcp_msg *m); - -uint32_t osmo_pfcp_next_seq_nr(uint32_t *next_seq_nr_state); -uint64_t osmo_pfcp_next_seid(uint64_t *next_seid_state); - -int osmo_pfcp_ie_node_id_from_osmo_sockaddr(struct osmo_pfcp_ie_node_id *node_id, const struct osmo_sockaddr *os); -int osmo_pfcp_ie_node_id_to_osmo_sockaddr(const struct osmo_pfcp_ie_node_id *node_id, struct osmo_sockaddr *os); - -#define OSMO_PFCP_MSG_MEMB(M, OFS) ((OFS) <= 0 ? NULL : (void *)((uint8_t *)(M) + OFS)) - -static inline enum osmo_pfcp_cause *osmo_pfcp_msg_cause(const struct osmo_pfcp_msg *m) -{ - return OSMO_PFCP_MSG_MEMB(m, m->ofs_cause); -} - -static inline struct osmo_pfcp_ie_node_id *osmo_pfcp_msg_node_id(const struct osmo_pfcp_msg *m) -{ - return OSMO_PFCP_MSG_MEMB(m, m->ofs_node_id); -} - -int osmo_pfcp_msg_to_str_buf(char *buf, size_t buflen, const struct osmo_pfcp_msg *m); -char *osmo_pfcp_msg_to_str_c(void *ctx, const struct osmo_pfcp_msg *m); diff --git a/include/osmocom/pfcp/pfcp_proto.h b/include/osmocom/pfcp/pfcp_proto.h deleted file mode 100644 index d387b1b..0000000 --- a/include/osmocom/pfcp/pfcp_proto.h +++ /dev/null @@ -1,528 +0,0 @@ -/* 3GPP TS 29.244: Packet Forwarding Control Protocol */ -/* - * (C) 2021-2022 by sysmocom - s.f.m.c. GmbH info@sysmocom.de - * All Rights Reserved. - * - * Author: Neels Janosch Hofmeyr nhofmeyr@sysmocom.de - * - * SPDX-License-Identifier: GPL-2.0+ - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. - * - */ - -#pragma once - -#define OSMO_PFCP_PORT 8805 - -/* Section 7.3 / Table 7.3-1 */ -enum osmo_pfcp_message_type { - OSMO_PFCP_MSGT_NONE = 0, - - /* Node related messages */ - OSMO_PFCP_MSGT_HEARTBEAT_REQ = 1, - OSMO_PFCP_MSGT_HEARTBEAT_RESP = 2, - OSMO_PFCP_MSGT_PFD_MGMT_REQ = 3, - OSMO_PFCP_MSGT_PFD_MGMT_RESP = 4, - OSMO_PFCP_MSGT_ASSOC_SETUP_REQ = 5, - OSMO_PFCP_MSGT_ASSOC_SETUP_RESP = 6, - OSMO_PFCP_MSGT_ASSOC_UPDATE_REQ = 7, - OSMO_PFCP_MSGT_ASSOC_UPDATE_RESP = 8, - OSMO_PFCP_MSGT_ASSOC_RELEASE_REQ = 9, - OSMO_PFCP_MSGT_ASSOC_RELEASE_RESP = 10, - OSMO_PFCP_MSGT_VERSION_NOT_SUPP_RESP = 11, - OSMO_PFCP_MSGT_NODE_REPORT_REQ = 12, - OSMO_PFCP_MSGT_NODE_REPORT_RESP = 13, - OSMO_PFCP_MSGT_SESSION_SET_DEL_REQ = 14, - OSMO_PFCP_MSGT_SESSION_SET_DEL_RESP = 15, - - /* Session related messages */ - OSMO_PFCP_MSGT_SESSION_EST_REQ = 50, - OSMO_PFCP_MSGT_SESSION_EST_RESP = 51, - OSMO_PFCP_MSGT_SESSION_MOD_REQ = 52, - OSMO_PFCP_MSGT_SESSION_MOD_RESP = 53, - OSMO_PFCP_MSGT_SESSION_DEL_REQ = 54, - OSMO_PFCP_MSGT_SESSION_DEL_RESP = 55, - OSMO_PFCP_MSGT_SESSION_REP_REQ = 56, - OSMO_PFCP_MSGT_SESSION_REP_RESP = 57, -}; - -/* Section 8.1.2 / Table 8.1.2-1 */ -enum osmo_pfcp_iei { - OSMO_PFCP_INVALID_IEI = 0, - OSMO_PFCP_IEI_CREATE_PDR = 1, - OSMO_PFCP_IEI_PDI = 2, - OSMO_PFCP_IEI_CREATE_FAR = 3, - OSMO_PFCP_IEI_FORW_PARAMS = 4, - OSMO_PFCP_IEI_DUPL_PARAMS = 5, - OSMO_PFCP_IEI_CREATE_URR = 6, - OSMO_PFCP_IEI_CREATE_QER = 7, - OSMO_PFCP_IEI_CREATED_PDR = 8, - OSMO_PFCP_IEI_UPD_PDR = 9, - OSMO_PFCP_IEI_UPD_FAR = 10, - OSMO_PFCP_IEI_UPD_FORW_PARAMS = 11, - OSMO_PFCP_IEI_UPD_BAR_SESS_REP_RESP = 12, - OSMO_PFCP_IEI_UPD_URR = 13, - OSMO_PFCP_IEI_UPD_QER = 14, - OSMO_PFCP_IEI_REMOVE_PDR = 15, - OSMO_PFCP_IEI_REMOVE_FAR = 16, - OSMO_PFCP_IEI_REMOVE_URR = 17, - OSMO_PFCP_IEI_REMOVE_QER = 18, - OSMO_PFCP_IEI_CAUSE = 19, - OSMO_PFCP_IEI_SOURCE_IFACE = 20, - OSMO_PFCP_IEI_F_TEID = 21, - OSMO_PFCP_IEI_NETWORK_INST = 22, - OSMO_PFCP_IEI_SDF_FILTER = 23, - OSMO_PFCP_IEI_APPLICATION_ID = 24, - OSMO_PFCP_IEI_GATE_STATUS = 25, - OSMO_PFCP_IEI_MBR = 26, - OSMO_PFCP_IEI_GBR = 27, - OSMO_PFCP_IEI_QER_CORRELATION_ID = 28, - OSMO_PFCP_IEI_PRECEDENCE = 29, - OSMO_PFCP_IEI_TRANSPORT_LEVEL_MARKING = 30, - OSMO_PFCP_IEI_VOLUME_THRESH = 31, - OSMO_PFCP_IEI_TIME_THRESH = 32, - OSMO_PFCP_IEI_MONITORING_TIME = 33, - OSMO_PFCP_IEI_SUBSEQUENT_VOLUME_THRESH = 34, - OSMO_PFCP_IEI_SUBSEQUENT_TIME_THRESH = 35, - OSMO_PFCP_IEI_INACT_DETECTION_TIME = 36, - OSMO_PFCP_IEI_REPORTING_TRIGGERS = 37, - OSMO_PFCP_IEI_REDIRECT_INFO = 38, - OSMO_PFCP_IEI_REP_TYPE = 39, - OSMO_PFCP_IEI_OFFENDING_IE = 40, - OSMO_PFCP_IEI_FORW_POLICY = 41, - OSMO_PFCP_IEI_DESTINATION_IFACE = 42, - OSMO_PFCP_IEI_UP_FUNCTION_FEATURES = 43, - OSMO_PFCP_IEI_APPLY_ACTION = 44, - OSMO_PFCP_IEI_DL_DATA_SERVICE_INFO = 45, - OSMO_PFCP_IEI_DL_DATA_NOTIFICATION_DELAY = 46, - OSMO_PFCP_IEI_DL_BUFF_DURATION = 47, - OSMO_PFCP_IEI_DL_BUFF_SUGGESTED_PACKET_COUNT = 48, - OSMO_PFCP_IEI_PFCPSMREQ_FLAGS = 49, - OSMO_PFCP_IEI_PFCPSRRSP_FLAGS = 50, - OSMO_PFCP_IEI_LOAD_CTRL_INFO = 51, - OSMO_PFCP_IEI_SEQUENCE_NUMBER = 52, - OSMO_PFCP_IEI_METRIC = 53, - OSMO_PFCP_IEI_OVERLOAD_CTRL_INFO = 54, - OSMO_PFCP_IEI_TIMER = 55, - OSMO_PFCP_IEI_PDR_ID = 56, - OSMO_PFCP_IEI_F_SEID = 57, - OSMO_PFCP_IEI_APPLICATION_IDS_PFDS = 58, - OSMO_PFCP_IEI_PFD_CONTEXT = 59, - OSMO_PFCP_IEI_NODE_ID = 60, - OSMO_PFCP_IEI_PFD_CONTENTS = 61, - OSMO_PFCP_IEI_MEAS_METHOD = 62, - OSMO_PFCP_IEI_USAGE_REP_TRIGGER = 63, - OSMO_PFCP_IEI_MEAS_PERIOD = 64, - OSMO_PFCP_IEI_FQ_CSID = 65, - OSMO_PFCP_IEI_VOLUME_MEAS = 66, - OSMO_PFCP_IEI_DURATION_MEAS = 67, - OSMO_PFCP_IEI_APPLICATION_DETECTION_INFO = 68, - OSMO_PFCP_IEI_TIME_OF_FIRST_PACKET = 69, - OSMO_PFCP_IEI_TIME_OF_LAST_PACKET = 70, - OSMO_PFCP_IEI_QUOTA_HOLDING_TIME = 71, - OSMO_PFCP_IEI_DROPPED_DL_TRAFFIC_THRESH = 72, - OSMO_PFCP_IEI_VOLUME_QUOTA = 73, - OSMO_PFCP_IEI_TIME_QUOTA = 74, - OSMO_PFCP_IEI_START_TIME = 75, - OSMO_PFCP_IEI_END_TIME = 76, - OSMO_PFCP_IEI_QUERY_URR = 77, - OSMO_PFCP_IEI_USAGE_REP_SESS_MOD_RESP = 78, - OSMO_PFCP_IEI_USAGE_REP_SESS_DEL_RESP = 79, - OSMO_PFCP_IEI_USAGE_REP_SESS_REP_REQ = 80, - OSMO_PFCP_IEI_URR_ID = 81, - OSMO_PFCP_IEI_LINKED_URR_ID = 82, - OSMO_PFCP_IEI_DL_DATA_REP = 83, - OSMO_PFCP_IEI_OUTER_HEADER_CREATION = 84, - OSMO_PFCP_IEI_CREATE_BAR = 85, - OSMO_PFCP_IEI_UPD_BAR_SESS_MOD_REQ = 86, - OSMO_PFCP_IEI_REMOVE_BAR = 87, - OSMO_PFCP_IEI_BAR_ID = 88, - OSMO_PFCP_IEI_CP_FUNCTION_FEATURES = 89, - OSMO_PFCP_IEI_USAGE_INFO = 90, - OSMO_PFCP_IEI_APPLICATION_INST_ID = 91, - OSMO_PFCP_IEI_FLOW_INFO = 92, - OSMO_PFCP_IEI_UE_IP_ADDRESS = 93, - OSMO_PFCP_IEI_PACKET_RATE = 94, - OSMO_PFCP_IEI_OUTER_HEADER_REMOVAL = 95, - OSMO_PFCP_IEI_RECOVERY_TIME_STAMP = 96, - OSMO_PFCP_IEI_DL_FLOW_LEVEL_MARKING = 97, - OSMO_PFCP_IEI_HEADER_ENRICHMENT = 98, - OSMO_PFCP_IEI_ERROR_IND_REP = 99, - OSMO_PFCP_IEI_MEAS_INFO = 100, - OSMO_PFCP_IEI_NODE_REP_TYPE = 101, - OSMO_PFCP_IEI_USER_PLANE_PATH_FAILURE_REP = 102, - OSMO_PFCP_IEI_REMOTE_GTP_U_PEER = 103, - OSMO_PFCP_IEI_UR_SEQN = 104, - OSMO_PFCP_IEI_UPD_DUPL_PARAMS = 105, - OSMO_PFCP_IEI_ACTIVATE_PREDEFINED_RULES = 106, - OSMO_PFCP_IEI_DEACTIVATE_PREDEFINED_RULES = 107, - OSMO_PFCP_IEI_FAR_ID = 108, - OSMO_PFCP_IEI_QER_ID = 109, - OSMO_PFCP_IEI_OCI_FLAGS = 110, - OSMO_PFCP_IEI_PFCP_ASSOC_RELEASE_REQ = 111, - OSMO_PFCP_IEI_GRACEFUL_RELEASE_PERIOD = 112, - OSMO_PFCP_IEI_PDN_TYPE = 113, - OSMO_PFCP_IEI_FAILED_RULE_ID = 114, - OSMO_PFCP_IEI_TIME_QUOTA_MECHANISM = 115, - OSMO_PFCP_IEI_RESERVED = 116, - OSMO_PFCP_IEI_USER_PLANE_INACT_TIMER = 117, - OSMO_PFCP_IEI_AGGREGATED_URRS = 118, - OSMO_PFCP_IEI_MULTIPLIER = 119, - OSMO_PFCP_IEI_AGGREGATED_URR_ID = 120, - OSMO_PFCP_IEI_SUBSEQUENT_VOLUME_QUOTA = 121, - OSMO_PFCP_IEI_SUBSEQUENT_TIME_QUOTA = 122, - OSMO_PFCP_IEI_RQI = 123, - OSMO_PFCP_IEI_QFI = 124, - OSMO_PFCP_IEI_QUERY_URR_REFERENCE = 125, - OSMO_PFCP_IEI_ADDITIONAL_USAGE_REPS_INFO = 126, - OSMO_PFCP_IEI_CREATE_TRAFFIC_ENDPOINT = 127, - OSMO_PFCP_IEI_CREATED_TRAFFIC_ENDPOINT = 128, - OSMO_PFCP_IEI_UPD_TRAFFIC_ENDPOINT = 129, - OSMO_PFCP_IEI_REMOVE_TRAFFIC_ENDPOINT = 130, - OSMO_PFCP_IEI_TRAFFIC_ENDPOINT_ID = 131, - OSMO_PFCP_IEI_ETHERNET_PACKET_FILTER = 132, - OSMO_PFCP_IEI_MAC_ADDRESS = 133, - OSMO_PFCP_IEI_C_TAG = 134, - OSMO_PFCP_IEI_S_TAG = 135, - OSMO_PFCP_IEI_ETHERTYPE = 136, - OSMO_PFCP_IEI_PROXYING = 137, - OSMO_PFCP_IEI_ETHERNET_FILTER_ID = 138, - OSMO_PFCP_IEI_ETHERNET_FILTER_PROPERTIES = 139, - OSMO_PFCP_IEI_SUGGESTED_BUFF_PACKETS_COUNT = 140, - OSMO_PFCP_IEI_USER_ID = 141, - OSMO_PFCP_IEI_ETHERNET_PDU_SESS_INFO = 142, - OSMO_PFCP_IEI_ETHERNET_TRAFFIC_INFO = 143, - OSMO_PFCP_IEI_MAC_ADDRS_DETECTED = 144, - OSMO_PFCP_IEI_MAC_ADDRS_REMOVED = 145, - OSMO_PFCP_IEI_ETHERNET_INACT_TIMER = 146, - OSMO_PFCP_IEI_ADDITIONAL_MONITORING_TIME = 147, - OSMO_PFCP_IEI_EVENT_QUOTA = 148, - OSMO_PFCP_IEI_EVENT_THRESH = 149, - OSMO_PFCP_IEI_SUBSEQUENT_EVENT_QUOTA = 150, - OSMO_PFCP_IEI_SUBSEQUENT_EVENT_THRESH = 151, - OSMO_PFCP_IEI_TRACE_INFO = 152, - OSMO_PFCP_IEI_FRAMED_ROUTE = 153, - OSMO_PFCP_IEI_FRAMED_ROUTING = 154, - OSMO_PFCP_IEI_FRAMED_IPV6_ROUTE = 155, - OSMO_PFCP_IEI_TIME_STAMP = 156, - OSMO_PFCP_IEI_AVERAGING_WINDOW = 157, - OSMO_PFCP_IEI_PAGING_POLICY_INDICATOR = 158, - OSMO_PFCP_IEI_APN_DNN = 159, - OSMO_PFCP_IEI_3GPP_IFACE_TYPE = 160, - OSMO_PFCP_IEI_PFCPSRREQ_FLAGS = 161, - OSMO_PFCP_IEI_PFCPAUREQ_FLAGS = 162, - OSMO_PFCP_IEI_ACTIVATION_TIME = 163, - OSMO_PFCP_IEI_DEACTIVATION_TIME = 164, - OSMO_PFCP_IEI_CREATE_MAR = 165, - OSMO_PFCP_IEI_3GPP_ACCESS_FORW_ACTION_INFO = 166, - OSMO_PFCP_IEI_NON_3GPP_ACCESS_FORW_ACTION_INFO = 167, - OSMO_PFCP_IEI_REMOVE_MAR = 168, - OSMO_PFCP_IEI_UPD_MAR = 169, - OSMO_PFCP_IEI_MAR_ID = 170, - OSMO_PFCP_IEI_STEERING_FUNCTIONALITY = 171, - OSMO_PFCP_IEI_STEERING_MODE = 172, - OSMO_PFCP_IEI_WEIGHT = 173, - OSMO_PFCP_IEI_PRIORITY = 174, - OSMO_PFCP_IEI_UPD_3GPP_ACCESS_FORW_ACTION_INFO = 175, - OSMO_PFCP_IEI_UPD_NON_3GPP_ACCESS_FORW_ACTION_INFO = 176, - OSMO_PFCP_IEI_UE_IP_ADDRESS_POOL_IDENTITY = 177, - OSMO_PFCP_IEI_ALTERNATIVE_SMF_IP_ADDRESS = 178, - OSMO_PFCP_IEI_PACKET_REPLICATION_AND_DETECTION_CARRY_ON_INFO = 179, - OSMO_PFCP_IEI_SMF_SET_ID = 180, - OSMO_PFCP_IEI_QUOTA_VALIDITY_TIME = 181, - OSMO_PFCP_IEI_NUMBER_OF_REPS = 182, - OSMO_PFCP_IEI_PFCP_SESS_RETENTION_INFO_IN_ASSOC_SETUP_REQ = 183, - OSMO_PFCP_IEI_PFCPASRSP_FLAGS = 184, - OSMO_PFCP_IEI_CP_ENTITY_IP_ADDRESS = 185, - OSMO_PFCP_IEI_PFCPSEREQ_FLAGS = 186, - OSMO_PFCP_IEI_USER_PLANE_PATH_RECOVERY_REP = 187, - OSMO_PFCP_IEI_IP_MULTICAST_ADDR_INFO_IN_SESS_EST_REQ = 188, - OSMO_PFCP_IEI_JOIN_IP_MULTICAST_INFO_IE_IN_USAGE_REP = 189, - OSMO_PFCP_IEI_LEAVE_IP_MULTICAST_INFO_IE_IN_USAGE_REP = 190, - OSMO_PFCP_IEI_IP_MULTICAST_ADDRESS = 191, - OSMO_PFCP_IEI_SOURCE_IP_ADDRESS = 192, - OSMO_PFCP_IEI_PACKET_RATE_STATUS = 193, - OSMO_PFCP_IEI_CREATE_BRIDGE_INFO_FOR_TSC = 194, - OSMO_PFCP_IEI_CREATED_BRIDGE_INFO_FOR_TSC = 195, - OSMO_PFCP_IEI_DS_TT_PORT_NUMBER = 196, - OSMO_PFCP_IEI_NW_TT_PORT_NUMBER = 197, - OSMO_PFCP_IEI_TSN_BRIDGE_ID = 198, - OSMO_PFCP_IEI_TSC_MGMT_INFO_IE_IN_SESS_MOD_REQ = 199, - OSMO_PFCP_IEI_TSC_MGMT_INFO_IE_IN_SESS_MOD_RESP = 200, - OSMO_PFCP_IEI_TSC_MGMT_INFO_IE_IN_SESS_REP_REQ = 201, - OSMO_PFCP_IEI_PORT_MGMT_INFO_CONTAINER = 202, - OSMO_PFCP_IEI_CLOCK_DRIFT_CTRL_INFO = 203, - OSMO_PFCP_IEI_REQUESTED_CLOCK_DRIFT_INFO = 204, - OSMO_PFCP_IEI_CLOCK_DRIFT_REP = 205, - OSMO_PFCP_IEI_TSN_TIME_DOMAIN_NUMBER = 206, - OSMO_PFCP_IEI_TIME_OFFSET_THRESH = 207, - OSMO_PFCP_IEI_CUMULATIVE_RATERATIO_THRESH = 208, - OSMO_PFCP_IEI_TIME_OFFSET_MEAS = 209, - OSMO_PFCP_IEI_CUMULATIVE_RATERATIO_MEAS = 210, - OSMO_PFCP_IEI_REMOVE_SRR = 211, - OSMO_PFCP_IEI_CREATE_SRR = 212, - OSMO_PFCP_IEI_UPD_SRR = 213, - OSMO_PFCP_IEI_SESS_REP = 214, - OSMO_PFCP_IEI_SRR_ID = 215, - OSMO_PFCP_IEI_ACCESS_AVAIL_CTRL_INFO = 216, - OSMO_PFCP_IEI_REQUESTED_ACCESS_AVAIL_INFO = 217, - OSMO_PFCP_IEI_ACCESS_AVAIL_REP = 218, - OSMO_PFCP_IEI_ACCESS_AVAIL_INFO = 219, - OSMO_PFCP_IEI_PROVIDE_ATSSS_CTRL_INFO = 220, - OSMO_PFCP_IEI_ATSSS_CTRL_PARAMS = 221, - OSMO_PFCP_IEI_MPTCP_CTRL_INFO = 222, - OSMO_PFCP_IEI_ATSSS_LL_CTRL_INFO = 223, - OSMO_PFCP_IEI_PMF_CTRL_INFO = 224, - OSMO_PFCP_IEI_MPTCP_PARAMS = 225, - OSMO_PFCP_IEI_ATSSS_LL_PARAMS = 226, - OSMO_PFCP_IEI_PMF_PARAMS = 227, - OSMO_PFCP_IEI_MPTCP_ADDRESS_INFO = 228, - OSMO_PFCP_IEI_UE_LINK_SPECIFIC_IP_ADDRESS = 229, - OSMO_PFCP_IEI_PMF_ADDRESS_INFO = 230, - OSMO_PFCP_IEI_ATSSS_LL_INFO = 231, - OSMO_PFCP_IEI_DATA_NETWORK_ACCESS_IDENTIFIER = 232, - OSMO_PFCP_IEI_UE_IP_ADDRESS_POOL_INFO = 233, - OSMO_PFCP_IEI_AVERAGE_PACKET_DELAY = 234, - OSMO_PFCP_IEI_MIN_PACKET_DELAY = 235, - OSMO_PFCP_IEI_MAX_PACKET_DELAY = 236, - OSMO_PFCP_IEI_QOS_REP_TRIGGER = 237, - OSMO_PFCP_IEI_GTP_U_PATH_QOS_CTRL_INFO = 238, - OSMO_PFCP_IEI_GTP_U_PATH_QOS_REP_NODE_REP_REQ = 239, - OSMO_PFCP_IEI_QOS_INFO_IN_GTP_U_PATH_QOS_REP = 240, - OSMO_PFCP_IEI_GTP_U_PATH_IFACE_TYPE = 241, - OSMO_PFCP_IEI_QOS_MONITORING_PER_QOS_FLOW_CTRL_INFO = 242, - OSMO_PFCP_IEI_REQUESTED_QOS_MONITORING = 243, - OSMO_PFCP_IEI_REPORTING_FREQUENCY = 244, - OSMO_PFCP_IEI_PACKET_DELAY_THRESHOLDS = 245, - OSMO_PFCP_IEI_MIN_WAIT_TIME = 246, - OSMO_PFCP_IEI_QOS_MONITORING_REP = 247, - OSMO_PFCP_IEI_QOS_MONITORING_MEAS = 248, - OSMO_PFCP_IEI_MT_EDT_CTRL_INFO = 249, - OSMO_PFCP_IEI_DL_DATA_PACKETS_SIZE = 250, - OSMO_PFCP_IEI_QER_CTRL_INDICATIONS = 251, - OSMO_PFCP_IEI_PACKET_RATE_STATUS_REP = 252, - OSMO_PFCP_IEI_NF_INST_ID = 253, - OSMO_PFCP_IEI_ETHERNET_CONTEXT_INFO = 254, - OSMO_PFCP_IEI_REDUNDANT_TRANSMISSION_PARAMS = 255, - OSMO_PFCP_IEI_UPDATED_PDR = 256, - OSMO_PFCP_IEI_S_NSSAI = 257, - OSMO_PFCP_IEI_IP_VERSION = 258, - OSMO_PFCP_IEI_PFCPASREQ_FLAGS = 259, - OSMO_PFCP_IEI_DATA_STATUS = 260, - OSMO_PFCP_IEI_PROVIDE_RDS_CONF_INFO = 261, - OSMO_PFCP_IEI_RDS_CONF_INFO = 262, - OSMO_PFCP_IEI_QUERY_PACKET_RATE_STATUS_IE_IN_SESS_MOD_REQ = 263, - OSMO_PFCP_IEI_PACKET_RATE_STATUS_REP_IE_IN_SESS_MOD_RESP = 264, - OSMO_PFCP_IEI_MPTCP_APPLICABLE_IND = 265, - OSMO_PFCP_IEI_BRIDGE_MGMT_INFO_CONTAINER = 266, - OSMO_PFCP_IEI_UE_IP_ADDRESS_USAGE_INFO = 267, - OSMO_PFCP_IEI_NUMBER_OF_UE_IP_ADDRS = 268, - OSMO_PFCP_IEI_VALIDITY_TIMER = 269, - OSMO_PFCP_IEI_REDUNDANT_TRANSMISSION_FORW_PARAMS = 270, - OSMO_PFCP_IEI_TRANSPORT_DELAY_REPORTING = 271, -}; - -/* Section 8.2.1 / Table 8.2.1-1 */ -enum osmo_pfcp_cause { - OSMO_PFCP_CAUSE_RESERVED = 0, - OSMO_PFCP_CAUSE_REQUEST_ACCEPTED = 1, - OSMO_PFCP_CAUSE_MORE_USAGE_REPORT_TO_SEND = 2, - OSMO_PFCP_CAUSE_REQUEST_REJECTED = 64, - OSMO_PFCP_CAUSE_SESSION_CTX_NOT_FOUND = 65, - OSMO_PFCP_CAUSE_MANDATORY_IE_MISSING = 66, - OSMO_PFCP_CAUSE_CONDITIONAL_IE_MISSING = 67, - OSMO_PFCP_CAUSE_INVALID_LENGTH = 68, - OSMO_PFCP_CAUSE_MANDATORY_IE_INCORRECT = 69, - OSMO_PFCP_CAUSE_INVALID_FORW_POLICY = 70, - OSMO_PFCP_CAUSE_INVALID_F_TEID_ALLOC_OPTION = 71, - OSMO_PFCP_CAUSE_NO_ESTABLISHED_PFCP_ASSOC = 72, - OSMO_PFCP_CAUSE_RULE_CREATION_MOD_FAILURE = 73, - OSMO_PFCP_CAUSE_PFCP_ENTITY_IN_CONGESTION = 74, - OSMO_PFCP_CAUSE_NO_RESOURCES_AVAILABLE = 75, - OSMO_PFCP_CAUSE_SERVICE_NOT_SUPPORTED = 76, - OSMO_PFCP_CAUSE_SYSTEM_FAILURE = 77, - OSMO_PFCP_CAUSE_REDIRECTION_REQUESTED = 78, - OSMO_PFCP_CAUSE_ALL_DYNAMIC_ADDRESSES_ARE_OCCUPIED = 79, -}; - -/* Section 8.2.38 */ -enum osmo_pfcp_node_id_type { - OSMO_PFCP_NODE_ID_T_IPV4 = 0, - OSMO_PFCP_NODE_ID_T_IPV6 = 1, - OSMO_PFCP_NODE_ID_T_FQDN = 2, -}; - -enum osmo_pfcp_3gpp_iface_type { - OSMO_PFCP_3GPP_IFACE_TYPE_S1_U = 0, - OSMO_PFCP_3GPP_IFACE_TYPE_S5_S8_U = 1, - OSMO_PFCP_3GPP_IFACE_TYPE_S4_U = 2, - OSMO_PFCP_3GPP_IFACE_TYPE_S11_U = 3, - OSMO_PFCP_3GPP_IFACE_TYPE_S12_U = 4, - OSMO_PFCP_3GPP_IFACE_TYPE_GN_GP_U = 5, - OSMO_PFCP_3GPP_IFACE_TYPE_S2A_U = 6, - OSMO_PFCP_3GPP_IFACE_TYPE_S2B_U = 7, - OSMO_PFCP_3GPP_IFACE_TYPE_ENODEB_GTP_U_INTERFACE_FOR_DL_DATA_FORWARDING = 8, - OSMO_PFCP_3GPP_IFACE_TYPE_ENODEB_GTP_U_INTERFACE_FOR_UL_DATA_FORWARDING = 9, - OSMO_PFCP_3GPP_IFACE_TYPE_SGW_UPF_GTP_U_INTERFACE_FOR_DL_DATA_FORWARDING = 10, - OSMO_PFCP_3GPP_IFACE_TYPE_N3_3GPP_ACCESS = 11, - OSMO_PFCP_3GPP_IFACE_TYPE_N3_TRUSTED_NON_3GPP_ACCESS = 12, - OSMO_PFCP_3GPP_IFACE_TYPE_N3_UNTRUSTED_NON_3GPP_ACCESS = 13, - OSMO_PFCP_3GPP_IFACE_TYPE_N3_FOR_DATA_FORWARDING = 14, - OSMO_PFCP_3GPP_IFACE_TYPE_N9 = 15, - OSMO_PFCP_3GPP_IFACE_TYPE_SGI = 16, - OSMO_PFCP_3GPP_IFACE_TYPE_N6 = 17, - OSMO_PFCP_3GPP_IFACE_TYPE_N19 = 18, - OSMO_PFCP_3GPP_IFACE_TYPE_S8_U = 19, - OSMO_PFCP_3GPP_IFACE_TYPE_GP_U = 20, -}; - -enum osmo_pfcp_source_iface { - OSMO_PFCP_SOURCE_IFACE_ACCESS = 0, - OSMO_PFCP_SOURCE_IFACE_CORE = 1, - OSMO_PFCP_SOURCE_IFACE_SGI_LAN_N6_LAN = 2, - OSMO_PFCP_SOURCE_IFACE_CP_FUNCTION = 3, - OSMO_PFCP_SOURCE_IFACE_5G_VN_INTERNAL = 4, -}; - -enum osmo_pfcp_dest_iface { - OSMO_PFCP_DEST_IFACE_ACCESS = 0, - OSMO_PFCP_DEST_IFACE_CORE = 1, - OSMO_PFCP_DEST_IFACE_SGI_LAN_N6_LAN = 2, - OSMO_PFCP_DEST_IFACE_CP_FUNCTION = 3, - OSMO_PFCP_DEST_IFACE_LI_FUNCTION = 4, - OSMO_PFCP_DEST_IFACE_5G_VN_INTERNAL = 5, -}; - -/* The enum values correspond to the bit index in the supported features bitmask in the PFCP UP Function Features IE. - * 0 means first octet and first bit, "Octet 5 Bit 1" as in spec; - * 7 means first octet last bit, "Octet 5 Bit 8"; - * 8 means second octet first bit, "Octet 6 Bit 1"; - * and so on. - * Intended for use with osmo_pfcp_bits_get(), osmo_pfcp_bits_set(), osmo_pfcp_bits_to_str_c(). - */ -enum osmo_pfcp_up_feature { - OSMO_PFCP_UP_FEAT_BUCP = 0, - OSMO_PFCP_UP_FEAT_DDND, - OSMO_PFCP_UP_FEAT_DLBD, - OSMO_PFCP_UP_FEAT_TRST, - OSMO_PFCP_UP_FEAT_FTUP, - OSMO_PFCP_UP_FEAT_PFDM, - OSMO_PFCP_UP_FEAT_HEEU, - OSMO_PFCP_UP_FEAT_TREU, - OSMO_PFCP_UP_FEAT_EMPU, - OSMO_PFCP_UP_FEAT_PDIU, - OSMO_PFCP_UP_FEAT_UDBC, - OSMO_PFCP_UP_FEAT_QUOAC, - OSMO_PFCP_UP_FEAT_TRACE, - OSMO_PFCP_UP_FEAT_FRRT, - OSMO_PFCP_UP_FEAT_PFDE, - OSMO_PFCP_UP_FEAT_EPFAR, - OSMO_PFCP_UP_FEAT_DPDRA, - OSMO_PFCP_UP_FEAT_ADPDP, - OSMO_PFCP_UP_FEAT_UEIP, - OSMO_PFCP_UP_FEAT_SSET, - OSMO_PFCP_UP_FEAT_MNOP, - OSMO_PFCP_UP_FEAT_MTE, - OSMO_PFCP_UP_FEAT_BUNDL, - OSMO_PFCP_UP_FEAT_GCOM, - OSMO_PFCP_UP_FEAT_MPAS, - OSMO_PFCP_UP_FEAT_RTTL, - OSMO_PFCP_UP_FEAT_VTIME, - OSMO_PFCP_UP_FEAT_NORP, - OSMO_PFCP_UP_FEAT_IP6PL, - OSMO_PFCP_UP_FEAT_TSCU, - OSMO_PFCP_UP_FEAT_MPTCP, - OSMO_PFCP_UP_FEAT_ATSSSLL, - OSMO_PFCP_UP_FEAT_QFQM, - OSMO_PFCP_UP_FEAT_GPQM, - OSMO_PFCP_UP_FEAT_MTEDT, - OSMO_PFCP_UP_FEAT_CIOT, - OSMO_PFCP_UP_FEAT_ETHAR, - OSMO_PFCP_UP_FEAT_DDDS, - OSMO_PFCP_UP_FEAT_RDS, - OSMO_PFCP_UP_FEAT_RTTWP, -}; - -/* The enum values correspond to the bit index in the supported features bitmask in the PFCP CP Function Features IE. - * 0 means first octet and first bit, "Octet 5 Bit 1" as in spec; - * 7 means first octet last bit, "Octet 5 Bit 8"; - * 8 means second octet first bit, "Octet 6 Bit 1"; - * and so on. - * Intended for use with osmo_pfcp_bits_get(), osmo_pfcp_bits_set(), osmo_pfcp_bits_to_str_c(). - */ -enum osmo_pfcp_cp_feature { - OSMO_PFCP_CP_FEAT_LOAD = 0, - OSMO_PFCP_CP_FEAT_OVRL, - OSMO_PFCP_CP_FEAT_EPFAR, - OSMO_PFCP_CP_FEAT_SSET, - OSMO_PFCP_CP_FEAT_BUNDL, - OSMO_PFCP_CP_FEAT_MPAS, - OSMO_PFCP_CP_FEAT_ARDR, - OSMO_PFCP_CP_FEAT_UIAUR, -}; - -/* The enum values correspond to the bit index in the PFCP Apply Action IE. - * 0 means first octet and first bit, "Octet 5 Bit 1" as in spec; - * 7 means first octet last bit, "Octet 5 Bit 8"; - * 8 means second octet first bit, "Octet 6 Bit 1"; - * and so on. - * Intended for use with osmo_pfcp_bits_get(), osmo_pfcp_bits_set(), osmo_pfcp_bits_to_str_c(). - */ -enum osmo_pfcp_apply_action { - OSMO_PFCP_APPLY_ACTION_DROP = 0, - OSMO_PFCP_APPLY_ACTION_FORW, - OSMO_PFCP_APPLY_ACTION_BUFF, - OSMO_PFCP_APPLY_ACTION_NOCP, - OSMO_PFCP_APPLY_ACTION_DUPL, - OSMO_PFCP_APPLY_ACTION_IPMA, - OSMO_PFCP_APPLY_ACTION_IPMD, - OSMO_PFCP_APPLY_ACTION_DFRT, - OSMO_PFCP_APPLY_ACTION_EDRT, - OSMO_PFCP_APPLY_ACTION_BDPN, - OSMO_PFCP_APPLY_ACTION_DDPN, -}; - -/* The enum values correspond to the bit index in the description bitmask in the PFCP Outer Header Creation IE. - * 0 means first octet and first bit, "Octet 5 Bit 1" as in spec; - * 7 means first octet last bit, "Octet 5 Bit 8"; - * 8 means second octet first bit, "Octet 6 Bit 1"; - * and so on. - * Intended for use with osmo_pfcp_bits_get(), osmo_pfcp_bits_set(), osmo_pfcp_bits_to_str_c(). - */ -enum osmo_pfcp_outer_header_creation { - OSMO_PFCP_OUTER_HEADER_CREATION_GTP_U_UDP_IPV4 = 0, - OSMO_PFCP_OUTER_HEADER_CREATION_GTP_U_UDP_IPV6, - OSMO_PFCP_OUTER_HEADER_CREATION_UDP_IPV4, - OSMO_PFCP_OUTER_HEADER_CREATION_UDP_IPV6, - OSMO_PFCP_OUTER_HEADER_CREATION_IPV4, - OSMO_PFCP_OUTER_HEADER_CREATION_IPV6, - OSMO_PFCP_OUTER_HEADER_CREATION_C_TAG, - OSMO_PFCP_OUTER_HEADER_CREATION_S_TAG, - OSMO_PFCP_OUTER_HEADER_CREATION_N19_INDICATION, - OSMO_PFCP_OUTER_HEADER_CREATION_N6_INDICATION, -}; - -/* 3GPP TS 29.244 8.2.64 */ -enum osmo_pfcp_outer_header_removal_desc { - OSMO_PFCP_OUTER_HEADER_REMOVAL_GTP_U_UDP_IPV4 = 0, - OSMO_PFCP_OUTER_HEADER_REMOVAL_GTP_U_UDP_IPV6 = 1, - OSMO_PFCP_OUTER_HEADER_REMOVAL_UDP_IPV4 = 2, - OSMO_PFCP_OUTER_HEADER_REMOVAL_UDP_IPV6 = 3, - OSMO_PFCP_OUTER_HEADER_REMOVAL_IPV4 = 4, - OSMO_PFCP_OUTER_HEADER_REMOVAL_IPV6 = 5, - OSMO_PFCP_OUTER_HEADER_REMOVAL_GTP_U_UDP_IP = 6, - OSMO_PFCP_OUTER_HEADER_REMOVAL_VLAN_S_TAG = 7, - OSMO_PFCP_OUTER_HEADER_REMOVAL_S_TAG_AND_C_TAG = 8, -}; diff --git a/include/osmocom/pfcp/pfcp_strs.h b/include/osmocom/pfcp/pfcp_strs.h deleted file mode 100644 index d0b106a..0000000 --- a/include/osmocom/pfcp/pfcp_strs.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * (C) 2021-2022 by sysmocom - s.f.m.c. GmbH info@sysmocom.de - * All Rights Reserved. - * - * Author: Neels Janosch Hofmeyr nhofmeyr@sysmocom.de - * - * SPDX-License-Identifier: GPL-2.0+ - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. - * - */ - -#pragma once - -#include <osmocom/core/utils.h> - -#include <osmocom/pfcp/pfcp_proto.h> - -extern const struct value_string osmo_pfcp_message_type_strs[]; -static inline const char *osmo_pfcp_message_type_str(enum osmo_pfcp_message_type val) -{ - return get_value_string(osmo_pfcp_message_type_strs, val); -} - -extern const struct value_string osmo_pfcp_iei_strs[]; -static inline const char *osmo_pfcp_iei_str(enum osmo_pfcp_iei val) -{ - return get_value_string(osmo_pfcp_iei_strs, val); -} - -extern const struct value_string osmo_pfcp_cause_strs[]; -static inline const char *osmo_pfcp_cause_str(enum osmo_pfcp_cause val) -{ - return get_value_string(osmo_pfcp_cause_strs, val); -} - -extern const struct value_string osmo_pfcp_up_feature_strs[]; -static inline const char *osmo_pfcp_up_feature_str(enum osmo_pfcp_up_feature val) -{ - return get_value_string(osmo_pfcp_up_feature_strs, val); -} - -extern const struct value_string osmo_pfcp_cp_feature_strs[]; -static inline const char *osmo_pfcp_cp_feature_str(enum osmo_pfcp_cp_feature val) -{ - return get_value_string(osmo_pfcp_cp_feature_strs, val); -} - -extern const struct value_string osmo_pfcp_apply_action_strs[]; -static inline const char *osmo_pfcp_apply_action_str(enum osmo_pfcp_apply_action val) -{ - return get_value_string(osmo_pfcp_apply_action_strs, val); -} - -extern const struct value_string osmo_pfcp_outer_header_creation_strs[]; -static inline const char *osmo_pfcp_outer_header_creation_str(enum osmo_pfcp_outer_header_creation val) -{ - return get_value_string(osmo_pfcp_outer_header_creation_strs, val); -} - -extern const struct value_string osmo_pfcp_outer_header_removal_desc_strs[]; -static inline const char *osmo_pfcp_outer_header_removal_desc_str(enum osmo_pfcp_outer_header_removal_desc val) -{ - return get_value_string(osmo_pfcp_outer_header_removal_desc_strs, val); -} - -extern const struct value_string osmo_pfcp_source_iface_strs[]; -static inline const char *osmo_pfcp_source_iface_str(enum osmo_pfcp_source_iface val) -{ - return get_value_string(osmo_pfcp_source_iface_strs, val); -} - -extern const struct value_string osmo_pfcp_dest_iface_strs[]; -static inline const char *osmo_pfcp_dest_iface_str(enum osmo_pfcp_dest_iface val) -{ - return get_value_string(osmo_pfcp_dest_iface_strs, val); -} - -extern const struct value_string osmo_pfcp_3gpp_iface_type_strs[]; -static inline const char *osmo_pfcp_3gpp_iface_type_str(enum osmo_pfcp_3gpp_iface_type val) -{ - return get_value_string(osmo_pfcp_3gpp_iface_type_strs, val); -} diff --git a/src/Makefile.am b/src/Makefile.am index 78c8adb..a8ba763 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,3 @@ SUBDIRS = \ - libosmo-pfcp \ osmo-upf \ $(NULL) diff --git a/src/libosmo-pfcp/Makefile.am b/src/libosmo-pfcp/Makefile.am deleted file mode 100644 index eb8c78f..0000000 --- a/src/libosmo-pfcp/Makefile.am +++ /dev/null @@ -1,55 +0,0 @@ -AM_CPPFLAGS = \ - $(all_includes) \ - -I$(top_srcdir)/include \ - -I$(top_builddir)/include \ - -I$(top_builddir) \ - -I$(builddir) \ - $(NULL) - -AM_CFLAGS = \ - -Wall \ - $(LIBOSMOCORE_CFLAGS) \ - $(LIBOSMOGTLV_CFLAGS) \ - $(LIBOSMOVTY_CFLAGS) \ - $(COVERAGE_CFLAGS) \ - $(NULL) - -AM_LDFLAGS = \ - $(LIBOSMOCORE_LIBS) \ - $(LIBOSMOGTLV_LIBS) \ - $(LIBOSMOVTY_LIBS) \ - $(COVERAGE_LDFLAGS) \ - $(NULL) - -noinst_LIBRARIES = \ - libosmo-pfcp.a \ - $(NULL) - -libosmo_pfcp_a_SOURCES = \ - pfcp_endpoint.c \ - pfcp_ies_custom.c \ - pfcp_msg.c \ - pfcp_strs.c \ - \ - pfcp_ies_auto.c \ - $(NULL) - -BUILT_SOURCES = \ - pfcp_ies_auto.c \ - $(NULL) - -CLEANFILES = \ - pfcp_ies_auto.c \ - $(NULL) - -pfcp_ies_auto.c: $(srcdir)/gen__pfcp_ies_auto.c - $(MAKE) gen__pfcp_ies_auto - $(builddir)/gen__pfcp_ies_auto c > $(builddir)/pfcp_ies_auto.c - -noinst_PROGRAMS = \ - gen__pfcp_ies_auto \ - $(NULL) - -gen__pfcp_ies_auto_SOURCES = \ - gen__pfcp_ies_auto.c \ - $(NULL) diff --git a/src/libosmo-pfcp/gen__pfcp_ies_auto.c b/src/libosmo-pfcp/gen__pfcp_ies_auto.c deleted file mode 100644 index 0dfb43c..0000000 --- a/src/libosmo-pfcp/gen__pfcp_ies_auto.c +++ /dev/null @@ -1,365 +0,0 @@ -/* Tool to generate C source code of structs and IE arrays for de- and encoding PFCP messages. */ -/* - * (C) 2021-2022 by sysmocom - s.f.m.c. GmbH info@sysmocom.de - * All Rights Reserved. - * - * Author: Neels Janosch Hofmeyr nhofmeyr@sysmocom.de - * - * SPDX-License-Identifier: GPL-2.0+ - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. - * - */ - -#include <stdbool.h> -#include <stdio.h> -#include <osmocom/core/utils.h> -#include <osmocom/core/linuxlist.h> -#include <osmocom/core/talloc.h> -#include <osmocom/gtlv/gtlv_gen.h> - -#define O OSMO_GTLV_GEN_O -#define M OSMO_GTLV_GEN_M -#define O_MULTI OSMO_GTLV_GEN_O_MULTI -#define M_MULTI OSMO_GTLV_GEN_M_MULTI -#define ALL_FROM_NAME osmo_gtlv_gen_ie_auto - -#define Ms(MEMB_NAME) M(MEMB_NAME, #MEMB_NAME) -#define Os(MEMB_NAME) O(MEMB_NAME, #MEMB_NAME) -#define O_MULTIs(N, MEMB_NAME) O_MULTI(N, MEMB_NAME, #MEMB_NAME) -#define M_MULTIs(N, M, MEMB_NAME) M_MULTI(N, M, MEMB_NAME, #MEMB_NAME) - -static const struct osmo_gtlv_gen_ie recovery_time_stamp = { - "uint32_t", - .dec_enc = "32be", - .spec_ref = "7.4.2", -}; - -static const struct osmo_gtlv_gen_ie cause = { - "enum osmo_pfcp_cause", - .spec_ref = "8.2.1", -}; - -static const struct osmo_gtlv_gen_ie offending_ie = { - .decoded_type = "enum osmo_pfcp_iei", - .spec_ref = "8.2.22", -}; - -static const struct osmo_gtlv_gen_ie f_seid = { - .tag_name = "f_seid", - .spec_ref = "8.2.37", -}; - -static const struct osmo_gtlv_gen_ie pdr_id = { - .decoded_type = "uint16_t", - .dec_enc = "16be", - .spec_ref = "8.2.36", -}; - -static const struct osmo_gtlv_gen_ie precedence = { - .decoded_type = "uint32_t", - .dec_enc = "32be", - .spec_ref = "8.2.11", -}; - -static const struct osmo_gtlv_gen_ie source_iface = { - .decoded_type = "enum osmo_pfcp_source_iface", - .spec_ref = "8.2.2", -}; - -static const struct osmo_gtlv_gen_ie f_teid = { - .tag_name = "f_teid", - .spec_ref = "8.2.3", -}; - -static const struct osmo_gtlv_gen_ie traffic_endpoint_id = { - .tag_name = "traffic_endpoint_id", - .decoded_type = "uint8_t", - .dec_enc = "8", - .spec_ref = "8.2.92", -}; - -static const struct osmo_gtlv_gen_ie iface_type = { - .decoded_type = "enum osmo_pfcp_3gpp_iface_type", - .tag_name = "3gpp_iface_type", - .spec_ref = "8.2.118", -}; - -static const struct osmo_gtlv_gen_ie_o ies_in_pdi[] = { - Ms(source_iface), - O(f_teid, "local_f_teid"), - O(ALL_FROM_NAME, "ue_ip_address"), - Os(traffic_endpoint_id), - O(iface_type, "source_iface_type"), - {} -}; - -static const struct osmo_gtlv_gen_ie pdi = { - .nested_ies = ies_in_pdi, - .spec_ref = "7.5.2.2-2", -}; - -static const struct osmo_gtlv_gen_ie far_id = { - .decoded_type = "uint32_t", - .dec_enc = "32be", - .spec_ref = "8.2.74", -}; - -static const struct osmo_gtlv_gen_ie_o ies_in_create_pdr[] = { - Ms(pdr_id), - Ms(precedence), - Ms(pdi), - O(ALL_FROM_NAME, "outer_header_removal"), - Os(far_id), - O(ALL_FROM_NAME, "activate_predefined_rules"), - {} -}; - -static const struct osmo_gtlv_gen_ie create_pdr = { - .nested_ies = ies_in_create_pdr, - .spec_ref = "7.5.2.2", -}; - -static const struct osmo_gtlv_gen_ie_o ies_in_created_pdr[] = { - Ms(pdr_id), - O(f_teid, "local_f_teid"), - {} -}; - -static const struct osmo_gtlv_gen_ie created_pdr = { - .nested_ies = ies_in_created_pdr, - .spec_ref = "7.5.3.2", -}; - -static const struct osmo_gtlv_gen_ie_o ies_in_upd_pdr[] = { - Ms(pdr_id), - O(ALL_FROM_NAME, "outer_header_removal"), - Os(pdi), - Os(far_id), - O(ALL_FROM_NAME, "activate_predefined_rules"), - {} -}; - -static const struct osmo_gtlv_gen_ie upd_pdr = { - .nested_ies = ies_in_upd_pdr, - .spec_ref = "7.5.4.2", -}; - -static const struct osmo_gtlv_gen_ie_o ies_in_updated_pdr[] = { - Ms(pdr_id), - O(f_teid, "local_f_teid"), - {} -}; - -static const struct osmo_gtlv_gen_ie updated_pdr = { - .nested_ies = ies_in_updated_pdr, - .spec_ref = "7.5.9.3", -}; - -static const struct osmo_gtlv_gen_ie_o ies_in_remove_pdr[] = { - Ms(pdr_id), - {} -}; - -static const struct osmo_gtlv_gen_ie remove_pdr = { - .nested_ies = ies_in_remove_pdr, - .spec_ref = "7.5.4.6", -}; - -static const struct osmo_gtlv_gen_ie destination_iface = { - .decoded_type = "enum osmo_pfcp_dest_iface", - .dec_enc = "dest_iface", - .spec_ref = "8.2.24", -}; - -static const struct osmo_gtlv_gen_ie_o ies_in_forw_params[] = { - Ms(destination_iface), - O(ALL_FROM_NAME, "network_inst"), - O(ALL_FROM_NAME, "outer_header_creation"), - O(traffic_endpoint_id, "linked_te_id"), - O(iface_type, "destination_iface_type"), - {} -}; - -static const struct osmo_gtlv_gen_ie forw_params = { - .nested_ies = ies_in_forw_params, - .spec_ref = "7.5.2.3-2", -}; - -static const struct osmo_gtlv_gen_ie_o ies_in_upd_forw_params[] = { - Os(destination_iface), - O(ALL_FROM_NAME, "network_inst"), - O(ALL_FROM_NAME, "outer_header_creation"), - O(traffic_endpoint_id, "linked_te_id"), - O(iface_type, "destination_iface_type"), - {} -}; - -static const struct osmo_gtlv_gen_ie upd_forw_params = { - .nested_ies = ies_in_upd_forw_params, - .spec_ref = "7.5.4.3-2", -}; - -static const struct osmo_gtlv_gen_ie_o ies_in_create_far[] = { - Ms(far_id), - M(ALL_FROM_NAME, "apply_action"), - Os(forw_params), - {} -}; - -static const struct osmo_gtlv_gen_ie create_far = { - .nested_ies = ies_in_create_far, - .spec_ref = "7.5.2.3", -}; - -static const struct osmo_gtlv_gen_ie_o ies_in_remove_far[] = { - Ms(far_id), - {} -}; - -static const struct osmo_gtlv_gen_ie remove_far = { - .nested_ies = ies_in_remove_far, - .spec_ref = "7.5.4.6", -}; - -static const struct osmo_gtlv_gen_ie_o ies_in_upd_far[] = { - Ms(far_id), - O(ALL_FROM_NAME, "apply_action"), - Os(upd_forw_params), - {} -}; - -static const struct osmo_gtlv_gen_ie upd_far = { - .nested_ies = ies_in_upd_far, - .spec_ref = "7.5.4.3", -}; - -static const struct osmo_gtlv_gen_ie_o ies_in_msg_heartbeat_req[] = { - Ms(recovery_time_stamp), - {} -}; - -static const struct osmo_gtlv_gen_ie_o ies_in_msg_heartbeat_resp[] = { - Ms(recovery_time_stamp), - {} -}; - -static const struct osmo_gtlv_gen_ie_o ies_in_msg_assoc_setup_req[] = { - M(ALL_FROM_NAME, "node_id"), - Ms(recovery_time_stamp), - O(ALL_FROM_NAME, "up_function_features"), - O(ALL_FROM_NAME, "cp_function_features"), - {} -}; - -static const struct osmo_gtlv_gen_ie_o ies_in_msg_assoc_setup_resp[] = { - M(ALL_FROM_NAME, "node_id"), - Ms(cause), - Ms(recovery_time_stamp), - O(ALL_FROM_NAME, "up_function_features"), - O(ALL_FROM_NAME, "cp_function_features"), - {} -}; - -static const struct osmo_gtlv_gen_ie_o ies_in_msg_assoc_release_req[] = { - M(ALL_FROM_NAME, "node_id"), - {} -}; - -static const struct osmo_gtlv_gen_ie_o ies_in_msg_assoc_release_resp[] = { - M(ALL_FROM_NAME, "node_id"), - Ms(cause), - {} -}; - -static const struct osmo_gtlv_gen_ie_o ies_in_msg_session_est_req[] = { - M(ALL_FROM_NAME, "node_id"), - O(f_seid, "cp_f_seid"), - M_MULTIs(32, 1, create_pdr), - M_MULTI(32, 1, create_far, "create_far"), - {} -}; - -static const struct osmo_gtlv_gen_ie_o ies_in_msg_session_est_resp[] = { - M(ALL_FROM_NAME, "node_id"), - Ms(cause), - Os(offending_ie), - O(f_seid, "up_f_seid"), - O_MULTIs(32, created_pdr), - {} -}; - -static const struct osmo_gtlv_gen_ie_o ies_in_msg_session_mod_req[] = { - O(f_seid, "cp_f_seid"), - O_MULTIs(32, remove_pdr), - O_MULTIs(32, remove_far), - O_MULTIs(32, create_pdr), - O_MULTIs(32, create_far), - O_MULTIs(32, upd_pdr), - O_MULTIs(32, upd_far), - {} -}; - -static const struct osmo_gtlv_gen_ie_o ies_in_msg_session_mod_resp[] = { - Ms(cause), - Os(offending_ie), - O_MULTIs(32, created_pdr), - O_MULTIs(32, updated_pdr), - {} -}; - -static const struct osmo_gtlv_gen_ie_o ies_in_msg_session_del_req[] = { - /* no IEs */ - {} -}; - -static const struct osmo_gtlv_gen_ie_o ies_in_msg_session_del_resp[] = { - Ms(cause), - {} -}; - -#define MSG(NAME) { #NAME, ies_in_msg_##NAME } -static const struct osmo_gtlv_gen_msg pfcp_msg_defs[] = { - MSG(heartbeat_req), - MSG(heartbeat_resp), - MSG(assoc_setup_req), - MSG(assoc_setup_resp), - MSG(assoc_release_req), - MSG(assoc_release_resp), - MSG(session_est_req), - MSG(session_est_resp), - MSG(session_mod_req), - MSG(session_mod_resp), - MSG(session_del_req), - MSG(session_del_resp), - {} -}; - -int main(int argc, const char **argv) -{ - struct osmo_gtlv_gen_cfg cfg = { - .proto_name = "osmo_pfcp", - .spec_ref_prefix = "3GPP TS 29.244 ", - .message_type_enum = "enum osmo_pfcp_message_type", - .message_type_prefix = "OSMO_PFCP_MSGT_", - .tag_enum = "enum osmo_pfcp_iei", - .tag_prefix = "OSMO_PFCP_IEI_", - .decoded_type_prefix = "struct osmo_pfcp_ie_", - .h_header = "#include <osmocom/pfcp/pfcp_ies_custom.h>", - .c_header = "#include <osmocom/pfcp/pfcp_ies_auto.h>", - .msg_defs = pfcp_msg_defs, - .add_enc_to_str = true, - }; - return osmo_gtlv_gen_main(&cfg, argc, argv); -} diff --git a/src/libosmo-pfcp/pfcp_endpoint.c b/src/libosmo-pfcp/pfcp_endpoint.c deleted file mode 100644 index 83b7c1a..0000000 --- a/src/libosmo-pfcp/pfcp_endpoint.c +++ /dev/null @@ -1,473 +0,0 @@ -/* - * (C) 2021-2022 by sysmocom - s.f.m.c. GmbH info@sysmocom.de - * All Rights Reserved. - * - * Author: Neels Janosch Hofmeyr nhofmeyr@sysmocom.de - * - * SPDX-License-Identifier: GPL-2.0+ - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. - * - */ - -#include <errno.h> -#include <unistd.h> -#include <time.h> - -#include <osmocom/core/talloc.h> -#include <osmocom/core/timer.h> -#include <osmocom/core/tdef.h> - -#include <osmocom/pfcp/pfcp_endpoint.h> -#include <osmocom/pfcp/pfcp_msg.h> - -/*! Entry of pfcp_endpoint message queue of PFCP messages, for re-transsions. */ -struct osmo_pfcp_queue_entry { - /* entry in per-peer list of messages waiting for a response */ - struct llist_head entry; - /* back-pointer */ - struct osmo_pfcp_endpoint *ep; - /* message we have transmitted */ - struct osmo_pfcp_msg *m; - /* T1 timer: How long to wait for response before retransmitting */ - struct osmo_timer_list t1; - /* N1: number of pending re-transmissions */ - unsigned int n1_remaining; -}; - -/* Find a matching osmo_pfcp_queue_entry for given rx_hdr. - * A returned osmo_pfcp_queue_entry is guaranteed to be a Response if rx is a Request, and vice versa. */ -static struct osmo_pfcp_queue_entry * -osmo_pfcp_queue_find(struct llist_head *queue, const struct osmo_pfcp_msg *rx) -{ - struct osmo_pfcp_queue_entry *qe; - /* It's important to match only a Request to a Response and vice versa, because the remote peer makes its own - * sequence_nr. There could be a collision of sequence_nr. But as long as all Requests look for a Response and - * vice versa, the sequence_nr scopes don't overlap. */ - llist_for_each_entry(qe, queue, entry) { - if (qe->m->is_response != rx->is_response - && qe->m->h.sequence_nr == rx->h.sequence_nr) - return qe; - } - return NULL; -} - -/* clean up and deallocate the given osmo_pfcp_queue_entry */ -static void osmo_pfcp_queue_del(struct osmo_pfcp_queue_entry *qe) -{ - /* see also the talloc destructor: osmo_pfcp_queue_destructor() */ - talloc_free(qe); -} - -static int osmo_pfcp_queue_destructor(struct osmo_pfcp_queue_entry *qe) -{ - osmo_timer_del(&qe->t1); - llist_del(&qe->entry); - return 0; -} - -struct osmo_tdef osmo_pfcp_tdefs[] = { - { .T = OSMO_PFCP_MSGT_HEARTBEAT_REQ, .default_val = 15, .unit = OSMO_TDEF_S, - .desc = "PFCP Heartbeat Request period, how long to wait between issuing requests" - }, - { .T = OSMO_PFCP_MSGT_HEARTBEAT_RESP, .default_val = 15, .unit = OSMO_TDEF_S, - .desc = "PFCP Heartbeat Response timeout, the time after which to regard a non-responding peer as disconnected" - }, - { .T = OSMO_PFCP_TIMER_GRACEFUL_REL, .default_val = 15, .unit = OSMO_TDEF_S, - .desc = "PFCP peer graceful shutdown timeout, how long to keep the peer's state after a peer requested" - " graceful shutdown" - }, - { .T = OSMO_PFCP_TIMER_T1, .default_val = 3000, .unit = OSMO_TDEF_MS, - .desc = "PFCP request timeout, how long after a missing response to retransmit a PFCP request" - }, - { .T = OSMO_PFCP_TIMER_N1, .default_val = 3, .unit = OSMO_TDEF_CUSTOM, - .desc = "Number of PFCP request retransmission attempts" - }, - { .T = OSMO_PFCP_TIMER_KEEP_RESP, .default_val = 10000, .unit = OSMO_TDEF_MS, - .desc = "PFCP response timeout, how long to keep a response, in case its same request is retransmitted by the peer" - }, - { .T = OSMO_PFCP_TIMER_ASSOC_RETRY, .default_val = 15, .unit = OSMO_TDEF_S, - .desc = "Idle time between attempts of PFCP Association Setup (CPF)" - }, - {} -}; - -struct osmo_pfcp_endpoint *osmo_pfcp_endpoint_create(void *ctx, void *priv) -{ - struct osmo_pfcp_endpoint *ep = talloc_zero(ctx, struct osmo_pfcp_endpoint); - uint32_t unix_time; - if (!ep) - return NULL; - - INIT_LLIST_HEAD(&ep->sent_requests); - INIT_LLIST_HEAD(&ep->sent_responses); - - ep->cfg.tdefs = osmo_pfcp_tdefs; - ep->priv = priv; - ep->pfcp_fd.fd = -1; - - /* time() returns seconds since 1970 (UNIX epoch), but the recovery_time_stamp is coded in the NTP format, which is - * seconds since 1900, the NTP era 0. 2208988800L is the offset between UNIX epoch and NTP era 0. - * TODO: what happens when we enter NTP era 1? Is it sufficient to integer-wrap? */ - unix_time = time(NULL); - ep->recovery_time_stamp = unix_time + 2208988800L; - LOGP(DLPFCP, LOGL_NOTICE, "PFCP endpoint: recovery timestamp = 0x%08x (%u seconds since UNIX epoch," - " which is %u seconds since NTP era 0; IETF RFC 5905)\n", - ep->recovery_time_stamp, unix_time, ep->recovery_time_stamp); - - return ep; -} - -static unsigned int ep_n1(struct osmo_pfcp_endpoint *ep) -{ - return osmo_tdef_get(ep->cfg.tdefs, OSMO_PFCP_TIMER_N1, OSMO_TDEF_CUSTOM, -1); -} - -static unsigned int ep_t1(struct osmo_pfcp_endpoint *ep) -{ - return osmo_tdef_get(ep->cfg.tdefs, OSMO_PFCP_TIMER_T1, OSMO_TDEF_MS, -1); -} - -static unsigned int ep_keep_resp(struct osmo_pfcp_endpoint *ep) -{ - return osmo_tdef_get(ep->cfg.tdefs, OSMO_PFCP_TIMER_KEEP_RESP, OSMO_TDEF_MS, -1); -} - -static int osmo_pfcp_endpoint_tx_data_no_logging(struct osmo_pfcp_endpoint *ep, struct osmo_pfcp_msg *m); - -/* Return true to keep the message in the queue, false for dropping from the queue. */ -static bool pfcp_queue_retrans(struct osmo_pfcp_queue_entry *qe) -{ - struct osmo_pfcp_endpoint *endpoint = qe->ep; - unsigned int t1_ms = ep_t1(endpoint); - struct osmo_pfcp_msg *m = qe->m; - int rc; - - /* re-transmit */ - if (qe->n1_remaining) - qe->n1_remaining--; - OSMO_LOG_PFCP_MSG(m, LOGL_INFO, "re-sending (%u attempts remaining)\n", qe->n1_remaining); - - rc = osmo_pfcp_endpoint_tx_data_no_logging(endpoint, m); - /* If encoding failed, it cannot ever succeed. Drop the queue entry. */ - if (rc) - return false; - /* if no more attempts remaining, drop from queue */ - if (!qe->n1_remaining) - return false; - /* re-schedule timer, keep in queue */ - osmo_timer_schedule(&qe->t1, t1_ms/1000, t1_ms%1000); - return true; -} - -/* T1 for a given queue entry has expired */ -static void pfcp_queue_timer_cb(void *data) -{ - struct osmo_pfcp_queue_entry *qe = data; - bool keep; - - if (qe->m->is_response) { - /* The response has waited in the queue for any retransmissions of its initiating request. Now that time - * has passed and the response can be dropped from the queue. */ - keep = false; - } else { - /* The request is still here, which means it has not received a response from the remote side. - * Retransmit the request. */ - keep = pfcp_queue_retrans(qe); - } - - if (keep) - return; - /* Drop the queue entry. No more retransmissions. */ - if (!qe->m->is_response && qe->m->ctx.resp_cb) - qe->m->ctx.resp_cb(qe->m, NULL, "PFCP retransmissions elapsed, no response received"); - osmo_pfcp_queue_del(qe); -} - -/* Directly encode and transmit the message, without storing in the retrans_queue. */ -static int osmo_pfcp_endpoint_tx_data_no_logging(struct osmo_pfcp_endpoint *ep, struct osmo_pfcp_msg *m) -{ - int rc; - - if (!m->encoded) { - /* Allocate msgb as child of the message m, so that when m gets deallocated at the end of - * retransmission queueing, the msgb gets deallocated with it. */ - m->encoded = msgb_alloc_c(m, OSMO_PFCP_MSGB_ALLOC_SIZE, "PFCP-tx"); - OSMO_ASSERT(m->encoded); - rc = osmo_pfcp_msg_encode(m->encoded, m); - if (rc) { - msgb_free(m->encoded); - m->encoded = NULL; - return rc; - } - } - - rc = sendto(ep->pfcp_fd.fd, msgb_data(m->encoded), msgb_length(m->encoded), 0, - (struct sockaddr *)&m->remote_addr, sizeof(m->remote_addr)); - if (rc != msgb_length(m->encoded)) { - OSMO_LOG_PFCP_MSG(m, LOGL_ERROR, "sendto() failed: rc = %d != length %u\n", - rc, msgb_length(m->encoded)); - return -EIO; - } - return 0; -} - -int osmo_pfcp_endpoint_tx_data(struct osmo_pfcp_endpoint *ep, struct osmo_pfcp_msg *m) -{ - OSMO_LOG_PFCP_MSG(m, LOGL_INFO, "sending\n"); - return osmo_pfcp_endpoint_tx_data_no_logging(ep, m); -} - -int osmo_pfcp_endpoint_tx_heartbeat_req(struct osmo_pfcp_endpoint *ep, const struct osmo_sockaddr *remote_addr) -{ - struct osmo_pfcp_msg *tx = osmo_pfcp_msg_alloc_tx(OTC_SELECT, remote_addr, NULL, NULL, - OSMO_PFCP_MSGT_HEARTBEAT_REQ); - tx->ies.heartbeat_req.recovery_time_stamp = ep->recovery_time_stamp; - tx->h.sequence_nr = osmo_pfcp_next_seq_nr(&ep->seq_nr_state); - return osmo_pfcp_endpoint_tx_data(ep, tx); -} - -/* add a given msgb to the queue of per-peer messages waiting for a response */ -static int osmo_pfcp_endpoint_retrans_queue_add(struct osmo_pfcp_endpoint *endpoint, struct osmo_pfcp_msg *m) -{ - struct osmo_pfcp_queue_entry *qe; - unsigned int n1 = ep_n1(endpoint); - unsigned int t1_ms = ep_t1(endpoint); - unsigned int keep_resp_ms = ep_keep_resp(endpoint); - unsigned int timeout = m->is_response ? keep_resp_ms : t1_ms; - - LOGP(DLPFCP, LOGL_DEBUG, "retransmit unanswered Requests %u x %ums; keep sent Responses for %ums\n", - n1, t1_ms, keep_resp_ms); - /* If there are no retransmissions or no timeout, it makes no sense to add to the queue. */ - if (!n1 || !t1_ms) { - if (!m->is_response && m->ctx.resp_cb) - m->ctx.resp_cb(m, NULL, "PFCP timeout is zero, cannot wait for a response"); - return 0; - } - - qe = talloc(endpoint, struct osmo_pfcp_queue_entry); - OSMO_ASSERT(qe); - *qe = (struct osmo_pfcp_queue_entry){ - .ep = endpoint, - .m = m, - .n1_remaining = m->is_response ? 0 : n1, - }; - talloc_steal(qe, m); - - /* Slight optimization: Add sent requests to the start of the list: we will usually receive a response shortly - * after sending a request, removing that entry from the queue quickly. - * Add sent responses to the end of the list: they will rarely be retransmitted at all. */ - if (m->is_response) - llist_add_tail(&qe->entry, &endpoint->sent_responses); - else - llist_add_tail(&qe->entry, &endpoint->sent_requests); - talloc_set_destructor(qe, osmo_pfcp_queue_destructor); - - osmo_timer_setup(&qe->t1, pfcp_queue_timer_cb, qe); - osmo_timer_schedule(&qe->t1, timeout/1000, timeout%1000); - return 0; -} - -/* Transmit a PFCP message. - * Store the message in the local message queue for possible retransmissions. - * On success, return zero, and pass ownership of m to ep. ep deallocates m when all retransmissions are done / a reply - * has been received. - * On error, return nonzero, and immediately deallocate m. */ -int osmo_pfcp_endpoint_tx(struct osmo_pfcp_endpoint *ep, struct osmo_pfcp_msg *m) -{ - struct osmo_pfcp_ie_node_id *node_id; - int rc; - if (!m->is_response) - m->h.sequence_nr = osmo_pfcp_next_seq_nr(&ep->seq_nr_state); - node_id = osmo_pfcp_msg_node_id(m); - if (node_id) - *node_id = ep->cfg.local_node_id; - - rc = osmo_pfcp_endpoint_tx_data(ep, m); - if (rc) { - if (!m->is_response && m->ctx.resp_cb) - m->ctx.resp_cb(m, NULL, "Failed to transmit request"); - osmo_pfcp_msg_free(m); - return rc; - } - osmo_pfcp_endpoint_retrans_queue_add(ep, m); - return 0; -} - -static void osmo_pfcp_endpoint_handle_rx(struct osmo_pfcp_endpoint *ep, struct osmo_pfcp_msg *m) -{ - bool dispatch_rx = true; - struct osmo_pfcp_queue_entry *prev_msg; - struct osmo_pfcp_msg *req; - - if (m->h.message_type == OSMO_PFCP_MSGT_HEARTBEAT_REQ) { - /* Directly answer with a Heartbeat Response. */ - struct osmo_pfcp_msg *resp = osmo_pfcp_msg_alloc_tx(OTC_SELECT, NULL, NULL, m, OSMO_PFCP_MSGT_HEARTBEAT_RESP); - resp->ies.heartbeat_resp.recovery_time_stamp = ep->recovery_time_stamp; - osmo_pfcp_endpoint_tx_data(ep, resp); - /* Still also dispatch the Rx event to the peer. */ - } - - /* If this is receiving a response, search for matching sent request that is now completed. - * If this is receiving a request, search for a matching sent response that can be retransmitted. - * A match is found by sequence_nr. */ - prev_msg = osmo_pfcp_queue_find(m->is_response ? &ep->sent_requests : &ep->sent_responses, m); - - if (prev_msg && !m->is_response) { - /* m is a request, and we have already sent a response to this same request earlier. Retransmit the same - * response, and don't dispatch the msg rx. Keep our response queued in case the request is - * retransmitted yet another time. */ - - /* Populate message context to point at peer and session, if applicable. - * With that context applied, log message rx. */ - if (ep->set_msg_ctx) - ep->set_msg_ctx(ep, m, NULL); - OSMO_LOG_PFCP_MSG(m, LOGL_INFO, "received retransmission of earlier request\n"); - - /* Also log on the earlier PFCP msg that it is resent */ - OSMO_LOG_PFCP_MSG(prev_msg->m, LOGL_INFO, "re-sending cached response\n"); - osmo_pfcp_endpoint_tx_data_no_logging(ep, prev_msg->m); - return; - } - - req = NULL; - if (prev_msg && m->is_response) { - /* m is a response to the earlier request prev_msg->m. The request is now ACKed and can be dropped from - * the retransmission queue: see 'if (req)' below. */ - req = prev_msg->m; - } - - /* Populate message context to point at peer and session, if applicable. - * With that context applied, log message rx. */ - if (ep->set_msg_ctx) - ep->set_msg_ctx(ep, m, req); - OSMO_LOG_PFCP_MSG(m, LOGL_INFO, "received\n"); - - if (req && req->ctx.resp_cb) { - int rc = req->ctx.resp_cb(req, m, NULL); - /* Only dispatch the response to rx_msg() when resp_cb() asks for it with rc == 1 (or when there is no - * resp_cb()). */ - if (rc != 1) { - dispatch_rx = false; - OSMO_LOG_PFCP_MSG(m, LOGL_DEBUG, - "response handled by m->resp_cb(), not dispatching to rx_msg()\n"); - } - } - - if (dispatch_rx) - ep->rx_msg(ep, m, req); - if (req) - osmo_pfcp_queue_del(prev_msg); -} - -/* call-back for PFCP socket file descriptor */ -static int osmo_pfcp_fd_cb(struct osmo_fd *ofd, unsigned int what) -{ - int rc; - struct osmo_pfcp_endpoint *ep = ofd->data; - - if (what & OSMO_FD_READ) { - struct osmo_sockaddr remote; - socklen_t remote_len = sizeof(remote); - struct msgb *msg = msgb_alloc_c(OTC_SELECT, OSMO_PFCP_MSGB_ALLOC_SIZE, "PFCP-rx"); - if (!msg) - return -ENOMEM; - - msg->l3h = msg->tail; - rc = recvfrom(ofd->fd, msg->tail, msgb_tailroom(msg), 0, (struct sockaddr *)&remote, &remote_len); - if (rc <= 0) - return -EIO; - msgb_put(msg, rc); - - OSMO_ASSERT(ep->rx_msg); - - /* This may be a bundle of PFCP messages. Parse and receive each message received, by shifting l4h - * through the message bundle. */ - msg->l4h = msg->l3h; - while (msgb_l4len(msg)) { - struct osmo_gtlv_load tlv; - struct osmo_pfcp_msg *m = osmo_pfcp_msg_alloc_rx(OTC_SELECT, &remote); - m->encoded = msg; - - rc = osmo_pfcp_msg_decode_header(&tlv, m, msg); - if (rc < 0) - break; - msg->l4h += rc; - - rc = osmo_pfcp_msg_decode_tlv(m, &tlv); - /* If errors occurred, they have already been logged on DLPFCP. */ - if (rc == 0) - osmo_pfcp_endpoint_handle_rx(ep, m); - osmo_pfcp_msg_free(m); - } - msgb_free(msg); - } - return 0; -} - -/*! bind a PFCP endpoint to its configured address (ep->cfg.local_addr). - * \return 0 on success, negative on error. */ -int osmo_pfcp_endpoint_bind(struct osmo_pfcp_endpoint *ep) -{ - int rc; - /* close the existing socket, if any */ - osmo_pfcp_endpoint_close(ep); - - if (!ep->rx_msg) { - LOGP(DLPFCP, LOGL_ERROR, "missing rx_msg cb at osmo_pfcp_endpoint\n"); - return -EINVAL; - } - - /* create the new socket, binding to configured local address */ - ep->pfcp_fd.cb = osmo_pfcp_fd_cb; - ep->pfcp_fd.data = ep; - rc = osmo_sock_init_osa_ofd(&ep->pfcp_fd, SOCK_DGRAM, IPPROTO_UDP, &ep->cfg.local_addr, NULL, OSMO_SOCK_F_BIND); - if (rc < 0) - return rc; - return 0; -} - -void osmo_pfcp_endpoint_close(struct osmo_pfcp_endpoint *ep) -{ - struct osmo_pfcp_queue_entry *qe; - while ((qe = llist_first_entry_or_null(&ep->sent_requests, struct osmo_pfcp_queue_entry, entry))) - osmo_pfcp_queue_del(qe); - while ((qe = llist_first_entry_or_null(&ep->sent_responses, struct osmo_pfcp_queue_entry, entry))) - osmo_pfcp_queue_del(qe); - - if (ep->pfcp_fd.fd != -1) { - osmo_fd_unregister(&ep->pfcp_fd); - close(ep->pfcp_fd.fd); - ep->pfcp_fd.fd = -1; - } -} - -void osmo_pfcp_endpoint_free(struct osmo_pfcp_endpoint **ep) -{ - if (!*ep) - return; - osmo_pfcp_endpoint_close(*ep); - talloc_free(*ep); - *ep = NULL; -} - -/* Call osmo_pfcp_msg_invalidate_ctx(deleted_fi) on all queued osmo_pfcp_msg instances in the retrans_queue. */ -void osmo_pfcp_endpoint_invalidate_ctx(struct osmo_pfcp_endpoint *ep, struct osmo_fsm_inst *deleted_fi) -{ - struct osmo_pfcp_queue_entry *qe; - llist_for_each_entry(qe, &ep->sent_requests, entry) - osmo_pfcp_msg_invalidate_ctx(qe->m, deleted_fi); - llist_for_each_entry(qe, &ep->sent_responses, entry) - osmo_pfcp_msg_invalidate_ctx(qe->m, deleted_fi); -} diff --git a/src/libosmo-pfcp/pfcp_ies_custom.c b/src/libosmo-pfcp/pfcp_ies_custom.c deleted file mode 100644 index 3b3769a..0000000 --- a/src/libosmo-pfcp/pfcp_ies_custom.c +++ /dev/null @@ -1,999 +0,0 @@ -/* Decoded PFCP IEs, to be used by the auto-generated pfcp_ies_auto.c. */ -/* - * (C) 2021-2022 by sysmocom - s.f.m.c. GmbH info@sysmocom.de - * All Rights Reserved. - * - * Author: Neels Janosch Hofmeyr nhofmeyr@sysmocom.de - * - * SPDX-License-Identifier: GPL-2.0+ - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. - * - */ - -#include <errno.h> -#include <inttypes.h> - -#include <osmocom/core/socket.h> -#include <osmocom/core/logging.h> -#include <osmocom/core/utils.h> -#include <osmocom/core/msgb.h> - -#include <osmocom/gtlv/gtlv.h> - -#include <osmocom/pfcp/pfcp_ies_custom.h> -#include <osmocom/pfcp/pfcp_strs.h> -#include <osmocom/pfcp/pfcp_msg.h> - -/* Assumes presence of local variable osmo_pfcp_msg *m. m->log_ctx may be NULL. */ -#define RETURN_ERROR(RC, FMT, ARGS...) \ - do {\ - OSMO_ASSERT(decoded_struct); \ - OSMO_LOG_PFCP_MSG(OSMO_PFCP_MSG_FOR_IES(decoded_struct), LOGL_ERROR, FMT " (%d: %s)\n", ##ARGS, RC, \ - strerror((RC) > 0 ? (RC) : -(RC))); \ - return RC; \ - } while (0) - -/* Assumes presence of local variable osmo_gtlv_load *tlv. Usage: - * ENSURE_LENGTH_IS_EXACTLY(2); - */ -#define ENSURE_LENGTH_IS_EXACTLY(VAL) \ - do { \ - if (!(tlv->len == VAL)) \ - RETURN_ERROR(-EINVAL, "IE has length = %zu, expected length == " #VAL, tlv->len); \ - } while (0) - -/* Assumes presence of local variable osmo_gtlv_load *tlv. Usage: - * ENSURE_LENGTH_IS_AT_LEAST(1); - */ -#define ENSURE_LENGTH_IS_AT_LEAST(VAL) \ - do { \ - if (!(tlv->len >= VAL)) \ - RETURN_ERROR(-EINVAL, "IE has length = %zu, expected length >= " #VAL, tlv->len); \ - } while (0) - -/* Assumes presence of local variable osmo_gtlv_load *tlv. Usage: - * const uint8_t *pos = tlv->val; - * ENSURE_REMAINING_LENGTH_IS_AT_LEAST("first part", pos, 23); - * <parse first part> - * pos += 23; - * ENSURE_REMAINING_LENGTH_IS_AT_LEAST("very long part", pos, 235); - * <parse very long part> - * pos += 235; - */ -#define ENSURE_REMAINING_LENGTH_IS_AT_LEAST(NAME, POS, MIN_VAL) \ - do { \ - if (!((tlv->len - ((POS) - tlv->val)) >= MIN_VAL)) \ - RETURN_ERROR(-EINVAL, \ - "at value octet %d: %zu octets remaining, but " #NAME " requires length >= " #MIN_VAL, \ - (int)((POS) - tlv->val), \ - tlv->len - ((POS) - tlv->val)); \ - } while (0) - -void osmo_pfcp_ie_f_seid_set(struct osmo_pfcp_ie_f_seid *f_seid, uint64_t seid, const struct osmo_sockaddr *remote_addr) -{ - *f_seid = (struct osmo_pfcp_ie_f_seid) { - .seid = seid, - }; - osmo_pfcp_ip_addrs_set(&f_seid->ip_addr, remote_addr); -} - -int osmo_pfcp_dec_cause(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *tlv) -{ - enum osmo_pfcp_cause *cause = decode_to; - ENSURE_LENGTH_IS_EXACTLY(1); - *cause = *tlv->val; - return 0; -} - -int osmo_pfcp_enc_cause(struct osmo_gtlv_put *tlv, const void *decoded_struct, const void *encode_from) -{ - const enum osmo_pfcp_cause *cause = encode_from; - msgb_put_u8(tlv->dst, *cause); - return 0; -} - -int osmo_pfcp_enc_to_str_cause(char *buf, size_t buflen, const void *encode_from) -{ - const enum osmo_pfcp_cause *cause = encode_from; - return snprintf(buf, buflen, "%s", osmo_pfcp_cause_str(*cause)); -} - -int osmo_pfcp_dec_offending_ie(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *tlv) -{ - enum osmo_pfcp_iei *offending_ie = decode_to; - ENSURE_LENGTH_IS_EXACTLY(2); - *offending_ie = osmo_load16be(tlv->val); - return 0; -} - -int osmo_pfcp_enc_offending_ie(struct osmo_gtlv_put *tlv, const void *decoded_struct, const void *encode_from) -{ - const enum osmo_pfcp_iei *offending_ie = encode_from; - msgb_put_u16(tlv->dst, *offending_ie); - return 0; -} - -int osmo_pfcp_enc_to_str_offending_ie(char *buf, size_t buflen, const void *encode_from) -{ - const enum osmo_pfcp_iei *offending_ie = encode_from; - return snprintf(buf, buflen, "%s", osmo_pfcp_iei_str(*offending_ie)); -} - -int osmo_pfcp_dec_8(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *tlv) -{ - uint8_t *u8 = decode_to; - ENSURE_LENGTH_IS_AT_LEAST(1); - *u8 = tlv->val[0]; - return 0; -} - -int osmo_pfcp_enc_8(struct osmo_gtlv_put *tlv, const void *decoded_struct, const void *encode_from) -{ - const uint8_t *u8 = encode_from; - msgb_put_u8(tlv->dst, *u8); - return 0; -} - -int osmo_pfcp_enc_to_str_8(char *buf, size_t buflen, const void *encode_from) -{ - const uint8_t *u8 = encode_from; - return snprintf(buf, buflen, "%u", *u8); -} - -int osmo_pfcp_dec_16be(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *tlv) -{ - uint16_t *u16 = decode_to; - ENSURE_LENGTH_IS_AT_LEAST(2); - *u16 = osmo_load16be(tlv->val); - return 0; -} - -int osmo_pfcp_enc_16be(struct osmo_gtlv_put *tlv, const void *decoded_struct, const void *encode_from) -{ - const uint16_t *u16 = encode_from; - msgb_put_u16(tlv->dst, *u16); - return 0; -} - -int osmo_pfcp_enc_to_str_16be(char *buf, size_t buflen, const void *encode_from) -{ - const uint16_t *u16 = encode_from; - return snprintf(buf, buflen, "%u", *u16); -} - -int osmo_pfcp_dec_32be(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *tlv) -{ - uint32_t *u32 = decode_to; - ENSURE_LENGTH_IS_AT_LEAST(4); - *u32 = osmo_load32be(tlv->val); - return 0; -} - -int osmo_pfcp_enc_32be(struct osmo_gtlv_put *tlv, const void *decoded_struct, const void *encode_from) -{ - const uint32_t *u32 = encode_from; - msgb_put_u32(tlv->dst, *u32); - return 0; -} - -int osmo_pfcp_enc_to_str_32be(char *buf, size_t buflen, const void *encode_from) -{ - const uint32_t *u32 = encode_from; - return snprintf(buf, buflen, "%u", *u32); -} - -int osmo_pfcp_dec_3gpp_iface_type(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *tlv) -{ - enum osmo_pfcp_3gpp_iface_type *_3gpp_iface_type = decode_to; - ENSURE_LENGTH_IS_AT_LEAST(1); - *_3gpp_iface_type = tlv->val[0] & 0x3f; - return 0; -} - -int osmo_pfcp_enc_3gpp_iface_type(struct osmo_gtlv_put *tlv, const void *decoded_struct, const void *encode_from) -{ - const enum osmo_pfcp_3gpp_iface_type *_3gpp_iface_type = encode_from; - msgb_put_u8(tlv->dst, (uint8_t)(*_3gpp_iface_type) & 0x3f); - return 0; -} - -int osmo_pfcp_enc_to_str_3gpp_iface_type(char *buf, size_t buflen, const void *encode_from) -{ - const enum osmo_pfcp_3gpp_iface_type *_3gpp_iface_type = encode_from; - return snprintf(buf, buflen, "%s", osmo_pfcp_3gpp_iface_type_str(*_3gpp_iface_type)); -} - -int osmo_pfcp_dec_source_iface(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *tlv) -{ - enum osmo_pfcp_source_iface *source_iface = decode_to; - ENSURE_LENGTH_IS_AT_LEAST(1); - *source_iface = tlv->val[0] & 0xf; - return 0; -} - -int osmo_pfcp_enc_source_iface(struct osmo_gtlv_put *tlv, const void *decoded_struct, const void *encode_from) -{ - const enum osmo_pfcp_source_iface *source_iface = encode_from; - msgb_put_u8(tlv->dst, (uint8_t)(*source_iface) & 0xf); - return 0; -} - -int osmo_pfcp_enc_to_str_source_iface(char *buf, size_t buflen, const void *encode_from) -{ - const enum osmo_pfcp_source_iface *source_iface = encode_from; - return snprintf(buf, buflen, "%s", osmo_pfcp_source_iface_str(*source_iface)); -} - -int osmo_pfcp_dec_dest_iface(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *tlv) -{ - enum osmo_pfcp_dest_iface *dest_interface = decode_to; - ENSURE_LENGTH_IS_AT_LEAST(1); - *dest_interface = tlv->val[0] & 0xf; - return 0; -} - -int osmo_pfcp_enc_dest_iface(struct osmo_gtlv_put *tlv, const void *decoded_struct, const void *encode_from) -{ - const enum osmo_pfcp_dest_iface *dest_interface = encode_from; - msgb_put_u8(tlv->dst, (uint8_t)(*dest_interface) & 0xf); - return 0; -} - -int osmo_pfcp_enc_to_str_dest_iface(char *buf, size_t buflen, const void *encode_from) -{ - const enum osmo_pfcp_dest_iface *dest_iface = encode_from; - return snprintf(buf, buflen, "%s", osmo_pfcp_dest_iface_str(*dest_iface)); -} - -int osmo_pfcp_dec_node_id(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *tlv) -{ - struct osmo_pfcp_ie_node_id *node_id = decode_to; - const void *ip; - unsigned int ip_len; - unsigned int want_len; - ENSURE_LENGTH_IS_AT_LEAST(1); - node_id->type = *(uint8_t *)tlv->val; - ip = &tlv->val[1]; - ip_len = tlv->len - 1; - - switch (node_id->type) { - case OSMO_PFCP_NODE_ID_T_IPV4: - want_len = sizeof(node_id->ip.u.sin.sin_addr); - if (ip_len != want_len) - RETURN_ERROR(-EINVAL, "Node ID: wrong IPv4 address value length %u, expected %u", - ip_len, want_len); - osmo_sockaddr_from_octets(&node_id->ip, ip, ip_len); - break; - case OSMO_PFCP_NODE_ID_T_IPV6: - want_len = sizeof(node_id->ip.u.sin6.sin6_addr); - if (ip_len != want_len) - RETURN_ERROR(-EINVAL, "Node ID: wrong IPv6 address value length %u, expected %u", - ip_len, want_len); - osmo_sockaddr_from_octets(&node_id->ip, ip, ip_len); - break; - case OSMO_PFCP_NODE_ID_T_FQDN: - /* Copy and add a trailing nul */ - OSMO_STRLCPY_ARRAY(node_id->fqdn, ip); - break; - default: - RETURN_ERROR(-EINVAL, "Invalid Node ID Type: %d", node_id->type); - } - return 0; -} - -int osmo_pfcp_enc_node_id(struct osmo_gtlv_put *tlv, const void *decoded_struct, const void *encode_from) -{ - unsigned int l; - const struct osmo_pfcp_ie_node_id *node_id = encode_from; - msgb_put_u8(tlv->dst, node_id->type); - switch (node_id->type) { - case OSMO_PFCP_NODE_ID_T_IPV4: - l = sizeof(node_id->ip.u.sin.sin_addr); - osmo_sockaddr_to_octets(msgb_put(tlv->dst, l), l, &node_id->ip); - break; - case OSMO_PFCP_NODE_ID_T_IPV6: - l = sizeof(node_id->ip.u.sin6.sin6_addr); - osmo_sockaddr_to_octets(msgb_put(tlv->dst, l), l, &node_id->ip); - break; - case OSMO_PFCP_NODE_ID_T_FQDN: - l = strnlen(node_id->fqdn, sizeof(node_id->fqdn)); - /* Copy without trailing nul */ - memcpy((char *)msgb_put(tlv->dst, l), node_id->fqdn, l); - break; - default: - RETURN_ERROR(-EINVAL, "Invalid Node ID Type: %d", node_id->type); - } - return 0; -} - -int osmo_pfcp_ie_node_id_to_str_buf(char *buf, size_t buflen, const struct osmo_pfcp_ie_node_id *node_id) -{ - struct osmo_strbuf sb = { .buf = buf, .len = buflen }; - - switch (node_id->type) { - case OSMO_PFCP_NODE_ID_T_IPV4: - OSMO_STRBUF_PRINTF(sb, "v4:"); - break; - case OSMO_PFCP_NODE_ID_T_IPV6: - OSMO_STRBUF_PRINTF(sb, "v6:"); - break; - case OSMO_PFCP_NODE_ID_T_FQDN: - OSMO_STRBUF_PRINTF(sb, "fqdn:"); - OSMO_STRBUF_APPEND(sb, osmo_quote_str_buf3, - node_id->fqdn, strnlen(node_id->fqdn, sizeof(node_id->fqdn))); - return sb.chars_needed; - default: - OSMO_STRBUF_PRINTF(sb, "unknown-node-id-type-%u", node_id->type); - return sb.chars_needed; - } - - OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, &node_id->ip); - return sb.chars_needed; -} - -char *osmo_pfcp_ie_node_id_to_str_c(void *ctx, const struct osmo_pfcp_ie_node_id *node_id) -{ - OSMO_NAME_C_IMPL(ctx, 64, "ERROR", osmo_pfcp_ie_node_id_to_str_buf, node_id) -} - -int osmo_pfcp_enc_to_str_node_id(char *buf, size_t buflen, const void *encode_from) -{ - return osmo_pfcp_ie_node_id_to_str_buf(buf, buflen, encode_from); -} - -bool osmo_pfcp_bits_get(const uint8_t *bits, unsigned int bitpos) -{ - unsigned int bytenum = bitpos / 8; - unsigned int bitmask = 1 << (bitpos % 8); - - return (bool)(bits[bytenum] & bitmask); -} - -void osmo_pfcp_bits_set(uint8_t *bits, unsigned int bitpos, bool val) -{ - unsigned int bytenum = bitpos / 8; - unsigned int bitmask = 1 << (bitpos % 8); - - if (val) - bits[bytenum] |= bitmask; - else - bits[bytenum] &= ~bitmask; -} - -int osmo_pfcp_bits_to_str_buf(char *buf, size_t buflen, const uint8_t *bits, const struct value_string *bit_strs) -{ - struct osmo_strbuf sb = { .buf = buf, .len = buflen }; - OSMO_STRBUF_PRINTF(sb, "("); - for (; bit_strs->str; bit_strs++) { - if (osmo_pfcp_bits_get(bits, bit_strs->value)) { - OSMO_STRBUF_PRINTF(sb, " %s", bit_strs->str); - } - } - OSMO_STRBUF_PRINTF(sb, " )"); - return sb.chars_needed; -} - -char *osmo_pfcp_bits_to_str_c(void *ctx, const uint8_t *bits, const struct value_string *bit_str) -{ - OSMO_NAME_C_IMPL(ctx, 64, "ERROR", osmo_pfcp_bits_to_str_buf, bits, bit_str) -} - -int osmo_pfcp_dec_up_function_features(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *tlv) -{ - struct osmo_pfcp_ie_up_function_features *up_function_features = decode_to; - ENSURE_LENGTH_IS_AT_LEAST(6); - memcpy(up_function_features->bits, tlv->val, 6); - return 0; -} - -int osmo_pfcp_enc_up_function_features(struct osmo_gtlv_put *tlv, const void *decoded_struct, const void *encode_from) -{ - const struct osmo_pfcp_ie_up_function_features *up_function_features = encode_from; - memcpy(msgb_put(tlv->dst, 6), up_function_features->bits, 6); - return 0; -} - -int osmo_pfcp_enc_to_str_up_function_features(char *buf, size_t buflen, const void *encode_from) -{ - const struct osmo_pfcp_ie_up_function_features *up_function_features = encode_from; - return osmo_pfcp_bits_to_str_buf(buf, buflen, up_function_features->bits, osmo_pfcp_up_feature_strs); -} - -int osmo_pfcp_dec_cp_function_features(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *tlv) -{ - struct osmo_pfcp_ie_cp_function_features *cp_function_features = decode_to; - ENSURE_LENGTH_IS_AT_LEAST(sizeof(cp_function_features->bits)); - memcpy(cp_function_features->bits, tlv->val, sizeof(cp_function_features->bits)); - return 0; -} - -int osmo_pfcp_enc_cp_function_features(struct osmo_gtlv_put *tlv, const void *decoded_struct, const void *encode_from) -{ - const struct osmo_pfcp_ie_cp_function_features *cp_function_features = encode_from; - memcpy(msgb_put(tlv->dst, sizeof(cp_function_features->bits)), - cp_function_features->bits, sizeof(cp_function_features->bits)); - return 0; -} - -int osmo_pfcp_enc_to_str_cp_function_features(char *buf, size_t buflen, const void *encode_from) -{ - const struct osmo_pfcp_ie_cp_function_features *cp_function_features = encode_from; - return osmo_pfcp_bits_to_str_buf(buf, buflen, cp_function_features->bits, osmo_pfcp_cp_feature_strs); -} - -int osmo_pfcp_dec_f_seid(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *tlv) -{ - struct osmo_pfcp_ie_f_seid *f_seid = decode_to; - uint8_t flags; - uint8_t pos; - unsigned int l; - /* flags and 8 octet seid */ - ENSURE_LENGTH_IS_AT_LEAST(9); - flags = tlv->val[0]; - f_seid->ip_addr.v6_present = flags & 1; - f_seid->ip_addr.v4_present = flags & 2; - f_seid->seid = osmo_load64be(&tlv->val[1]); - pos = 9; - if (f_seid->ip_addr.v4_present) { - l = sizeof(f_seid->ip_addr.v4.u.sin.sin_addr); - if (pos + l > tlv->len) - RETURN_ERROR(-EINVAL, "F-SEID IE is too short for the IPv4 address: %zu", tlv->len); - osmo_sockaddr_from_octets(&f_seid->ip_addr.v4, &tlv->val[pos], l); - pos += l; - } - if (f_seid->ip_addr.v6_present) { - l = sizeof(f_seid->ip_addr.v4.u.sin6.sin6_addr); - if (pos + l > tlv->len) - RETURN_ERROR(-EINVAL, "F-SEID IE is too short for the IPv6 address: %zu", tlv->len); - osmo_sockaddr_from_octets(&f_seid->ip_addr.v6, &tlv->val[pos], l); - pos += l; - } - return 0; -} - -int osmo_pfcp_enc_f_seid(struct osmo_gtlv_put *tlv, const void *decoded_struct, const void *encode_from) -{ - const struct osmo_pfcp_ie_f_seid *f_seid = encode_from; - unsigned int l; - uint8_t flags = (f_seid->ip_addr.v6_present ? 1 : 0) + (f_seid->ip_addr.v4_present ? 2 : 0); - /* flags and 8 octet seid */ - msgb_put_u8(tlv->dst, flags); - osmo_store64be(f_seid->seid, msgb_put(tlv->dst, 8)); - - if (f_seid->ip_addr.v4_present) { - if (f_seid->ip_addr.v4.u.sin.sin_family != AF_INET) - RETURN_ERROR(-EINVAL, - "f_seid IE indicates IPv4 address, but there is no ipv4_addr"); - l = sizeof(f_seid->ip_addr.v4.u.sin.sin_addr); - osmo_sockaddr_to_octets(msgb_put(tlv->dst, l), l, &f_seid->ip_addr.v4); - } - if (f_seid->ip_addr.v6_present) { - if (f_seid->ip_addr.v6.u.sin6.sin6_family != AF_INET6) - RETURN_ERROR(-EINVAL, - "f_seid IE indicates IPv6 address, but there is no ipv6_addr"); - l = sizeof(f_seid->ip_addr.v6.u.sin6.sin6_addr); - osmo_sockaddr_to_octets(msgb_put(tlv->dst, l), l, &f_seid->ip_addr.v6); - } - return 0; -} - -static int ip_addrs_to_str_buf(char *buf, size_t buflen, const struct osmo_pfcp_ip_addrs *addrs) -{ - struct osmo_strbuf sb = { .buf = buf, .len = buflen }; - if (addrs->v4_present) { - OSMO_STRBUF_PRINTF(sb, ",v4:"); - OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, &addrs->v4); - } - if (addrs->v6_present) { - OSMO_STRBUF_PRINTF(sb, ",v6:"); - OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, &addrs->v6); - } - return sb.chars_needed; -} - -int osmo_pfcp_enc_to_str_f_seid(char *buf, size_t buflen, const void *encode_from) -{ - const struct osmo_pfcp_ie_f_seid *f_seid = encode_from; - struct osmo_strbuf sb = { .buf = buf, .len = buflen }; - OSMO_STRBUF_PRINTF(sb, "0x%"PRIx64, f_seid->seid); - OSMO_STRBUF_APPEND(sb, ip_addrs_to_str_buf, &f_seid->ip_addr); - return sb.chars_needed; -} - -int osmo_pfcp_dec_f_teid(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *tlv) -{ - struct osmo_pfcp_ie_f_teid *f_teid = decode_to; - uint8_t flags; - const uint8_t *pos; - - *f_teid = (struct osmo_pfcp_ie_f_teid){}; - - pos = tlv->val; - - ENSURE_REMAINING_LENGTH_IS_AT_LEAST("flags", pos, 1); - flags = *pos; - pos++; - f_teid->choose_flag = flags & 4; - - if (!f_teid->choose_flag) { - /* A fixed TEID and address are provided */ - f_teid->fixed.ip_addr.v4_present = flags & 1; - f_teid->fixed.ip_addr.v6_present = flags & 2; - - ENSURE_REMAINING_LENGTH_IS_AT_LEAST("TEID", pos, 4); - f_teid->fixed.teid = osmo_load32be(pos); - pos += 4; - - if (f_teid->fixed.ip_addr.v4_present) { - osmo_static_assert(sizeof(f_teid->fixed.ip_addr.v4.u.sin.sin_addr) == 4, sin_addr_size_is_4); - ENSURE_REMAINING_LENGTH_IS_AT_LEAST("IPv4 address", pos, 4); - osmo_sockaddr_from_octets(&f_teid->fixed.ip_addr.v4, pos, 4); - pos += 4; - } - if (f_teid->fixed.ip_addr.v6_present) { - osmo_static_assert(sizeof(f_teid->fixed.ip_addr.v6.u.sin6.sin6_addr) == 16, sin6_addr_size_is_16); - ENSURE_REMAINING_LENGTH_IS_AT_LEAST("IPv6 address", pos, 16); - osmo_sockaddr_from_octets(&f_teid->fixed.ip_addr.v6, pos, 16); - pos += 16; - } - } else { - /* CH flag is 1, choose an F-TEID. */ - f_teid->choose.ipv4_addr = flags & 1; - f_teid->choose.ipv6_addr = flags & 2; - f_teid->choose.choose_id_present = flags & 8; - - if (f_teid->choose.choose_id_present) { - ENSURE_REMAINING_LENGTH_IS_AT_LEAST("CHOOSE ID", pos, 1); - f_teid->choose.choose_id = *pos; - pos++; - } - } - return 0; -} - -int osmo_pfcp_enc_f_teid(struct osmo_gtlv_put *tlv, const void *decoded_struct, const void *encode_from) -{ - const struct osmo_pfcp_ie_f_teid *f_teid = encode_from; - uint8_t flags; - - flags = (f_teid->choose_flag ? 4 : 0); - - if (!f_teid->choose_flag) { - /* A fixed TEID and address are provided */ - flags |= (f_teid->fixed.ip_addr.v4_present ? 1 : 0) - + (f_teid->fixed.ip_addr.v6_present ? 2 : 0); - - msgb_put_u8(tlv->dst, flags); - msgb_put_u32(tlv->dst, f_teid->fixed.teid); - - if (f_teid->fixed.ip_addr.v4_present) { - if (f_teid->fixed.ip_addr.v4.u.sin.sin_family != AF_INET) - RETURN_ERROR(-EINVAL, - "f_teid IE indicates IPv4 address, but there is no ipv4_addr" - " (sin_family = %d != AF_INET)", f_teid->fixed.ip_addr.v4.u.sin.sin_family); - osmo_sockaddr_to_octets(msgb_put(tlv->dst, 4), 4, &f_teid->fixed.ip_addr.v4); - } - if (f_teid->fixed.ip_addr.v6_present) { - if (f_teid->fixed.ip_addr.v6.u.sin6.sin6_family != AF_INET6) - RETURN_ERROR(-EINVAL, - "f_teid IE indicates IPv6 address, but there is no ipv6_addr" - " (sin6_family = %d != AF_INET6)", f_teid->fixed.ip_addr.v6.u.sin6.sin6_family); - osmo_sockaddr_to_octets(msgb_put(tlv->dst, 16), 16, &f_teid->fixed.ip_addr.v6); - } - } else { - flags |= (f_teid->choose.ipv4_addr ? 1 : 0) - + (f_teid->choose.ipv6_addr ? 2 : 0) - + (f_teid->choose.choose_id_present ? 8 : 0); - msgb_put_u8(tlv->dst, flags); - if (f_teid->choose.choose_id_present) - msgb_put_u8(tlv->dst, f_teid->choose.choose_id); - } - return 0; -} - -int osmo_pfcp_ie_f_teid_to_str_buf(char *buf, size_t buflen, const struct osmo_pfcp_ie_f_teid *ft) -{ - struct osmo_strbuf sb = { .buf = buf, .len = buflen }; - if (ft->choose_flag) { - OSMO_STRBUF_PRINTF(sb, "CHOOSE"); - if (ft->choose.ipv4_addr) - OSMO_STRBUF_PRINTF(sb, "-v4"); - if (ft->choose.ipv6_addr) - OSMO_STRBUF_PRINTF(sb, "-v6"); - if (ft->choose.choose_id_present) - OSMO_STRBUF_PRINTF(sb, "-id%u", ft->choose.choose_id); - } else { - OSMO_STRBUF_PRINTF(sb, "TEID-0x%x", ft->fixed.teid); - OSMO_STRBUF_APPEND(sb, ip_addrs_to_str_buf, &ft->fixed.ip_addr); - } - return sb.chars_needed; -} - -char *osmo_pfcp_ie_f_teid_to_str_c(void *ctx, const struct osmo_pfcp_ie_f_teid *ft) -{ - OSMO_NAME_C_IMPL(ctx, 64, "ERROR", osmo_pfcp_ie_f_teid_to_str_buf, ft) -} - -int osmo_pfcp_enc_to_str_f_teid(char *buf, size_t buflen, const void *encode_from) -{ - const struct osmo_pfcp_ie_f_teid *f_teid = encode_from; - return osmo_pfcp_ie_f_teid_to_str_buf(buf, buflen, f_teid); -} - -int osmo_pfcp_dec_apply_action(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *tlv) -{ - struct osmo_pfcp_ie_apply_action *apply_action = decode_to; - ENSURE_LENGTH_IS_AT_LEAST(1); - *apply_action = (struct osmo_pfcp_ie_apply_action){}; - memcpy(apply_action->bits, tlv->val, OSMO_MIN(tlv->len, sizeof(apply_action->bits))); - return 0; -} - -int osmo_pfcp_enc_apply_action(struct osmo_gtlv_put *tlv, const void *decoded_struct, const void *encode_from) -{ - const struct osmo_pfcp_ie_apply_action *apply_action = encode_from; - memcpy(msgb_put(tlv->dst, sizeof(apply_action->bits)), - apply_action->bits, sizeof(apply_action->bits)); - return 0; -} - -int osmo_pfcp_enc_to_str_apply_action(char *buf, size_t buflen, const void *encode_from) -{ - const struct osmo_pfcp_ie_apply_action *apply_action = encode_from; - return osmo_pfcp_bits_to_str_buf(buf, buflen, apply_action->bits, osmo_pfcp_apply_action_strs); -} - -int osmo_pfcp_dec_network_inst(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *tlv) -{ - struct osmo_pfcp_ie_network_inst *network_inst = decode_to; - osmo_strlcpy(network_inst->str, (const char *)tlv->val, OSMO_MIN(sizeof(network_inst->str), tlv->len+1)); - return 0; -} - -int osmo_pfcp_enc_network_inst(struct osmo_gtlv_put *tlv, const void *decoded_struct, const void *encode_from) -{ - const struct osmo_pfcp_ie_network_inst *network_inst = encode_from; - unsigned int l = strlen(network_inst->str); - if (l) - memcpy(msgb_put(tlv->dst, l), network_inst->str, l); - return 0; -} - -int osmo_pfcp_enc_to_str_network_inst(char *buf, size_t buflen, const void *encode_from) -{ - const struct osmo_pfcp_ie_network_inst *network_inst = encode_from; - return osmo_quote_str_buf3(buf, buflen, network_inst->str, - strnlen(network_inst->str, sizeof(network_inst->str))); -} - -int osmo_pfcp_dec_outer_header_creation(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *tlv) -{ - struct osmo_pfcp_ie_outer_header_creation *ohc = decode_to; - const uint8_t *pos; - bool gtp_u_udp_ipv4; - bool gtp_u_udp_ipv6; - bool udp_ipv4; - bool udp_ipv6; - bool ipv4; - bool ipv6; - bool c_tag; - bool s_tag; - - *ohc = (struct osmo_pfcp_ie_outer_header_creation){}; - - ENSURE_LENGTH_IS_AT_LEAST(2); - - memcpy(ohc->desc_bits, tlv->val, 2); - - gtp_u_udp_ipv4 = osmo_pfcp_bits_get(ohc->desc_bits, OSMO_PFCP_OUTER_HEADER_CREATION_GTP_U_UDP_IPV4); - udp_ipv4 = osmo_pfcp_bits_get(ohc->desc_bits, OSMO_PFCP_OUTER_HEADER_CREATION_UDP_IPV4); - ipv4 = osmo_pfcp_bits_get(ohc->desc_bits, OSMO_PFCP_OUTER_HEADER_CREATION_IPV4); - gtp_u_udp_ipv6 = osmo_pfcp_bits_get(ohc->desc_bits, OSMO_PFCP_OUTER_HEADER_CREATION_GTP_U_UDP_IPV6); - udp_ipv6 = osmo_pfcp_bits_get(ohc->desc_bits, OSMO_PFCP_OUTER_HEADER_CREATION_UDP_IPV6); - ipv6 = osmo_pfcp_bits_get(ohc->desc_bits, OSMO_PFCP_OUTER_HEADER_CREATION_IPV6); - c_tag = osmo_pfcp_bits_get(ohc->desc_bits, OSMO_PFCP_OUTER_HEADER_CREATION_C_TAG); - s_tag = osmo_pfcp_bits_get(ohc->desc_bits, OSMO_PFCP_OUTER_HEADER_CREATION_S_TAG); - - pos = tlv->val + 2; - if (gtp_u_udp_ipv4 || gtp_u_udp_ipv6) { - ENSURE_REMAINING_LENGTH_IS_AT_LEAST("TEID", pos, 4); - ohc->teid_present = true; - ohc->teid = osmo_load32be(pos); - pos += 4; - } - if (gtp_u_udp_ipv4 || udp_ipv4 || ipv4) { - ENSURE_REMAINING_LENGTH_IS_AT_LEAST("IPv4 address", pos, 4); - ohc->ip_addr.v4_present = true; - osmo_sockaddr_from_octets(&ohc->ip_addr.v4, pos, 4); - pos += 4; - } - if (gtp_u_udp_ipv6 || udp_ipv6 || ipv6) { - ENSURE_REMAINING_LENGTH_IS_AT_LEAST("IPv6 address", pos, 16); - ohc->ip_addr.v6_present = true; - osmo_sockaddr_from_octets(&ohc->ip_addr.v6, pos, 16); - pos += 16; - } - if (udp_ipv4 || udp_ipv6) { - ENSURE_REMAINING_LENGTH_IS_AT_LEAST("UDP port number", pos, 2); - ohc->port_number_present = true; - ohc->port_number = osmo_load16be(pos); - pos += 2; - } - if (c_tag) { - ohc->c_tag_present = true; - ENSURE_REMAINING_LENGTH_IS_AT_LEAST("C-TAG", pos, 3); - ohc->c_tag_present = true; - ohc->c_tag = osmo_load32be_ext_2(pos, 3); - pos += 3; - } - if (s_tag) { - ohc->s_tag_present = true; - ENSURE_REMAINING_LENGTH_IS_AT_LEAST("S-TAG", pos, 3); - ohc->s_tag_present = true; - ohc->s_tag = osmo_load32be_ext_2(pos, 3); - pos += 3; - } - - return 0; -} - -int osmo_pfcp_enc_outer_header_creation(struct osmo_gtlv_put *tlv, const void *decoded_struct, const void *encode_from) -{ - const struct osmo_pfcp_ie_outer_header_creation *ohc = encode_from; - bool gtp_u_udp_ipv4; - bool gtp_u_udp_ipv6; - bool udp_ipv4; - bool udp_ipv6; - bool ipv4; - bool ipv6; - bool c_tag; - bool s_tag; - - memcpy(msgb_put(tlv->dst, sizeof(ohc->desc_bits)), ohc->desc_bits, sizeof(ohc->desc_bits)); - - gtp_u_udp_ipv4 = osmo_pfcp_bits_get(ohc->desc_bits, OSMO_PFCP_OUTER_HEADER_CREATION_GTP_U_UDP_IPV4); - udp_ipv4 = osmo_pfcp_bits_get(ohc->desc_bits, OSMO_PFCP_OUTER_HEADER_CREATION_UDP_IPV4); - ipv4 = osmo_pfcp_bits_get(ohc->desc_bits, OSMO_PFCP_OUTER_HEADER_CREATION_IPV4); - gtp_u_udp_ipv6 = osmo_pfcp_bits_get(ohc->desc_bits, OSMO_PFCP_OUTER_HEADER_CREATION_GTP_U_UDP_IPV6); - udp_ipv6 = osmo_pfcp_bits_get(ohc->desc_bits, OSMO_PFCP_OUTER_HEADER_CREATION_UDP_IPV6); - ipv6 = osmo_pfcp_bits_get(ohc->desc_bits, OSMO_PFCP_OUTER_HEADER_CREATION_IPV6); - c_tag = osmo_pfcp_bits_get(ohc->desc_bits, OSMO_PFCP_OUTER_HEADER_CREATION_C_TAG); - s_tag = osmo_pfcp_bits_get(ohc->desc_bits, OSMO_PFCP_OUTER_HEADER_CREATION_S_TAG); - - if ((gtp_u_udp_ipv4 || gtp_u_udp_ipv6) != (ohc->teid_present)) - RETURN_ERROR(-EINVAL, "teid_present = %s does not match the description bits 0x%02x\n", - ohc->teid_present ? "true" : "false", - ohc->desc_bits[0]); - if (ohc->teid_present) - msgb_put_u32(tlv->dst, ohc->teid); - - if ((gtp_u_udp_ipv4 || udp_ipv4 || ipv4) != ohc->ip_addr.v4_present) - RETURN_ERROR(-EINVAL, "ipv4_addr_present = %s does not match the description bits 0x%02x\n", - ohc->ip_addr.v4_present ? "true" : "false", - ohc->desc_bits[0]); - if (ohc->ip_addr.v4_present) - osmo_sockaddr_to_octets(msgb_put(tlv->dst, 4), 4, &ohc->ip_addr.v4); - - if ((gtp_u_udp_ipv6 || udp_ipv6 || ipv6) != ohc->ip_addr.v6_present) - RETURN_ERROR(-EINVAL, "ipv6_addr_present = %s does not match the description bits 0x%02x\n", - ohc->ip_addr.v6_present ? "true" : "false", - ohc->desc_bits[0]); - if (ohc->ip_addr.v6_present) - osmo_sockaddr_to_octets(msgb_put(tlv->dst, 16), 16, &ohc->ip_addr.v6); - - if ((udp_ipv4 || udp_ipv6) != ohc->port_number_present) - RETURN_ERROR(-EINVAL, "port_number_present = %s does not match the description bits 0x%02x\n", - ohc->port_number_present ? "true" : "false", - ohc->desc_bits[0]); - if (ohc->port_number_present) - msgb_put_u16(tlv->dst, ohc->port_number); - - if (c_tag != ohc->c_tag_present) - RETURN_ERROR(-EINVAL, "c_tag_present = %s does not match the description bits 0x%02x%02x\n", - ohc->c_tag_present ? "true" : "false", - ohc->desc_bits[1], ohc->desc_bits[0]); - if (ohc->c_tag_present) - osmo_store32be_ext(ohc->c_tag, msgb_put(tlv->dst, 3), 3); - - if (s_tag != ohc->s_tag_present) - RETURN_ERROR(-EINVAL, "s_tag_present = %s does not match the description bits 0x%02x%02x\n", - ohc->s_tag_present ? "true" : "false", - ohc->desc_bits[1], ohc->desc_bits[0]); - if (ohc->s_tag_present) - osmo_store32be_ext(ohc->s_tag, msgb_put(tlv->dst, 3), 3); - - return 0; -} - -int osmo_pfcp_enc_to_str_outer_header_creation(char *buf, size_t buflen, const void *encode_from) -{ - const struct osmo_pfcp_ie_outer_header_creation *ohc = encode_from; - struct osmo_strbuf sb = { .buf = buf, .len = buflen }; - OSMO_STRBUF_APPEND(sb, osmo_pfcp_bits_to_str_buf, ohc->desc_bits, osmo_pfcp_outer_header_creation_strs); - if (ohc->teid_present) - OSMO_STRBUF_PRINTF(sb, ",TEID:0x%x", ohc->teid); - OSMO_STRBUF_APPEND(sb, ip_addrs_to_str_buf, &ohc->ip_addr); - if (ohc->port_number_present) - OSMO_STRBUF_PRINTF(sb, ",port:%u", ohc->port_number); - if (ohc->c_tag_present) - OSMO_STRBUF_PRINTF(sb, ",c-tag:%u", ohc->c_tag); - if (ohc->s_tag_present) - OSMO_STRBUF_PRINTF(sb, ",s-tag:%u", ohc->s_tag); - return sb.chars_needed; -} - -int osmo_pfcp_dec_activate_predefined_rules(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *tlv) -{ - struct osmo_pfcp_ie_activate_predefined_rules *activate_predefined_rules = decode_to; - osmo_strlcpy(activate_predefined_rules->str, (const char *)tlv->val, OSMO_MIN(sizeof(activate_predefined_rules->str), tlv->len+1)); - return 0; -} - -int osmo_pfcp_enc_activate_predefined_rules(struct osmo_gtlv_put *tlv, const void *decoded_struct, const void *encode_from) -{ - const struct osmo_pfcp_ie_activate_predefined_rules *activate_predefined_rules = encode_from; - unsigned int l = strlen(activate_predefined_rules->str); - if (l) - memcpy(msgb_put(tlv->dst, l), activate_predefined_rules->str, l); - return 0; -} - -int osmo_pfcp_enc_to_str_activate_predefined_rules(char *buf, size_t buflen, const void *encode_from) -{ - const struct osmo_pfcp_ie_activate_predefined_rules *activate_predefined_rules = encode_from; - return osmo_quote_str_buf3(buf, buflen, activate_predefined_rules->str, - strnlen(activate_predefined_rules->str, sizeof(activate_predefined_rules->str))); -} - -int osmo_pfcp_dec_outer_header_removal(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *tlv) -{ - struct osmo_pfcp_ie_outer_header_removal *outer_header_removal = decode_to; - ENSURE_LENGTH_IS_AT_LEAST(1); - outer_header_removal->desc = tlv->val[0]; - - if (tlv->len > 1) { - outer_header_removal->gtp_u_extension_header_del_present = true; - memcpy(outer_header_removal->gtp_u_extension_header_del_bits, &tlv->val[1], - sizeof(outer_header_removal->gtp_u_extension_header_del_bits)); - } - return 0; -} - -int osmo_pfcp_enc_outer_header_removal(struct osmo_gtlv_put *tlv, const void *decoded_struct, const void *encode_from) -{ - const struct osmo_pfcp_ie_outer_header_removal *outer_header_removal = encode_from; - msgb_put_u8(tlv->dst, outer_header_removal->desc); - if (outer_header_removal->gtp_u_extension_header_del_present) { - memcpy(msgb_put(tlv->dst, sizeof(outer_header_removal->gtp_u_extension_header_del_bits)), - outer_header_removal->gtp_u_extension_header_del_bits, - sizeof(outer_header_removal->gtp_u_extension_header_del_bits)); - } - return 0; -} - -int osmo_pfcp_enc_to_str_outer_header_removal(char *buf, size_t buflen, const void *encode_from) -{ - const struct osmo_pfcp_ie_outer_header_removal *outer_header_removal = encode_from; - struct osmo_strbuf sb = { .buf = buf, .len = buflen }; - OSMO_STRBUF_PRINTF(sb, "%s", osmo_pfcp_outer_header_removal_desc_str(outer_header_removal->desc)); - if (outer_header_removal->gtp_u_extension_header_del_present) - OSMO_STRBUF_PRINTF(sb, ",ext-hdr-del:0x%x", outer_header_removal->gtp_u_extension_header_del_bits[0]); - return sb.chars_needed; -} - -int osmo_pfcp_dec_ue_ip_address(void *decoded_struct, void *decode_to, const struct osmo_gtlv_load *tlv) -{ - struct osmo_pfcp_ie_ue_ip_address *ue_ip_address = decode_to; - const uint8_t *pos; - uint8_t flags; - - pos = tlv->val; - - ENSURE_REMAINING_LENGTH_IS_AT_LEAST("flags", pos, 1); - flags = *pos; - pos++; - - ue_ip_address->ipv6_prefix_length_present = flags & (1 << 6); - ue_ip_address->chv6 = flags & (1 << 5); - ue_ip_address->chv4 = flags & (1 << 4); - ue_ip_address->ipv6_prefix_delegation_bits_present = flags & (1 << 3); - ue_ip_address->ip_is_destination = flags & (1 << 2); - ue_ip_address->ip_addr.v4_present = flags & (1 << 1); - ue_ip_address->ip_addr.v6_present = flags & (1 << 0); - - if (ue_ip_address->ip_addr.v4_present) { - ENSURE_REMAINING_LENGTH_IS_AT_LEAST("IPv4 address", pos, 4); - osmo_sockaddr_from_octets(&ue_ip_address->ip_addr.v4, pos, 4); - pos += 4; - } - if (ue_ip_address->ip_addr.v6_present) { - ENSURE_REMAINING_LENGTH_IS_AT_LEAST("IPv6 address", pos, 16); - osmo_sockaddr_from_octets(&ue_ip_address->ip_addr.v6, pos, 16); - pos += 16; - } - - if (ue_ip_address->ipv6_prefix_delegation_bits_present) { - ENSURE_REMAINING_LENGTH_IS_AT_LEAST("IPv6 prefix delegation bits", pos, 1); - ue_ip_address->ipv6_prefix_delegation_bits = *pos; - pos++; - } - if (ue_ip_address->ipv6_prefix_length_present) { - ENSURE_REMAINING_LENGTH_IS_AT_LEAST("IPv6 prefix length", pos, 1); - ue_ip_address->ipv6_prefix_length = *pos; - pos++; - } - - return 0; -} - -int osmo_pfcp_enc_ue_ip_address(struct osmo_gtlv_put *tlv, const void *decoded_struct, const void *encode_from) -{ - const struct osmo_pfcp_ie_ue_ip_address *ue_ip_address = encode_from; - unsigned int l; - uint8_t flags; - - flags = 0 - | (ue_ip_address->ipv6_prefix_length_present ? (1 << 6) : 0) - | (ue_ip_address->chv6 ? (1 << 5) : 0) - | (ue_ip_address->chv4 ? (1 << 4) : 0) - | (ue_ip_address->ipv6_prefix_delegation_bits_present ? (1 << 3) : 0) - | (ue_ip_address->ip_is_destination ? (1 << 2) : 0) - | (ue_ip_address->ip_addr.v4_present ? (1 << 1) : 0) - | (ue_ip_address->ip_addr.v6_present ? (1 << 0) : 0) - ; - - msgb_put_u8(tlv->dst, flags); - - if (ue_ip_address->ip_addr.v4_present) { - if (ue_ip_address->ip_addr.v4.u.sin.sin_family != AF_INET) - RETURN_ERROR(-EINVAL, - "ue_ip_address IE indicates IPv4 address, but there is no ipv4_addr"); - l = sizeof(ue_ip_address->ip_addr.v4.u.sin.sin_addr); - osmo_sockaddr_to_octets(msgb_put(tlv->dst, l), l, &ue_ip_address->ip_addr.v4); - } - if (ue_ip_address->ip_addr.v6_present) { - if (ue_ip_address->ip_addr.v6.u.sin6.sin6_family != AF_INET6) - RETURN_ERROR(-EINVAL, - "ue_ip_address IE indicates IPv6 address, but there is no ipv6_addr"); - l = sizeof(ue_ip_address->ip_addr.v6.u.sin6.sin6_addr); - osmo_sockaddr_to_octets(msgb_put(tlv->dst, l), l, &ue_ip_address->ip_addr.v6); - } - - if (ue_ip_address->ipv6_prefix_delegation_bits_present) - msgb_put_u8(tlv->dst, ue_ip_address->ipv6_prefix_delegation_bits); - - if (ue_ip_address->ipv6_prefix_length_present) - msgb_put_u8(tlv->dst, ue_ip_address->ipv6_prefix_length); - - return 0; -} - -int osmo_pfcp_enc_to_str_ue_ip_address(char *buf, size_t buflen, const void *encode_from) -{ - const struct osmo_pfcp_ie_ue_ip_address *uia = encode_from; - struct osmo_strbuf sb = { .buf = buf, .len = buflen }; - if (uia->chv4) - OSMO_STRBUF_PRINTF(sb, "chv4"); - if (uia->chv6) - OSMO_STRBUF_PRINTF(sb, "%schv4", sb.pos ? "," : ""); - if (uia->ip_is_destination) - OSMO_STRBUF_PRINTF(sb, "%sdst", sb.pos ? "," : ""); - OSMO_STRBUF_APPEND(sb, ip_addrs_to_str_buf, &uia->ip_addr); - if (uia->ipv6_prefix_delegation_bits_present) - OSMO_STRBUF_PRINTF(sb, ",ipv6-prefix-deleg:%x", uia->ipv6_prefix_delegation_bits); - if (uia->ipv6_prefix_length_present) - OSMO_STRBUF_PRINTF(sb, ",ipv6-prefix-len:%u", uia->ipv6_prefix_length); - return sb.chars_needed; -} diff --git a/src/libosmo-pfcp/pfcp_msg.c b/src/libosmo-pfcp/pfcp_msg.c deleted file mode 100644 index 9d65efc..0000000 --- a/src/libosmo-pfcp/pfcp_msg.c +++ /dev/null @@ -1,540 +0,0 @@ -/* - * (C) 2021-2022 by sysmocom - s.f.m.c. GmbH info@sysmocom.de - * All Rights Reserved. - * - * Author: Neels Janosch Hofmeyr nhofmeyr@sysmocom.de - * - * SPDX-License-Identifier: GPL-2.0+ - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. - * - */ - -#include <errno.h> -#include <string.h> - -#include <osmocom/core/endian.h> -#include <osmocom/core/logging.h> -#include <osmocom/core/fsm.h> -#include <osmocom/core/use_count.h> -#include <osmocom/core/bitvec.h> - -#include <osmocom/pfcp/pfcp_msg.h> -#include <osmocom/gtlv/gtlv_dec_enc.h> - -/* Assumes presence of local variable osmo_pfcp_msg *m. m->log_ctx may be NULL. */ -#define RETURN_ERROR(RC, FMT, ARGS...) \ - do {\ - OSMO_ASSERT(m); \ - OSMO_LOG_PFCP_MSG(m, LOGL_ERROR, FMT " (%d: %s)\n", ##ARGS, RC, strerror((RC) > 0 ? (RC) : -(RC))); \ - return RC; \ - } while (0) - -bool osmo_pfcp_msgtype_is_response(enum osmo_pfcp_message_type message_type) -{ - switch (message_type) { - case OSMO_PFCP_MSGT_HEARTBEAT_RESP: - case OSMO_PFCP_MSGT_PFD_MGMT_RESP: - case OSMO_PFCP_MSGT_ASSOC_SETUP_RESP: - case OSMO_PFCP_MSGT_ASSOC_UPDATE_RESP: - case OSMO_PFCP_MSGT_ASSOC_RELEASE_RESP: - case OSMO_PFCP_MSGT_VERSION_NOT_SUPP_RESP: - case OSMO_PFCP_MSGT_NODE_REPORT_RESP: - case OSMO_PFCP_MSGT_SESSION_SET_DEL_RESP: - case OSMO_PFCP_MSGT_SESSION_EST_RESP: - case OSMO_PFCP_MSGT_SESSION_MOD_RESP: - case OSMO_PFCP_MSGT_SESSION_DEL_RESP: - case OSMO_PFCP_MSGT_SESSION_REP_RESP: - return true; - default: - return false; - } -} - -struct osmo_pfcp_header_common { -#if OSMO_IS_LITTLE_ENDIAN - uint8_t seid_present:1, - message_priority_present:1, - follow_on:1, - spare:2, - version:3; - uint8_t message_type; - uint16_t message_length; -#elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ - uint8_t version:3, spare:2, follow_on:1, message_priority_present:1, seid_present:1; - uint8_t message_type; - uint16_t message_length; -#endif -} __attribute__ ((packed)); - -struct osmo_pfcp_header_no_seid { - struct osmo_pfcp_header_common c; - uint8_t sequence_nr[3]; - uint8_t spare; -} __attribute__ ((packed)); - -struct osmo_pfcp_header_seid { -#if OSMO_IS_LITTLE_ENDIAN - struct osmo_pfcp_header_common c; - uint64_t session_endpoint_identifier; - uint8_t sequence_nr[3]; - uint8_t message_priority:4, - spare:4; -#elif OSMO_IS_BIG_ENDIAN -/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianess.py) */ - struct osmo_pfcp_header_common c; - uint64_t session_endpoint_identifier; - uint8_t sequence_nr[3]; - uint8_t spare:4, message_priority:4; -#endif -} __attribute__ ((packed)); - -int osmo_pfcp_ie_node_id_from_osmo_sockaddr(struct osmo_pfcp_ie_node_id *node_id, const struct osmo_sockaddr *os) -{ - switch (os->u.sa.sa_family) { - case AF_INET: - node_id->type = OSMO_PFCP_NODE_ID_T_IPV4; - break; - case AF_INET6: - node_id->type = OSMO_PFCP_NODE_ID_T_IPV6; - break; - default: - return -ENOTSUP; - } - node_id->ip = *os; - return 0; -} - -int osmo_pfcp_ie_node_id_to_osmo_sockaddr(const struct osmo_pfcp_ie_node_id *node_id, struct osmo_sockaddr *os) -{ - switch (node_id->type) { - case OSMO_PFCP_NODE_ID_T_IPV4: - if (os->u.sa.sa_family != AF_INET) - return -EINVAL; - break; - case OSMO_PFCP_NODE_ID_T_IPV6: - if (os->u.sa.sa_family != AF_INET6) - return -EINVAL; - break; - default: - return -ENOTSUP; - } - *os = node_id->ip; - return 0; -} - -static int pfcp_header_set_message_length(struct osmo_pfcp_header_common *c, unsigned int header_and_payload_len) -{ - if (header_and_payload_len < sizeof(struct osmo_pfcp_header_common)) - return -EINVAL; - if (header_and_payload_len - sizeof(struct osmo_pfcp_header_common) > UINT16_MAX) - return -EMSGSIZE; - osmo_store16be(header_and_payload_len - sizeof(struct osmo_pfcp_header_common), - &c->message_length); - return 0; -} - -static unsigned int pfcp_header_get_message_length(const struct osmo_pfcp_header_common *c) -{ - unsigned int len = osmo_load16be(&c->message_length); - return len + sizeof(struct osmo_pfcp_header_common); -} - -/*! Encode and append the given PFCP header to a msgb. - * \param[out] msg message buffer to which to push the header. - * \param[in] to-be-encoded representation of PFCP header. */ -static int enc_pfcp_header(struct msgb *msg, const struct osmo_pfcp_msg *m) -{ - const struct osmo_pfcp_header_parsed *parsed = &m->h; - struct osmo_pfcp_header_seid *h_seid; - struct osmo_pfcp_header_no_seid *h_no_seid; - struct osmo_pfcp_header_common *c; - int rc; - - if (!parsed->seid_present) { - h_no_seid = (struct osmo_pfcp_header_no_seid *)msgb_put(msg, sizeof(struct osmo_pfcp_header_no_seid)); - c = &h_no_seid->c; - } else { - h_seid = (struct osmo_pfcp_header_seid *)msgb_put(msg, sizeof(struct osmo_pfcp_header_seid)); - c = &h_seid->c; - } - - *c = (struct osmo_pfcp_header_common){ - .version = parsed->version, - .message_priority_present = (parsed->priority_present ? 1 : 0), - .seid_present = (parsed->seid_present ? 1 : 0), - .message_type = parsed->message_type, - }; - - /* Put a preliminary length reflecting only the header, until it is updated later in osmo_pfcp_msg_encode(). */ - rc = pfcp_header_set_message_length(c, parsed->seid_present ? sizeof(struct osmo_pfcp_header_seid) - : sizeof(struct osmo_pfcp_header_no_seid)); - if (rc) - RETURN_ERROR(rc, "Problem with PFCP message length"); - - if (!parsed->seid_present) { - osmo_store32be_ext(parsed->sequence_nr, h_no_seid->sequence_nr, 3); - if (parsed->priority_present) - RETURN_ERROR(-EINVAL, "Message Priority can only be present when the SEID is also present"); - } else { - osmo_store64be(parsed->seid, &h_seid->session_endpoint_identifier); - osmo_store32be_ext(parsed->sequence_nr, h_seid->sequence_nr, 3); - if (parsed->priority_present) - h_seid->message_priority = parsed->priority; - } - - return 0; -} - -static void osmo_pfcp_msg_set_memb_ofs(struct osmo_pfcp_msg *m) -{ - const struct osmo_gtlv_coding *mc = osmo_pfcp_get_msg_coding(m->h.message_type); - m->ofs_cause = 0; - m->ofs_node_id = 0; - if (!mc) - return; - for (; !osmo_gtlv_coding_end(mc) && (m->ofs_cause == 0 || m->ofs_node_id == 0); mc++) { - if (mc->ti.tag == OSMO_PFCP_IEI_CAUSE) - m->ofs_cause = offsetof(struct osmo_pfcp_msg, ies) + mc->memb_ofs; - if (mc->ti.tag == OSMO_PFCP_IEI_NODE_ID) - m->ofs_node_id = offsetof(struct osmo_pfcp_msg, ies) + mc->memb_ofs; - } -}; - -/*! Decode a single PFCP message's header. - * - * If msg->l4h is non-NULL, decode at msgb_l4(msg). If l4h is NULL, decode at msgb_l3(msg). - * In case of bundled PFCP messages, decode only one message and return the offset to the next message in the buffer. - * Hence, to decode a message bundle, increment msg->l4h until all messages are decoded: - * - * msg->l4h = msg->l3h; - * while (msgb_l4len(msg)) { - * struct osmo_pfcp_msg m; - * struct osmo_gtlv_load tlv; - * int rc; - * rc = osmo_pfcp_msg_decode_header(&tlv, &m, msg); - * if (rc < 0) - * error(); - * msg->l4h += rc; - * - * if (osmo_pfcp_msg_decode_tlv(&m, &tlv)) - * error(); - * handle(&m); - * } - * - * \param[out] tlv Return TLV start pointer and length in tlv->src.*. - * \param[inout] m Place the decoded data in m->h; use m->ctx.* as logging context. - * \param[in] msg PFCP data to parse, possibly containing a PFCP message bundle. - * \return total single PFCP message length (<= data_len) on success, negative on error. - */ -int osmo_pfcp_msg_decode_header(struct osmo_gtlv_load *tlv, struct osmo_pfcp_msg *m, - const struct msgb *msg) -{ - struct osmo_pfcp_header_parsed *parsed = &m->h; - const uint8_t *pfcp_msg_data; - unsigned int pfcp_msg_data_len; - unsigned int header_len; - unsigned int message_length; - const struct osmo_pfcp_header_common *c; - - if (msg->l4h) { - pfcp_msg_data = msgb_l4(msg); - pfcp_msg_data_len = msgb_l4len(msg); - } else { - pfcp_msg_data = msgb_l3(msg); - pfcp_msg_data_len = msgb_l3len(msg); - } - - if (!pfcp_msg_data || !pfcp_msg_data_len) - RETURN_ERROR(-EINVAL, "No Layer 3 data in this message buffer"); - - if (pfcp_msg_data_len < sizeof(struct osmo_pfcp_header_common)) - RETURN_ERROR(-EINVAL, "Message too short for PFCP header: %u", pfcp_msg_data_len); - - c = (void *)pfcp_msg_data; - - header_len = (c->seid_present ? sizeof(struct osmo_pfcp_header_seid) : sizeof(struct osmo_pfcp_header_no_seid)); - if (pfcp_msg_data_len < header_len) - RETURN_ERROR(-EINVAL, "Message too short for PFCP header: %u", pfcp_msg_data_len); - - *parsed = (struct osmo_pfcp_header_parsed){ - .version = c->version, - .priority_present = (bool)c->message_priority_present, - .seid_present = (bool)c->seid_present, - .message_type = c->message_type, - }; - - m->is_response = osmo_pfcp_msgtype_is_response(parsed->message_type); - osmo_pfcp_msg_set_memb_ofs(m); - - message_length = pfcp_header_get_message_length(c); - if (message_length > pfcp_msg_data_len) - RETURN_ERROR(-EMSGSIZE, - "The header's indicated total message length %u is larger than the received data %u", - message_length, pfcp_msg_data_len); - - /* T16L16V payload data and len */ - *tlv = (struct osmo_gtlv_load){ - .cfg = &osmo_t16l16v_cfg, - .src = { - .data = pfcp_msg_data + header_len, - .len = message_length - header_len, - }, - }; - - if (c->follow_on) { - /* Another PFCP message should follow */ - if (pfcp_msg_data_len - message_length < sizeof(struct osmo_pfcp_header_common)) - OSMO_LOG_PFCP_MSG(m, LOGL_INFO, - "PFCP message indicates more messages should follow in the bundle," - " but remaining size %u is too short", pfcp_msg_data_len - message_length); - } else { - /* No more PFCP message should follow in the bundle */ - if (pfcp_msg_data_len > message_length) - OSMO_LOG_PFCP_MSG(m, LOGL_INFO, "Surplus data after PFCP message: %u", - pfcp_msg_data_len - message_length); - } - - if (!parsed->seid_present) { - const struct osmo_pfcp_header_no_seid *h_no_seid = (void *)pfcp_msg_data; - parsed->sequence_nr = osmo_load32be_ext_2(h_no_seid->sequence_nr, 3); - if (parsed->priority_present) - RETURN_ERROR(-EINVAL, "Message Priority can only be present when the SEID is also present"); - } else { - const struct osmo_pfcp_header_seid *h_seid = (void *)pfcp_msg_data; - parsed->seid = osmo_load64be(&h_seid->session_endpoint_identifier); - parsed->sequence_nr = osmo_load32be_ext_2(h_seid->sequence_nr, 3); - if (parsed->priority_present) - parsed->priority = h_seid->message_priority; - } - - return message_length; -} - -void osmo_pfcp_msg_err_cb(void *data, void *decoded_struct, const char *file, int line, const char *fmt, ...) -{ - va_list ap; - if (log_check_level(DLPFCP, LOGL_ERROR)) { - char *errmsg; - - va_start(ap, fmt); - errmsg = talloc_vasprintf(OTC_SELECT, fmt, ap); - va_end(ap); - OSMO_LOG_PFCP_MSG_SRC((struct osmo_pfcp_msg *)data, LOGL_ERROR, file, line, "%s", errmsg); - } -} - -int osmo_pfcp_msg_decode_tlv(struct osmo_pfcp_msg *m, struct osmo_gtlv_load *tlv) -{ - return osmo_pfcp_ies_decode(&m->ies, tlv, false, m->h.message_type, osmo_pfcp_msg_err_cb, m, osmo_pfcp_iei_strs); -} - -static int osmo_pfcp_msg_encode_tlv(struct msgb *msg, const struct osmo_pfcp_msg *m) -{ - struct osmo_gtlv_put tlv = { - .cfg = &osmo_t16l16v_cfg, - .dst = msg, - }; - return osmo_pfcp_ies_encode(&tlv, &m->ies, m->h.message_type, osmo_pfcp_msg_err_cb, (void *)m, osmo_pfcp_iei_strs); -} - -/* Append the encoded PFCP message to the message buffer. - * - * If msg->l3h is NULL, point it at the start of the encoded message. - * Always point msg->l4h at the start of the newly encoded message. - * Hence, in a message bundle, msg->l3h always points at the first PFCP message, while msg->l4h always points at the - * last PFCP message. - * - * When adding a PFCP message to a bundle, set the Follow On (FO) flag of the previously last message to 1, and of the - * newly encoded, now last message as 0. - * - * To log errors to a specific osmo_fsm_inst, point m->log_ctx to that instance before calling this function. Otherwise - * set log_ctx = NULL. - * - * \return 0 on success, negative on error. */ -int osmo_pfcp_msg_encode(struct msgb *msg, const struct osmo_pfcp_msg *m) -{ - struct osmo_pfcp_header_common *c; - int rc; - - /* Forming a bundle? If yes, set the Follow On flag of the currently last message to 1 */ - if (msg->l4h && msgb_l4len(msg)) { - c = msgb_l4(msg); - c->follow_on = 1; - } - /* Make sure l3h points at the first PFCP message in a message bundle */ - if (!msg->l3h) - msg->l3h = msg->tail; - /* Make sure l4h points at the last PFCP message in a message bundle */ - msg->l4h = msg->tail; - c = (void *)msg->tail; - - rc = enc_pfcp_header(msg, m); - if (rc) - return rc; - - rc = osmo_pfcp_msg_encode_tlv(msg, m); - if (rc) - return rc; - - /* Update the header's message_length */ - rc = pfcp_header_set_message_length(c, msgb_l4len(msg)); - if (rc) - RETURN_ERROR(rc, "Problem with PFCP message length"); - return 0; -} - -static int osmo_pfcp_msg_destructor(struct osmo_pfcp_msg *m); - -static struct osmo_pfcp_msg *_osmo_pfcp_msg_alloc(void *ctx, const struct osmo_sockaddr *remote_addr) -{ - struct osmo_pfcp_msg *m = talloc(ctx, struct osmo_pfcp_msg); - *m = (struct osmo_pfcp_msg){ - .remote_addr = *remote_addr, - .h = { - .version = 1, - }, - }; - talloc_set_destructor(m, osmo_pfcp_msg_destructor); - return m; -} - -struct osmo_pfcp_msg *osmo_pfcp_msg_alloc_rx(void *ctx, const struct osmo_sockaddr *remote_addr) -{ - struct osmo_pfcp_msg *rx = _osmo_pfcp_msg_alloc(ctx, remote_addr); - rx->rx = true; - return rx; -} - -struct osmo_pfcp_msg *osmo_pfcp_msg_alloc_tx(void *ctx, const struct osmo_sockaddr *remote_addr, - const struct osmo_pfcp_ie_node_id *node_id, - const struct osmo_pfcp_msg *in_reply_to, - enum osmo_pfcp_message_type msg_type) -{ - struct osmo_pfcp_msg *tx; - if (!remote_addr && in_reply_to) - remote_addr = &in_reply_to->remote_addr; - OSMO_ASSERT(remote_addr); - tx = _osmo_pfcp_msg_alloc(ctx, remote_addr); - tx->is_response = osmo_pfcp_msgtype_is_response(msg_type); - tx->h.message_type = msg_type; - if (in_reply_to) - tx->h.sequence_nr = in_reply_to->h.sequence_nr; - osmo_pfcp_msg_set_memb_ofs(tx); - - /* Write the local node id data to the correct tx->ies.* member. */ - if (node_id) { - struct osmo_pfcp_ie_node_id *tx_node_id = osmo_pfcp_msg_node_id(tx); - if (tx_node_id) - *tx_node_id = *node_id; - } - return tx; -} - -static int osmo_pfcp_msg_destructor(struct osmo_pfcp_msg *m) -{ - OSMO_LOG_PFCP_MSG(m, LOGL_DEBUG, "discarding\n"); - if (m->ctx.session_use_count) - osmo_use_count_get_put(m->ctx.session_use_count, m->ctx.session_use_token, -1); - m->ctx.session_fi = NULL; - m->ctx.session_use_count = NULL; - m->ctx.session_use_token = NULL; - - if (m->ctx.peer_use_count) - osmo_use_count_get_put(m->ctx.peer_use_count, m->ctx.peer_use_token, -1); - m->ctx.peer_fi = NULL; - m->ctx.peer_use_count = NULL; - m->ctx.peer_use_token = NULL; - return 0; -} - -void osmo_pfcp_msg_free(struct osmo_pfcp_msg *m) -{ - if (!m) - return; - talloc_free(m); -} - -uint32_t osmo_pfcp_next_seq_nr(uint32_t *next_seq_nr_state) -{ - (*next_seq_nr_state)++; - (*next_seq_nr_state) &= 0xffffff; - /* Avoid seq == 0, so that it doesn't look like the value is missing. */ - if (!(*next_seq_nr_state)) - (*next_seq_nr_state)++; - return *next_seq_nr_state; -} - -uint64_t osmo_pfcp_next_seid(uint64_t *next_seid_state) -{ - (*next_seid_state)++; - /* Avoid SEID == 0, which is sent in Session Establishment Request before a remote SEID is known. */ - if (!*next_seid_state) - (*next_seid_state)++; - return *next_seid_state; -} - -int osmo_pfcp_ip_addrs_set(struct osmo_pfcp_ip_addrs *dst, const struct osmo_sockaddr *addr) -{ - switch (addr->u.sas.ss_family) { - case AF_INET: - dst->v4_present = true; - dst->v4 = *addr; - return 0; - case AF_INET6: - dst->v6_present = true; - dst->v6 = *addr; - return 0; - default: - return -ENOTSUP; - } -} - -/* If a osmo_fsm_inst placed in m->ctx deallocates before the osmo_pfcp_msg, call this function, to make sure to avoid - * use after free. Alternatively use m->ctx.*_use_count to make sure the FSM inst does not deallocate before the - * osmo_pfcp_msg is discarded from the resend queue. */ -void osmo_pfcp_msg_invalidate_ctx(struct osmo_pfcp_msg *m, struct osmo_fsm_inst *deleted_fi) -{ - if (m->ctx.session_fi == deleted_fi) { - m->ctx.session_fi = NULL; - m->ctx.session_use_count = NULL; - m->ctx.session_use_token = NULL; - } - if (m->ctx.peer_fi == deleted_fi) { - m->ctx.peer_fi = NULL; - m->ctx.peer_use_count = NULL; - m->ctx.peer_use_token = NULL; - } -} - -int osmo_pfcp_msg_to_str_buf(char *buf, size_t buflen, const struct osmo_pfcp_msg *m) -{ - struct osmo_strbuf sb = { .buf = buf, .len = buflen }; - OSMO_STRBUF_PRINTF(sb, "PFCPv%u %s hdr={seq=%u", m->h.version, osmo_pfcp_message_type_str(m->h.message_type), - m->h.sequence_nr); - if (m->h.priority_present) - OSMO_STRBUF_PRINTF(sb, " prio=%u", m->h.priority); - if (m->h.seid_present) - OSMO_STRBUF_PRINTF(sb, " SEID=0x%"PRIx64, m->h.seid); - OSMO_STRBUF_PRINTF(sb, "} ies={"); - OSMO_STRBUF_APPEND(sb, osmo_pfcp_ies_encode_to_str, &m->ies, m->h.message_type, osmo_pfcp_iei_strs); - OSMO_STRBUF_PRINTF(sb, " }"); - return sb.chars_needed; -} - -char *osmo_pfcp_msg_to_str_c(void *ctx, const struct osmo_pfcp_msg *m) -{ - OSMO_NAME_C_IMPL(ctx, 256, "ERROR", osmo_pfcp_msg_to_str_buf, m) -} diff --git a/src/libosmo-pfcp/pfcp_strs.c b/src/libosmo-pfcp/pfcp_strs.c deleted file mode 100644 index bd53aa0..0000000 --- a/src/libosmo-pfcp/pfcp_strs.c +++ /dev/null @@ -1,492 +0,0 @@ -/* - * (C) 2021-2022 by sysmocom - s.f.m.c. GmbH info@sysmocom.de - * All Rights Reserved. - * - * Author: Neels Janosch Hofmeyr nhofmeyr@sysmocom.de - * - * SPDX-License-Identifier: GPL-2.0+ - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. - * - */ - -#include <osmocom/pfcp/pfcp_strs.h> - -const struct value_string osmo_pfcp_message_type_strs[] = { - { OSMO_PFCP_MSGT_HEARTBEAT_REQ, "HEARTBEAT_REQ" }, - { OSMO_PFCP_MSGT_HEARTBEAT_RESP, "HEARTBEAT_RESP" }, - { OSMO_PFCP_MSGT_PFD_MGMT_REQ, "PFD_MGMT_REQ" }, - { OSMO_PFCP_MSGT_PFD_MGMT_RESP, "PFD_MGMT_RESP" }, - { OSMO_PFCP_MSGT_ASSOC_SETUP_REQ, "ASSOC_SETUP_REQ" }, - { OSMO_PFCP_MSGT_ASSOC_SETUP_RESP, "ASSOC_SETUP_RESP" }, - { OSMO_PFCP_MSGT_ASSOC_UPDATE_REQ, "ASSOC_UPDATE_REQ" }, - { OSMO_PFCP_MSGT_ASSOC_UPDATE_RESP, "ASSOC_UPDATE_RESP" }, - { OSMO_PFCP_MSGT_ASSOC_RELEASE_REQ, "ASSOC_RELEASE_REQ" }, - { OSMO_PFCP_MSGT_ASSOC_RELEASE_RESP, "ASSOC_RELEASE_RESP" }, - { OSMO_PFCP_MSGT_VERSION_NOT_SUPP_RESP, "VERSION_NOT_SUPP_RESP" }, - { OSMO_PFCP_MSGT_NODE_REPORT_REQ, "NODE_REPORT_REQ" }, - { OSMO_PFCP_MSGT_NODE_REPORT_RESP, "NODE_REPORT_RESP" }, - { OSMO_PFCP_MSGT_SESSION_SET_DEL_REQ, "SESSION_SET_DEL_REQ" }, - { OSMO_PFCP_MSGT_SESSION_SET_DEL_RESP, "SESSION_SET_DEL_RESP" }, - { OSMO_PFCP_MSGT_SESSION_EST_REQ, "SESSION_EST_REQ" }, - { OSMO_PFCP_MSGT_SESSION_EST_RESP, "SESSION_EST_RESP" }, - { OSMO_PFCP_MSGT_SESSION_MOD_REQ, "SESSION_MOD_REQ" }, - { OSMO_PFCP_MSGT_SESSION_MOD_RESP, "SESSION_MOD_RESP" }, - { OSMO_PFCP_MSGT_SESSION_DEL_REQ, "SESSION_DEL_REQ" }, - { OSMO_PFCP_MSGT_SESSION_DEL_RESP, "SESSION_DEL_RESP" }, - { OSMO_PFCP_MSGT_SESSION_REP_REQ, "SESSION_REP_REQ" }, - { OSMO_PFCP_MSGT_SESSION_REP_RESP, "SESSION_REP_RESP" }, - { 0 } -}; - -const struct value_string osmo_pfcp_iei_strs[] = { - { OSMO_PFCP_IEI_CREATE_PDR, "Create PDR" }, - { OSMO_PFCP_IEI_PDI, "PDI" }, - { OSMO_PFCP_IEI_CREATE_FAR, "Create FAR" }, - { OSMO_PFCP_IEI_FORW_PARAMS, "Forwarding Parameters" }, - { OSMO_PFCP_IEI_DUPL_PARAMS, "Duplicating Parameters" }, - { OSMO_PFCP_IEI_CREATE_URR, "Create URR" }, - { OSMO_PFCP_IEI_CREATE_QER, "Create QER" }, - { OSMO_PFCP_IEI_CREATED_PDR, "Created PDR" }, - { OSMO_PFCP_IEI_UPD_PDR, "Update PDR" }, - { OSMO_PFCP_IEI_UPD_FAR, "Update FAR" }, - { OSMO_PFCP_IEI_UPD_FORW_PARAMS, "Update Forwarding Parameters" }, - { OSMO_PFCP_IEI_UPD_BAR_SESS_REP_RESP, "Update BAR (PFCP Session Report Response)" }, - { OSMO_PFCP_IEI_UPD_URR, "Update URR" }, - { OSMO_PFCP_IEI_UPD_QER, "Update QER" }, - { OSMO_PFCP_IEI_REMOVE_PDR, "Remove PDR" }, - { OSMO_PFCP_IEI_REMOVE_FAR, "Remove FAR" }, - { OSMO_PFCP_IEI_REMOVE_URR, "Remove URR" }, - { OSMO_PFCP_IEI_REMOVE_QER, "Remove QER" }, - { OSMO_PFCP_IEI_CAUSE, "Cause" }, - { OSMO_PFCP_IEI_SOURCE_IFACE, "Source Interface" }, - { OSMO_PFCP_IEI_F_TEID, "F-TEID" }, - { OSMO_PFCP_IEI_NETWORK_INST, "Network Instance" }, - { OSMO_PFCP_IEI_SDF_FILTER, "SDF Filter" }, - { OSMO_PFCP_IEI_APPLICATION_ID, "Application ID" }, - { OSMO_PFCP_IEI_GATE_STATUS, "Gate Status" }, - { OSMO_PFCP_IEI_MBR, "MBR" }, - { OSMO_PFCP_IEI_GBR, "GBR" }, - { OSMO_PFCP_IEI_QER_CORRELATION_ID, "QER Correlation ID" }, - { OSMO_PFCP_IEI_PRECEDENCE, "Precedence" }, - { OSMO_PFCP_IEI_TRANSPORT_LEVEL_MARKING, "Transport Level Marking" }, - { OSMO_PFCP_IEI_VOLUME_THRESH, "Volume Threshold" }, - { OSMO_PFCP_IEI_TIME_THRESH, "Time Threshold" }, - { OSMO_PFCP_IEI_MONITORING_TIME, "Monitoring Time" }, - { OSMO_PFCP_IEI_SUBSEQUENT_VOLUME_THRESH, "Subsequent Volume Threshold" }, - { OSMO_PFCP_IEI_SUBSEQUENT_TIME_THRESH, "Subsequent Time Threshold" }, - { OSMO_PFCP_IEI_INACT_DETECTION_TIME, "Inactivity Detection Time" }, - { OSMO_PFCP_IEI_REPORTING_TRIGGERS, "Reporting Triggers" }, - { OSMO_PFCP_IEI_REDIRECT_INFO, "Redirect Information" }, - { OSMO_PFCP_IEI_REP_TYPE, "Report Type" }, - { OSMO_PFCP_IEI_OFFENDING_IE, "Offending IE" }, - { OSMO_PFCP_IEI_FORW_POLICY, "Forwarding Policy" }, - { OSMO_PFCP_IEI_DESTINATION_IFACE, "Destination Interface" }, - { OSMO_PFCP_IEI_UP_FUNCTION_FEATURES, "UP Function Features" }, - { OSMO_PFCP_IEI_APPLY_ACTION, "Apply Action" }, - { OSMO_PFCP_IEI_DL_DATA_SERVICE_INFO, "Downlink Data Service Information" }, - { OSMO_PFCP_IEI_DL_DATA_NOTIFICATION_DELAY, "Downlink Data Notification Delay" }, - { OSMO_PFCP_IEI_DL_BUFF_DURATION, "DL Buffering Duration" }, - { OSMO_PFCP_IEI_DL_BUFF_SUGGESTED_PACKET_COUNT, "DL Buffering Suggested Packet Count" }, - { OSMO_PFCP_IEI_PFCPSMREQ_FLAGS, "PFCPSMReq-Flags" }, - { OSMO_PFCP_IEI_PFCPSRRSP_FLAGS, "PFCPSRRsp-Flags" }, - { OSMO_PFCP_IEI_LOAD_CTRL_INFO, "Load Control Information" }, - { OSMO_PFCP_IEI_SEQUENCE_NUMBER, "Sequence Number" }, - { OSMO_PFCP_IEI_METRIC, "Metric" }, - { OSMO_PFCP_IEI_OVERLOAD_CTRL_INFO, "Overload Control Information" }, - { OSMO_PFCP_IEI_TIMER, "Timer" }, - { OSMO_PFCP_IEI_PDR_ID, "PDR ID" }, - { OSMO_PFCP_IEI_F_SEID, "F-SEID" }, - { OSMO_PFCP_IEI_APPLICATION_IDS_PFDS, "Application ID's PFDs" }, - { OSMO_PFCP_IEI_PFD_CONTEXT, "PFD context" }, - { OSMO_PFCP_IEI_NODE_ID, "Node ID" }, - { OSMO_PFCP_IEI_PFD_CONTENTS, "PFD contents" }, - { OSMO_PFCP_IEI_MEAS_METHOD, "Measurement Method" }, - { OSMO_PFCP_IEI_USAGE_REP_TRIGGER, "Usage Report Trigger" }, - { OSMO_PFCP_IEI_MEAS_PERIOD, "Measurement Period" }, - { OSMO_PFCP_IEI_FQ_CSID, "FQ-CSID" }, - { OSMO_PFCP_IEI_VOLUME_MEAS, "Volume Measurement" }, - { OSMO_PFCP_IEI_DURATION_MEAS, "Duration Measurement" }, - { OSMO_PFCP_IEI_APPLICATION_DETECTION_INFO, "Application Detection Information" }, - { OSMO_PFCP_IEI_TIME_OF_FIRST_PACKET, "Time of First Packet" }, - { OSMO_PFCP_IEI_TIME_OF_LAST_PACKET, "Time of Last Packet" }, - { OSMO_PFCP_IEI_QUOTA_HOLDING_TIME, "Quota Holding Time" }, - { OSMO_PFCP_IEI_DROPPED_DL_TRAFFIC_THRESH, "Dropped DL Traffic Threshold" }, - { OSMO_PFCP_IEI_VOLUME_QUOTA, "Volume Quota" }, - { OSMO_PFCP_IEI_TIME_QUOTA, "Time Quota" }, - { OSMO_PFCP_IEI_START_TIME, "Start Time" }, - { OSMO_PFCP_IEI_END_TIME, "End Time" }, - { OSMO_PFCP_IEI_QUERY_URR, "Query URR" }, - { OSMO_PFCP_IEI_USAGE_REP_SESS_MOD_RESP, "Usage Report (Session Modification Response)" }, - { OSMO_PFCP_IEI_USAGE_REP_SESS_DEL_RESP, "Usage Report (Session Deletion Response)" }, - { OSMO_PFCP_IEI_USAGE_REP_SESS_REP_REQ, "Usage Report (Session Report Request)" }, - { OSMO_PFCP_IEI_URR_ID, "URR ID" }, - { OSMO_PFCP_IEI_LINKED_URR_ID, "Linked URR ID" }, - { OSMO_PFCP_IEI_DL_DATA_REP, "Downlink Data Report" }, - { OSMO_PFCP_IEI_OUTER_HEADER_CREATION, "Outer Header Creation" }, - { OSMO_PFCP_IEI_CREATE_BAR, "Create BAR" }, - { OSMO_PFCP_IEI_UPD_BAR_SESS_MOD_REQ, "Update BAR (Session Modification Request)" }, - { OSMO_PFCP_IEI_REMOVE_BAR, "Remove BAR" }, - { OSMO_PFCP_IEI_BAR_ID, "BAR ID" }, - { OSMO_PFCP_IEI_CP_FUNCTION_FEATURES, "CP Function Features" }, - { OSMO_PFCP_IEI_USAGE_INFO, "Usage Information" }, - { OSMO_PFCP_IEI_APPLICATION_INST_ID, "Application Instance ID" }, - { OSMO_PFCP_IEI_FLOW_INFO, "Flow Information" }, - { OSMO_PFCP_IEI_UE_IP_ADDRESS, "UE IP Address" }, - { OSMO_PFCP_IEI_PACKET_RATE, "Packet Rate" }, - { OSMO_PFCP_IEI_OUTER_HEADER_REMOVAL, "Outer Header Removal" }, - { OSMO_PFCP_IEI_RECOVERY_TIME_STAMP, "Recovery Time Stamp" }, - { OSMO_PFCP_IEI_DL_FLOW_LEVEL_MARKING, "DL Flow Level Marking" }, - { OSMO_PFCP_IEI_HEADER_ENRICHMENT, "Header Enrichment" }, - { OSMO_PFCP_IEI_ERROR_IND_REP, "Error Indication Report" }, - { OSMO_PFCP_IEI_MEAS_INFO, "Measurement Information" }, - { OSMO_PFCP_IEI_NODE_REP_TYPE, "Node Report Type" }, - { OSMO_PFCP_IEI_USER_PLANE_PATH_FAILURE_REP, "User Plane Path Failure Report" }, - { OSMO_PFCP_IEI_REMOTE_GTP_U_PEER, "Remote GTP-U Peer" }, - { OSMO_PFCP_IEI_UR_SEQN, "UR-SEQN" }, - { OSMO_PFCP_IEI_UPD_DUPL_PARAMS, "Update Duplicating Parameters" }, - { OSMO_PFCP_IEI_ACTIVATE_PREDEFINED_RULES, "Activate Predefined Rules" }, - { OSMO_PFCP_IEI_DEACTIVATE_PREDEFINED_RULES, "Deactivate Predefined Rules" }, - { OSMO_PFCP_IEI_FAR_ID, "FAR ID" }, - { OSMO_PFCP_IEI_QER_ID, "QER ID" }, - { OSMO_PFCP_IEI_OCI_FLAGS, "OCI Flags" }, - { OSMO_PFCP_IEI_PFCP_ASSOC_RELEASE_REQ, "PFCP Association Release Request" }, - { OSMO_PFCP_IEI_GRACEFUL_RELEASE_PERIOD, "Graceful Release Period" }, - { OSMO_PFCP_IEI_PDN_TYPE, "PDN Type" }, - { OSMO_PFCP_IEI_FAILED_RULE_ID, "Failed Rule ID" }, - { OSMO_PFCP_IEI_TIME_QUOTA_MECHANISM, "Time Quota Mechanism" }, - { OSMO_PFCP_IEI_RESERVED, "Reserved" }, - { OSMO_PFCP_IEI_USER_PLANE_INACT_TIMER, "User Plane Inactivity Timer" }, - { OSMO_PFCP_IEI_AGGREGATED_URRS, "Aggregated URRs" }, - { OSMO_PFCP_IEI_MULTIPLIER, "Multiplier" }, - { OSMO_PFCP_IEI_AGGREGATED_URR_ID, "Aggregated URR ID" }, - { OSMO_PFCP_IEI_SUBSEQUENT_VOLUME_QUOTA, "Subsequent Volume Quota" }, - { OSMO_PFCP_IEI_SUBSEQUENT_TIME_QUOTA, "Subsequent Time Quota" }, - { OSMO_PFCP_IEI_RQI, "RQI" }, - { OSMO_PFCP_IEI_QFI, "QFI" }, - { OSMO_PFCP_IEI_QUERY_URR_REFERENCE, "Query URR Reference" }, - { OSMO_PFCP_IEI_ADDITIONAL_USAGE_REPS_INFO, "Additional Usage Reports Information" }, - { OSMO_PFCP_IEI_CREATE_TRAFFIC_ENDPOINT, "Create Traffic Endpoint" }, - { OSMO_PFCP_IEI_CREATED_TRAFFIC_ENDPOINT, "Created Traffic Endpoint" }, - { OSMO_PFCP_IEI_UPD_TRAFFIC_ENDPOINT, "Update Traffic Endpoint" }, - { OSMO_PFCP_IEI_REMOVE_TRAFFIC_ENDPOINT, "Remove Traffic Endpoint" }, - { OSMO_PFCP_IEI_TRAFFIC_ENDPOINT_ID, "Traffic Endpoint ID" }, - { OSMO_PFCP_IEI_ETHERNET_PACKET_FILTER, "Ethernet Packet Filter" }, - { OSMO_PFCP_IEI_MAC_ADDRESS, "MAC address" }, - { OSMO_PFCP_IEI_C_TAG, "C-TAG" }, - { OSMO_PFCP_IEI_S_TAG, "S-TAG" }, - { OSMO_PFCP_IEI_ETHERTYPE, "Ethertype" }, - { OSMO_PFCP_IEI_PROXYING, "Proxying" }, - { OSMO_PFCP_IEI_ETHERNET_FILTER_ID, "Ethernet Filter ID" }, - { OSMO_PFCP_IEI_ETHERNET_FILTER_PROPERTIES, "Ethernet Filter Properties" }, - { OSMO_PFCP_IEI_SUGGESTED_BUFF_PACKETS_COUNT, "Suggested Buffering Packets Count" }, - { OSMO_PFCP_IEI_USER_ID, "User ID" }, - { OSMO_PFCP_IEI_ETHERNET_PDU_SESS_INFO, "Ethernet PDU Session Information" }, - { OSMO_PFCP_IEI_ETHERNET_TRAFFIC_INFO, "Ethernet Traffic Information" }, - { OSMO_PFCP_IEI_MAC_ADDRS_DETECTED, "MAC Addresses Detected" }, - { OSMO_PFCP_IEI_MAC_ADDRS_REMOVED, "MAC Addresses Removed" }, - { OSMO_PFCP_IEI_ETHERNET_INACT_TIMER, "Ethernet Inactivity Timer" }, - { OSMO_PFCP_IEI_ADDITIONAL_MONITORING_TIME, "Additional Monitoring Time" }, - { OSMO_PFCP_IEI_EVENT_QUOTA, "Event Quota" }, - { OSMO_PFCP_IEI_EVENT_THRESH, "Event Threshold" }, - { OSMO_PFCP_IEI_SUBSEQUENT_EVENT_QUOTA, "Subsequent Event Quota" }, - { OSMO_PFCP_IEI_SUBSEQUENT_EVENT_THRESH, "Subsequent Event Threshold" }, - { OSMO_PFCP_IEI_TRACE_INFO, "Trace Information" }, - { OSMO_PFCP_IEI_FRAMED_ROUTE, "Framed-Route" }, - { OSMO_PFCP_IEI_FRAMED_ROUTING, "Framed-Routing" }, - { OSMO_PFCP_IEI_FRAMED_IPV6_ROUTE, "Framed-IPv6-Route" }, - { OSMO_PFCP_IEI_TIME_STAMP, "Time Stamp" }, - { OSMO_PFCP_IEI_AVERAGING_WINDOW, "Averaging Window" }, - { OSMO_PFCP_IEI_PAGING_POLICY_INDICATOR, "Paging Policy Indicator" }, - { OSMO_PFCP_IEI_APN_DNN, "APN/DNN" }, - { OSMO_PFCP_IEI_3GPP_IFACE_TYPE, "3GPP Interface Type" }, - { OSMO_PFCP_IEI_PFCPSRREQ_FLAGS, "PFCPSRReq-Flags" }, - { OSMO_PFCP_IEI_PFCPAUREQ_FLAGS, "PFCPAUReq-Flags" }, - { OSMO_PFCP_IEI_ACTIVATION_TIME, "Activation Time" }, - { OSMO_PFCP_IEI_DEACTIVATION_TIME, "Deactivation Time" }, - { OSMO_PFCP_IEI_CREATE_MAR, "Create MAR" }, - { OSMO_PFCP_IEI_3GPP_ACCESS_FORW_ACTION_INFO, "3GPP Access Forwarding Action Information" }, - { OSMO_PFCP_IEI_NON_3GPP_ACCESS_FORW_ACTION_INFO, "Non-3GPP Access Forwarding Action Information" }, - { OSMO_PFCP_IEI_REMOVE_MAR, "Remove MAR" }, - { OSMO_PFCP_IEI_UPD_MAR, "Update MAR" }, - { OSMO_PFCP_IEI_MAR_ID, "MAR ID" }, - { OSMO_PFCP_IEI_STEERING_FUNCTIONALITY, "Steering Functionality" }, - { OSMO_PFCP_IEI_STEERING_MODE, "Steering Mode" }, - { OSMO_PFCP_IEI_WEIGHT, "Weight" }, - { OSMO_PFCP_IEI_PRIORITY, "Priority" }, - { OSMO_PFCP_IEI_UPD_3GPP_ACCESS_FORW_ACTION_INFO, "Update 3GPP Access Forwarding Action Information" }, - { OSMO_PFCP_IEI_UPD_NON_3GPP_ACCESS_FORW_ACTION_INFO, "Update Non 3GPP Access Forwarding Action Information" }, - { OSMO_PFCP_IEI_UE_IP_ADDRESS_POOL_IDENTITY, "UE IP address Pool Identity" }, - { OSMO_PFCP_IEI_ALTERNATIVE_SMF_IP_ADDRESS, "Alternative SMF IP Address" }, - { OSMO_PFCP_IEI_PACKET_REPLICATION_AND_DETECTION_CARRY_ON_INFO, "Packet Replication and Detection Carry-On Information" }, - { OSMO_PFCP_IEI_SMF_SET_ID, "SMF Set ID" }, - { OSMO_PFCP_IEI_QUOTA_VALIDITY_TIME, "Quota Validity Time" }, - { OSMO_PFCP_IEI_NUMBER_OF_REPS, "Number of Reports" }, - { OSMO_PFCP_IEI_PFCP_SESS_RETENTION_INFO_IN_ASSOC_SETUP_REQ, "PFCP Session Retention Information (within PFCP Association Setup Request)" }, - { OSMO_PFCP_IEI_PFCPASRSP_FLAGS, "PFCPASRsp-Flags" }, - { OSMO_PFCP_IEI_CP_ENTITY_IP_ADDRESS, "CP PFCP Entity IP Address" }, - { OSMO_PFCP_IEI_PFCPSEREQ_FLAGS, "PFCPSEReq-Flags" }, - { OSMO_PFCP_IEI_USER_PLANE_PATH_RECOVERY_REP, "User Plane Path Recovery Report" }, - { OSMO_PFCP_IEI_IP_MULTICAST_ADDR_INFO_IN_SESS_EST_REQ, "IP Multicast Addressing Info within PFCP Session Establishment Request" }, - { OSMO_PFCP_IEI_JOIN_IP_MULTICAST_INFO_IE_IN_USAGE_REP, "Join IP Multicast Information IE within Usage Report" }, - { OSMO_PFCP_IEI_LEAVE_IP_MULTICAST_INFO_IE_IN_USAGE_REP, "Leave IP Multicast Information IE within Usage Report" }, - { OSMO_PFCP_IEI_IP_MULTICAST_ADDRESS, "IP Multicast Address" }, - { OSMO_PFCP_IEI_SOURCE_IP_ADDRESS, "Source IP Address" }, - { OSMO_PFCP_IEI_PACKET_RATE_STATUS, "Packet Rate Status" }, - { OSMO_PFCP_IEI_CREATE_BRIDGE_INFO_FOR_TSC, "Create Bridge Info for TSC" }, - { OSMO_PFCP_IEI_CREATED_BRIDGE_INFO_FOR_TSC, "Created Bridge Info for TSC" }, - { OSMO_PFCP_IEI_DS_TT_PORT_NUMBER, "DS-TT Port Number" }, - { OSMO_PFCP_IEI_NW_TT_PORT_NUMBER, "NW-TT Port Number" }, - { OSMO_PFCP_IEI_TSN_BRIDGE_ID, "TSN Bridge ID" }, - { OSMO_PFCP_IEI_TSC_MGMT_INFO_IE_IN_SESS_MOD_REQ, "TSC Management Information IE within PFCP Session Modification Request" }, - { OSMO_PFCP_IEI_TSC_MGMT_INFO_IE_IN_SESS_MOD_RESP, "TSC Management Information IE within PFCP Session Modification Response" }, - { OSMO_PFCP_IEI_TSC_MGMT_INFO_IE_IN_SESS_REP_REQ, "TSC Management Information IE within PFCP Session Report Request" }, - { OSMO_PFCP_IEI_PORT_MGMT_INFO_CONTAINER, "Port Management Information Container" }, - { OSMO_PFCP_IEI_CLOCK_DRIFT_CTRL_INFO, "Clock Drift Control Information" }, - { OSMO_PFCP_IEI_REQUESTED_CLOCK_DRIFT_INFO, "Requested Clock Drift Information" }, - { OSMO_PFCP_IEI_CLOCK_DRIFT_REP, "Clock Drift Report" }, - { OSMO_PFCP_IEI_TSN_TIME_DOMAIN_NUMBER, "TSN Time Domain Number" }, - { OSMO_PFCP_IEI_TIME_OFFSET_THRESH, "Time Offset Threshold" }, - { OSMO_PFCP_IEI_CUMULATIVE_RATERATIO_THRESH, "Cumulative rateRatio Threshold" }, - { OSMO_PFCP_IEI_TIME_OFFSET_MEAS, "Time Offset Measurement" }, - { OSMO_PFCP_IEI_CUMULATIVE_RATERATIO_MEAS, "Cumulative rateRatio Measurement" }, - { OSMO_PFCP_IEI_REMOVE_SRR, "Remove SRR" }, - { OSMO_PFCP_IEI_CREATE_SRR, "Create SRR" }, - { OSMO_PFCP_IEI_UPD_SRR, "Update SRR" }, - { OSMO_PFCP_IEI_SESS_REP, "Session Report" }, - { OSMO_PFCP_IEI_SRR_ID, "SRR ID" }, - { OSMO_PFCP_IEI_ACCESS_AVAIL_CTRL_INFO, "Access Availability Control Information" }, - { OSMO_PFCP_IEI_REQUESTED_ACCESS_AVAIL_INFO, "Requested Access Availability Information" }, - { OSMO_PFCP_IEI_ACCESS_AVAIL_REP, "Access Availability Report" }, - { OSMO_PFCP_IEI_ACCESS_AVAIL_INFO, "Access Availability Information" }, - { OSMO_PFCP_IEI_PROVIDE_ATSSS_CTRL_INFO, "Provide ATSSS Control Information" }, - { OSMO_PFCP_IEI_ATSSS_CTRL_PARAMS, "ATSSS Control Parameters" }, - { OSMO_PFCP_IEI_MPTCP_CTRL_INFO, "MPTCP Control Information" }, - { OSMO_PFCP_IEI_ATSSS_LL_CTRL_INFO, "ATSSS-LL Control Information" }, - { OSMO_PFCP_IEI_PMF_CTRL_INFO, "PMF Control Information" }, - { OSMO_PFCP_IEI_MPTCP_PARAMS, "MPTCP Parameters" }, - { OSMO_PFCP_IEI_ATSSS_LL_PARAMS, "ATSSS-LL Parameters" }, - { OSMO_PFCP_IEI_PMF_PARAMS, "PMF Parameters" }, - { OSMO_PFCP_IEI_MPTCP_ADDRESS_INFO, "MPTCP Address Information" }, - { OSMO_PFCP_IEI_UE_LINK_SPECIFIC_IP_ADDRESS, "UE Link-Specific IP Address" }, - { OSMO_PFCP_IEI_PMF_ADDRESS_INFO, "PMF Address Information" }, - { OSMO_PFCP_IEI_ATSSS_LL_INFO, "ATSSS-LL Information" }, - { OSMO_PFCP_IEI_DATA_NETWORK_ACCESS_IDENTIFIER, "Data Network Access Identifier" }, - { OSMO_PFCP_IEI_UE_IP_ADDRESS_POOL_INFO, "UE IP address Pool Information" }, - { OSMO_PFCP_IEI_AVERAGE_PACKET_DELAY, "Average Packet Delay" }, - { OSMO_PFCP_IEI_MIN_PACKET_DELAY, "Minimum Packet Delay" }, - { OSMO_PFCP_IEI_MAX_PACKET_DELAY, "Maximum Packet Delay" }, - { OSMO_PFCP_IEI_QOS_REP_TRIGGER, "QoS Report Trigger" }, - { OSMO_PFCP_IEI_GTP_U_PATH_QOS_CTRL_INFO, "GTP-U Path QoS Control Information" }, - { OSMO_PFCP_IEI_GTP_U_PATH_QOS_REP_NODE_REP_REQ, "GTP-U Path QoS Report (PFCP Node Report Request)" }, - { OSMO_PFCP_IEI_QOS_INFO_IN_GTP_U_PATH_QOS_REP, "QoS Information in GTP-U Path QoS Report" }, - { OSMO_PFCP_IEI_GTP_U_PATH_IFACE_TYPE, "GTP-U Path Interface Type" }, - { OSMO_PFCP_IEI_QOS_MONITORING_PER_QOS_FLOW_CTRL_INFO, "QoS Monitoring per QoS flow Control Information" }, - { OSMO_PFCP_IEI_REQUESTED_QOS_MONITORING, "Requested QoS Monitoring" }, - { OSMO_PFCP_IEI_REPORTING_FREQUENCY, "Reporting Frequency" }, - { OSMO_PFCP_IEI_PACKET_DELAY_THRESHOLDS, "Packet Delay Thresholds" }, - { OSMO_PFCP_IEI_MIN_WAIT_TIME, "Minimum Wait Time" }, - { OSMO_PFCP_IEI_QOS_MONITORING_REP, "QoS Monitoring Report" }, - { OSMO_PFCP_IEI_QOS_MONITORING_MEAS, "QoS Monitoring Measurement" }, - { OSMO_PFCP_IEI_MT_EDT_CTRL_INFO, "MT-EDT Control Information" }, - { OSMO_PFCP_IEI_DL_DATA_PACKETS_SIZE, "DL Data Packets Size" }, - { OSMO_PFCP_IEI_QER_CTRL_INDICATIONS, "QER Control Indications" }, - { OSMO_PFCP_IEI_PACKET_RATE_STATUS_REP, "Packet Rate Status Report" }, - { OSMO_PFCP_IEI_NF_INST_ID, "NF Instance ID" }, - { OSMO_PFCP_IEI_ETHERNET_CONTEXT_INFO, "Ethernet Context Information" }, - { OSMO_PFCP_IEI_REDUNDANT_TRANSMISSION_PARAMS, "Redundant Transmission Parameters" }, - { OSMO_PFCP_IEI_UPDATED_PDR, "Updated PDR" }, - { OSMO_PFCP_IEI_S_NSSAI, "S-NSSAI" }, - { OSMO_PFCP_IEI_IP_VERSION, "IP version" }, - { OSMO_PFCP_IEI_PFCPASREQ_FLAGS, "PFCPASReq-Flags" }, - { OSMO_PFCP_IEI_DATA_STATUS, "Data Status" }, - { OSMO_PFCP_IEI_PROVIDE_RDS_CONF_INFO, "Provide RDS configuration information" }, - { OSMO_PFCP_IEI_RDS_CONF_INFO, "RDS configuration information" }, - { OSMO_PFCP_IEI_QUERY_PACKET_RATE_STATUS_IE_IN_SESS_MOD_REQ, "Query Packet Rate Status IE within PFCP Session Modification Request" }, - { OSMO_PFCP_IEI_PACKET_RATE_STATUS_REP_IE_IN_SESS_MOD_RESP, "Packet Rate Status Report IE within PFCP Session Modification Response" }, - { OSMO_PFCP_IEI_MPTCP_APPLICABLE_IND, "MPTCP Applicable Indication" }, - { OSMO_PFCP_IEI_BRIDGE_MGMT_INFO_CONTAINER, "Bridge Management Information Container" }, - { OSMO_PFCP_IEI_UE_IP_ADDRESS_USAGE_INFO, "UE IP Address Usage Information" }, - { OSMO_PFCP_IEI_NUMBER_OF_UE_IP_ADDRS, "Number of UE IP Addresses" }, - { OSMO_PFCP_IEI_VALIDITY_TIMER, "Validity Timer" }, - { OSMO_PFCP_IEI_REDUNDANT_TRANSMISSION_FORW_PARAMS, "Redundant Transmission Forwarding Parameters" }, - { OSMO_PFCP_IEI_TRANSPORT_DELAY_REPORTING, "Transport Delay Reporting" }, - { 0 } -}; - -const struct value_string osmo_pfcp_cause_strs[] = { - { OSMO_PFCP_CAUSE_RESERVED, "0" }, - { OSMO_PFCP_CAUSE_REQUEST_ACCEPTED, "Request accepted (success)" }, - { OSMO_PFCP_CAUSE_MORE_USAGE_REPORT_TO_SEND, "More Usage Report to send" }, - { OSMO_PFCP_CAUSE_REQUEST_REJECTED, "Request rejected (reason not specified)" }, - { OSMO_PFCP_CAUSE_SESSION_CTX_NOT_FOUND, "Session context not found" }, - { OSMO_PFCP_CAUSE_MANDATORY_IE_MISSING, "Mandatory IE missing" }, - { OSMO_PFCP_CAUSE_CONDITIONAL_IE_MISSING, "Conditional IE missing" }, - { OSMO_PFCP_CAUSE_INVALID_LENGTH, "Invalid length" }, - { OSMO_PFCP_CAUSE_MANDATORY_IE_INCORRECT, "Mandatory IE incorrect" }, - { OSMO_PFCP_CAUSE_INVALID_FORW_POLICY, "Invalid Forwarding Policy" }, - { OSMO_PFCP_CAUSE_INVALID_F_TEID_ALLOC_OPTION, "Invalid F-TEID allocation option" }, - { OSMO_PFCP_CAUSE_NO_ESTABLISHED_PFCP_ASSOC, "No established PFCP Association" }, - { OSMO_PFCP_CAUSE_RULE_CREATION_MOD_FAILURE, "Rule creation/modification Failure" }, - { OSMO_PFCP_CAUSE_PFCP_ENTITY_IN_CONGESTION, "PFCP entity in congestion" }, - { OSMO_PFCP_CAUSE_NO_RESOURCES_AVAILABLE, "No resources available" }, - { OSMO_PFCP_CAUSE_SERVICE_NOT_SUPPORTED, "Service not supported" }, - { OSMO_PFCP_CAUSE_SYSTEM_FAILURE, "System failure" }, - { OSMO_PFCP_CAUSE_REDIRECTION_REQUESTED, "Redirection Requested" }, - { OSMO_PFCP_CAUSE_ALL_DYNAMIC_ADDRESSES_ARE_OCCUPIED, "All dynamic addresses are occupied" }, - { 0 } -}; - -const struct value_string osmo_pfcp_up_feature_strs[] = { - { OSMO_PFCP_UP_FEAT_BUCP, "BUCP" }, - { OSMO_PFCP_UP_FEAT_DDND, "DDND" }, - { OSMO_PFCP_UP_FEAT_DLBD, "DLBD" }, - { OSMO_PFCP_UP_FEAT_TRST, "TRST" }, - { OSMO_PFCP_UP_FEAT_FTUP, "FTUP" }, - { OSMO_PFCP_UP_FEAT_PFDM, "PFDM" }, - { OSMO_PFCP_UP_FEAT_HEEU, "HEEU" }, - { OSMO_PFCP_UP_FEAT_TREU, "TREU" }, - { OSMO_PFCP_UP_FEAT_EMPU, "EMPU" }, - { OSMO_PFCP_UP_FEAT_PDIU, "PDIU" }, - { OSMO_PFCP_UP_FEAT_UDBC, "UDBC" }, - { OSMO_PFCP_UP_FEAT_QUOAC, "QUOAC" }, - { OSMO_PFCP_UP_FEAT_TRACE, "TRACE" }, - { OSMO_PFCP_UP_FEAT_FRRT, "FRRT" }, - { OSMO_PFCP_UP_FEAT_PFDE, "PFDE" }, - { OSMO_PFCP_UP_FEAT_EPFAR, "EPFAR" }, - { OSMO_PFCP_UP_FEAT_DPDRA, "DPDRA" }, - { OSMO_PFCP_UP_FEAT_ADPDP, "ADPDP" }, - { OSMO_PFCP_UP_FEAT_UEIP, "UEIP" }, - { OSMO_PFCP_UP_FEAT_SSET, "SSET" }, - { OSMO_PFCP_UP_FEAT_MNOP, "MNOP" }, - { OSMO_PFCP_UP_FEAT_MTE, "MTE" }, - { OSMO_PFCP_UP_FEAT_BUNDL, "BUNDL" }, - { OSMO_PFCP_UP_FEAT_GCOM, "GCOM" }, - { OSMO_PFCP_UP_FEAT_MPAS, "MPAS" }, - { OSMO_PFCP_UP_FEAT_RTTL, "RTTL" }, - { OSMO_PFCP_UP_FEAT_VTIME, "VTIME" }, - { OSMO_PFCP_UP_FEAT_NORP, "NORP" }, - { OSMO_PFCP_UP_FEAT_IP6PL, "IP6PL" }, - { OSMO_PFCP_UP_FEAT_TSCU, "TSCU" }, - { OSMO_PFCP_UP_FEAT_MPTCP, "MPTCP" }, - { OSMO_PFCP_UP_FEAT_ATSSSLL, "ATSSSLL" }, - { OSMO_PFCP_UP_FEAT_QFQM, "QFQM" }, - { OSMO_PFCP_UP_FEAT_GPQM, "GPQM" }, - { OSMO_PFCP_UP_FEAT_MTEDT, "MTEDT" }, - { OSMO_PFCP_UP_FEAT_CIOT, "CIOT" }, - { OSMO_PFCP_UP_FEAT_ETHAR, "ETHAR" }, - { OSMO_PFCP_UP_FEAT_DDDS, "DDDS" }, - { OSMO_PFCP_UP_FEAT_RDS, "RDS" }, - { OSMO_PFCP_UP_FEAT_RTTWP, "RTTWP" }, - {} -}; - - -const struct value_string osmo_pfcp_cp_feature_strs[] = { - { OSMO_PFCP_CP_FEAT_LOAD, "LOAD" }, - { OSMO_PFCP_CP_FEAT_OVRL, "OVRL" }, - { OSMO_PFCP_CP_FEAT_EPFAR, "EPFAR" }, - { OSMO_PFCP_CP_FEAT_SSET, "SSET" }, - { OSMO_PFCP_CP_FEAT_BUNDL, "BUNDL" }, - { OSMO_PFCP_CP_FEAT_MPAS, "MPAS" }, - { OSMO_PFCP_CP_FEAT_ARDR, "ARDR" }, - { OSMO_PFCP_CP_FEAT_UIAUR, "UIAUR" }, - {} -}; - -const struct value_string osmo_pfcp_apply_action_strs[] = { - { OSMO_PFCP_APPLY_ACTION_DROP, "DROP" }, - { OSMO_PFCP_APPLY_ACTION_FORW, "FORW" }, - { OSMO_PFCP_APPLY_ACTION_BUFF, "BUFF" }, - { OSMO_PFCP_APPLY_ACTION_NOCP, "NOCP" }, - { OSMO_PFCP_APPLY_ACTION_DUPL, "DUPL" }, - { OSMO_PFCP_APPLY_ACTION_IPMA, "IPMA" }, - { OSMO_PFCP_APPLY_ACTION_IPMD, "IPMD" }, - { OSMO_PFCP_APPLY_ACTION_DFRT, "DFRT" }, - { OSMO_PFCP_APPLY_ACTION_EDRT, "EDRT" }, - { OSMO_PFCP_APPLY_ACTION_BDPN, "BDPN" }, - { OSMO_PFCP_APPLY_ACTION_DDPN, "DDPN" }, - {} -}; - -const struct value_string osmo_pfcp_outer_header_creation_strs[] = { - { OSMO_PFCP_OUTER_HEADER_CREATION_GTP_U_UDP_IPV4, "GTP_U_UDP_IPV4" }, - { OSMO_PFCP_OUTER_HEADER_CREATION_GTP_U_UDP_IPV6, "GTP_U_UDP_IPV6" }, - { OSMO_PFCP_OUTER_HEADER_CREATION_UDP_IPV4, "UDP_IPV4" }, - { OSMO_PFCP_OUTER_HEADER_CREATION_UDP_IPV6, "UDP_IPV6" }, - { OSMO_PFCP_OUTER_HEADER_CREATION_IPV4, "IPV4" }, - { OSMO_PFCP_OUTER_HEADER_CREATION_IPV6, "IPV6" }, - { OSMO_PFCP_OUTER_HEADER_CREATION_C_TAG, "C_TAG" }, - { OSMO_PFCP_OUTER_HEADER_CREATION_S_TAG, "S_TAG" }, - { OSMO_PFCP_OUTER_HEADER_CREATION_N19_INDICATION, "N19_INDICATION" }, - { OSMO_PFCP_OUTER_HEADER_CREATION_N6_INDICATION, "N6_INDICATION" }, - {} -}; - -const struct value_string osmo_pfcp_outer_header_removal_desc_strs[] = { - { OSMO_PFCP_OUTER_HEADER_REMOVAL_GTP_U_UDP_IPV4, "GTP_U_UDP_IPV4" }, - { OSMO_PFCP_OUTER_HEADER_REMOVAL_GTP_U_UDP_IPV6, "GTP_U_UDP_IPV6" }, - { OSMO_PFCP_OUTER_HEADER_REMOVAL_UDP_IPV4, "UDP_IPV4" }, - { OSMO_PFCP_OUTER_HEADER_REMOVAL_UDP_IPV6, "UDP_IPV6" }, - { OSMO_PFCP_OUTER_HEADER_REMOVAL_IPV4, "IPV4" }, - { OSMO_PFCP_OUTER_HEADER_REMOVAL_IPV6, "IPV6" }, - { OSMO_PFCP_OUTER_HEADER_REMOVAL_GTP_U_UDP_IP, "GTP_U_UDP_IP" }, - { OSMO_PFCP_OUTER_HEADER_REMOVAL_VLAN_S_TAG, "VLAN_S_TAG" }, - { OSMO_PFCP_OUTER_HEADER_REMOVAL_S_TAG_AND_C_TAG, "S_TAG_AND_C_TAG" }, - {} -}; - -const struct value_string osmo_pfcp_source_iface_strs[] = { - { OSMO_PFCP_SOURCE_IFACE_ACCESS, "Access" }, - { OSMO_PFCP_SOURCE_IFACE_CORE, "Core" }, - { OSMO_PFCP_SOURCE_IFACE_SGI_LAN_N6_LAN, "SGi-LAN/N6-LAN" }, - { OSMO_PFCP_SOURCE_IFACE_CP_FUNCTION, "CP-function" }, - { OSMO_PFCP_SOURCE_IFACE_5G_VN_INTERNAL, "5G-VN-Internal" }, - {} -}; - -const struct value_string osmo_pfcp_dest_iface_strs[] = { - { OSMO_PFCP_DEST_IFACE_ACCESS, "Access" }, - { OSMO_PFCP_DEST_IFACE_CORE, "Core" }, - { OSMO_PFCP_DEST_IFACE_SGI_LAN_N6_LAN, "SGi-LAN/N6-LAN" }, - { OSMO_PFCP_DEST_IFACE_CP_FUNCTION, "CP-function" }, - { OSMO_PFCP_DEST_IFACE_LI_FUNCTION, "LI-function" }, - { OSMO_PFCP_DEST_IFACE_5G_VN_INTERNAL, "5G-VN-Internal" }, - {} -}; - -const struct value_string osmo_pfcp_3gpp_iface_type_strs[] = { - { OSMO_PFCP_3GPP_IFACE_TYPE_S1_U, "S1_U" }, - { OSMO_PFCP_3GPP_IFACE_TYPE_S5_S8_U, "S5_S8_U" }, - { OSMO_PFCP_3GPP_IFACE_TYPE_S4_U, "S4_U" }, - { OSMO_PFCP_3GPP_IFACE_TYPE_S11_U, "S11_U" }, - { OSMO_PFCP_3GPP_IFACE_TYPE_S12_U, "S12_U" }, - { OSMO_PFCP_3GPP_IFACE_TYPE_GN_GP_U, "GN_GP_U" }, - { OSMO_PFCP_3GPP_IFACE_TYPE_S2A_U, "S2A_U" }, - { OSMO_PFCP_3GPP_IFACE_TYPE_S2B_U, "S2B_U" }, - { OSMO_PFCP_3GPP_IFACE_TYPE_ENODEB_GTP_U_INTERFACE_FOR_DL_DATA_FORWARDING, "ENODEB_GTP_U_INTERFACE_FOR_DL_DATA_FORWARDING" }, - { OSMO_PFCP_3GPP_IFACE_TYPE_ENODEB_GTP_U_INTERFACE_FOR_UL_DATA_FORWARDING, "ENODEB_GTP_U_INTERFACE_FOR_UL_DATA_FORWARDING" }, - { OSMO_PFCP_3GPP_IFACE_TYPE_SGW_UPF_GTP_U_INTERFACE_FOR_DL_DATA_FORWARDING, "SGW_UPF_GTP_U_INTERFACE_FOR_DL_DATA_FORWARDING" }, - { OSMO_PFCP_3GPP_IFACE_TYPE_N3_3GPP_ACCESS, "N3_3GPP_ACCESS" }, - { OSMO_PFCP_3GPP_IFACE_TYPE_N3_TRUSTED_NON_3GPP_ACCESS, "N3_TRUSTED_NON_3GPP_ACCESS" }, - { OSMO_PFCP_3GPP_IFACE_TYPE_N3_UNTRUSTED_NON_3GPP_ACCESS, "N3_UNTRUSTED_NON_3GPP_ACCESS" }, - { OSMO_PFCP_3GPP_IFACE_TYPE_N3_FOR_DATA_FORWARDING, "N3_FOR_DATA_FORWARDING" }, - { OSMO_PFCP_3GPP_IFACE_TYPE_N9, "N9" }, - { OSMO_PFCP_3GPP_IFACE_TYPE_SGI, "SGI" }, - { OSMO_PFCP_3GPP_IFACE_TYPE_N6, "N6" }, - { OSMO_PFCP_3GPP_IFACE_TYPE_N19, "N19" }, - { OSMO_PFCP_3GPP_IFACE_TYPE_S8_U, "S8_U" }, - { OSMO_PFCP_3GPP_IFACE_TYPE_GP_U, "GP_U" }, - {} -}; diff --git a/tests/Makefile.am b/tests/Makefile.am index fad7e6c..66510f0 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,7 +1,3 @@ -SUBDIRS = \ - libosmo-pfcp \ - $(NULL) - # The `:;' works around a Bash 3.2 bug when the output is not writeable. $(srcdir)/package.m4: $(top_srcdir)/configure.ac :;{ \ diff --git a/tests/libosmo-pfcp/Makefile.am b/tests/libosmo-pfcp/Makefile.am deleted file mode 100644 index eba3aa4..0000000 --- a/tests/libosmo-pfcp/Makefile.am +++ /dev/null @@ -1,33 +0,0 @@ -AM_CPPFLAGS = \ - $(all_includes) \ - -I$(top_srcdir)/include \ - -I$(top_builddir)/include \ - $(NULL) - -AM_CFLAGS = \ - -Wall \ - $(LIBOSMOCORE_CFLAGS) \ - $(LIBOSMOGTLV_CFLAGS) \ - $(NULL) - -noinst_PROGRAMS = \ - pfcp_test \ - $(NULL) - -EXTRA_DIST = \ - pfcp_test.ok \ - $(NULL) - -pfcp_test_SOURCES = \ - pfcp_test.c \ - $(NULL) - -pfcp_test_LDADD = \ - $(top_builddir)/src/libosmo-pfcp/libosmo-pfcp.a \ - $(LIBOSMOCORE_LIBS) \ - $(LIBOSMOGTLV_LIBS) \ - $(NULL) - -.PHONY: update_exp -update_exp: - $(builddir)/pfcp_test >$(srcdir)/pfcp_test.ok diff --git a/tests/libosmo-pfcp/pfcp_test.c b/tests/libosmo-pfcp/pfcp_test.c deleted file mode 100644 index 189622e..0000000 --- a/tests/libosmo-pfcp/pfcp_test.c +++ /dev/null @@ -1,512 +0,0 @@ -/* - * (C) 2021-2022 by sysmocom - s.f.m.c. GmbH info@sysmocom.de - * All Rights Reserved. - * - * Author: Neels Janosch Hofmeyr nhofmeyr@sysmocom.de - * - * SPDX-License-Identifier: GPL-2.0+ - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. - * - */ - -#include <stdio.h> -#include <errno.h> - -#include <osmocom/core/application.h> -#include <osmocom/core/utils.h> -#include <osmocom/core/msgb.h> - -#include <osmocom/pfcp/pfcp_msg.h> - -void *ctx; - -/* struct osmo_sockaddr */ -#define v4_ue { \ - .u.sin = { \ - .sin_family = AF_INET, \ - .sin_addr = { 0x1700a8c0 }, \ - } \ -} - -/* struct osmo_sockaddr */ -#define v4_gtp { \ - .u.sin = { \ - .sin_family = AF_INET, \ - .sin_addr = { 0x0708090a }, \ - } \ -} - -/* struct osmo_pfcp_ie_f_teid */ -#define f_teid_access_local { \ - .choose_flag = true, \ - .choose = { \ - .ipv4_addr = true, \ - }, \ -} - -/* struct osmo_pfcp_ie_f_teid */ -#define f_teid_created { \ - .fixed = { \ - .teid = 1234, \ - .ip_addr = { \ - .v4_present = true, \ - .v4 = v4_gtp, \ - }, \ - }, \ -} - -/* struct osmo_pfcp_ie_outer_header_creation */ -#define ohc_access { \ - .desc_bits = { 0x01 }, \ - .teid_present = true, \ - .teid = 0xabcdef, \ - .ip_addr = { \ - .v4_present = true, \ - .v4 = v4_gtp, \ - }, \ -} - -/* struct osmo_pfcp_ie_apply_action */ -#define aa_forw { \ - .bits = { 0x02 }, \ -} - -/* struct osmo_pfcp_ie_f_seid */ -#define f_seid { \ - .seid = 0x1234567890abcdef, \ - .ip_addr = { \ - .v4_present = true, \ - .v4 = v4_gtp, \ - }, \ -} - -struct osmo_pfcp_msg tests[] = { - { - .h = { - .version = 1, - .message_type = OSMO_PFCP_MSGT_HEARTBEAT_REQ, - .sequence_nr = 1, - }, - .ies.heartbeat_req = { - .recovery_time_stamp = 1234, - }, - }, - { - .h = { - .version = 1, - .message_type = OSMO_PFCP_MSGT_HEARTBEAT_RESP, - .sequence_nr = 2, - }, - .ies.heartbeat_resp = { - .recovery_time_stamp = 5678, - }, - }, - { - .h = { - .version = 1, - .message_type = OSMO_PFCP_MSGT_ASSOC_SETUP_REQ, - .sequence_nr = 3, - }, - .ies.assoc_setup_req = { - .node_id = { - .type = OSMO_PFCP_NODE_ID_T_IPV4, - .ip.u.sin = { - .sin_family = AF_INET, - .sin_addr = { 0x01020304 }, - }, - }, - .recovery_time_stamp = 0x2b2b2b2b, - }, - }, - { - .h = { - .version = 1, - .message_type = OSMO_PFCP_MSGT_ASSOC_SETUP_RESP, - .sequence_nr = 4, - }, - .ies.assoc_setup_resp = { - .node_id = { - .type = OSMO_PFCP_NODE_ID_T_FQDN, - .fqdn = "example.com", - }, - .cause = OSMO_PFCP_CAUSE_REQUEST_ACCEPTED, - .recovery_time_stamp = 0x2b2b2b2b, - .up_function_features_present = true, - .up_function_features.bits = { 1, 2 }, - }, - }, - { - .h = { - .version = 1, - .message_type = OSMO_PFCP_MSGT_ASSOC_RELEASE_REQ, - .sequence_nr = 5, - }, - .ies.assoc_release_req = { - .node_id = { - .type = OSMO_PFCP_NODE_ID_T_IPV6, - .ip.u.sin6 = { - .sin6_family = AF_INET6, - .sin6_addr = {{{ 1, 2, 3, 4 }}}, - }, - }, - }, - }, - { - .h = { - .version = 1, - .message_type = OSMO_PFCP_MSGT_ASSOC_RELEASE_RESP, - .sequence_nr = 6, - }, - .ies.assoc_release_resp = { - .node_id = { - .type = OSMO_PFCP_NODE_ID_T_IPV4, - .ip.u.sin = { - .sin_family = AF_INET, - .sin_addr = { 0x01020304 }, - }, - }, - .cause = OSMO_PFCP_CAUSE_REQUEST_REJECTED, - }, - }, - { - .h = { - .version = 1, - .message_type = OSMO_PFCP_MSGT_SESSION_EST_REQ, - .sequence_nr = 7, - .seid_present = true, - .seid = 0, - }, - .ies.session_est_req = { - .node_id = { - .type = OSMO_PFCP_NODE_ID_T_IPV4, - .ip.u.sin = { - .sin_family = AF_INET, - .sin_addr = { 0x0100007f }, - }, - }, - .cp_f_seid_present = true, - .cp_f_seid = f_seid, - .create_pdr_count = 2, - .create_pdr = { - { - .pdr_id = 1, - .precedence = 255, - .pdi = { - .source_iface = OSMO_PFCP_SOURCE_IFACE_CORE, - .ue_ip_address_present = true, - .ue_ip_address = { - .ip_is_destination = true, - .ip_addr = { - .v4_present = true, - .v4 = v4_ue, - }, - }, - }, - .far_id_present = true, - .far_id = 1, - }, - { - .pdr_id = 2, - .precedence = 255, - .pdi = { - .source_iface = OSMO_PFCP_SOURCE_IFACE_ACCESS, - .local_f_teid_present = true, - .local_f_teid = f_teid_access_local, - }, - .outer_header_removal_present = true, - .outer_header_removal = { - .desc = OSMO_PFCP_OUTER_HEADER_REMOVAL_GTP_U_UDP_IPV4, - }, - .far_id_present = true, - .far_id = 2, - }, - }, - .create_far_count = 2, - .create_far = { - { - .far_id = 1, - .forw_params_present = true, - .forw_params = { - .destination_iface = OSMO_PFCP_DEST_IFACE_ACCESS, - .outer_header_creation_present = true, - .outer_header_creation = ohc_access, - }, - .apply_action = aa_forw, - }, - { - .far_id = 2, - .forw_params_present = true, - .forw_params = { - .destination_iface = OSMO_PFCP_DEST_IFACE_CORE, - }, - .apply_action = aa_forw, - }, - }, - }, - }, - { - .h = { - .version = 1, - .message_type = OSMO_PFCP_MSGT_SESSION_EST_RESP, - .sequence_nr = 8, - .seid_present = true, - .seid = 0x0123456789abcdef, - }, - .ies.session_est_resp = { - .node_id = { - .type = OSMO_PFCP_NODE_ID_T_IPV4, - .ip.u.sin = { - .sin_family = AF_INET, - .sin_addr = { 0x0200007f }, - }, - }, - .cause = OSMO_PFCP_CAUSE_REQUEST_ACCEPTED, - .up_f_seid_present = true, - .up_f_seid = f_seid, - .created_pdr_count = 2, - .created_pdr = { - { - .pdr_id = 1, - }, - { - .pdr_id = 2, - .local_f_teid_present = true, - .local_f_teid = f_teid_created, - }, - }, - }, - }, - { - .h = { - .version = 1, - .message_type = OSMO_PFCP_MSGT_SESSION_MOD_REQ, - .sequence_nr = 9, - .seid_present = true, - .seid = 0, - }, - .ies.session_mod_req = { - .remove_pdr_count = 1, - .remove_pdr = { - { - .pdr_id = 1, - }, - }, - .remove_far_count = 1, - .remove_far = { - { - .far_id = 1, - }, - }, - .create_pdr_count = 1, - .create_pdr = { - { - .pdr_id = 3, - .precedence = 255, - .pdi = { - .source_iface = OSMO_PFCP_SOURCE_IFACE_ACCESS, - .local_f_teid_present = true, - .local_f_teid = f_teid_access_local, - }, - .outer_header_removal_present = true, - .outer_header_removal = { - .desc = OSMO_PFCP_OUTER_HEADER_REMOVAL_GTP_U_UDP_IPV4, - }, - .far_id_present = true, - .far_id = 3, - }, - }, - .create_far_count = 1, - .create_far = { - { - .far_id = 3, - .forw_params_present = true, - .forw_params = { - .destination_iface = OSMO_PFCP_DEST_IFACE_ACCESS, - .outer_header_creation_present = true, - .outer_header_creation = ohc_access, - }, - .apply_action = aa_forw, - }, - }, - .upd_pdr_count = 1, - .upd_pdr = { - { - .pdr_id = 1, - .pdi = { - .source_iface = OSMO_PFCP_SOURCE_IFACE_ACCESS, - .local_f_teid_present = true, - .local_f_teid = f_teid_access_local, - }, - .outer_header_removal_present = true, - .outer_header_removal = { - .desc = OSMO_PFCP_OUTER_HEADER_REMOVAL_GTP_U_UDP_IPV4, - }, - .far_id_present = true, - .far_id = 1, - }, - }, - .upd_far_count = 1, - .upd_far = { - { - .far_id = 1, - .upd_forw_params_present = true, - .upd_forw_params = { - .destination_iface = OSMO_PFCP_DEST_IFACE_CORE, - .network_inst_present = true, - .network_inst = { - .str = "internet", - }, - }, - .apply_action = aa_forw, - }, - }, - }, - }, - { - .h = { - .version = 1, - .message_type = OSMO_PFCP_MSGT_SESSION_MOD_RESP, - .sequence_nr = 10, - .seid_present = true, - .seid = 0x0123456789abcdef, - }, - .ies.session_mod_resp = { - .cause = OSMO_PFCP_CAUSE_REQUEST_ACCEPTED, - .created_pdr_count = 1, - .created_pdr = { - { - .pdr_id = 3, - .local_f_teid_present = true, - .local_f_teid = f_teid_created, - }, - }, - .updated_pdr_count = 1, - .updated_pdr = { - { - .pdr_id = 1, - .local_f_teid_present = true, - .local_f_teid = f_teid_created, - }, - }, - }, - }, - { - .h = { - .version = 1, - .message_type = OSMO_PFCP_MSGT_SESSION_MOD_RESP, - .sequence_nr = 11, - .seid_present = true, - .seid = 0x0123456789abcdef, - }, - .ies.session_mod_resp = { - .cause = OSMO_PFCP_CAUSE_MANDATORY_IE_MISSING, - .offending_ie_present = true, - .offending_ie = OSMO_PFCP_IEI_APPLY_ACTION, - }, - }, - { - .h = { - .version = 1, - .message_type = OSMO_PFCP_MSGT_SESSION_DEL_REQ, - .sequence_nr = 12, - .seid_present = true, - .seid = 0x0123456789abcdef, - }, - }, - { - .h = { - .version = 1, - .message_type = OSMO_PFCP_MSGT_SESSION_DEL_RESP, - .sequence_nr = 13, - .seid_present = true, - .seid = 0x0123456789abcdef, - }, - .ies.session_del_resp = { - .cause = OSMO_PFCP_CAUSE_NO_ESTABLISHED_PFCP_ASSOC, - }, - }, - { - .h = { - .version = 1, - .message_type = OSMO_PFCP_MSGT_SESSION_DEL_RESP, - .sequence_nr = 13, - .seid_present = true, - .seid = 0x0123456789abcdef, - }, - .ies.session_del_resp = { - .cause = OSMO_PFCP_CAUSE_REQUEST_ACCEPTED, - }, - }, -}; - -void test_enc_dec() -{ - int i; - for (i = 0; i < ARRAY_SIZE(tests); i++) { - void *loop_ctx = talloc_named_const(ctx, 0, "loop"); - int rc; - const struct osmo_pfcp_msg *orig = &tests[i]; - struct osmo_pfcp_msg parsed = {}; - struct msgb *msg; - struct osmo_gtlv_load tlv; - - printf("\n=== start %s[%d]\n", __func__, i); - printf("encoding: %s\n", osmo_pfcp_message_type_str(orig->h.message_type)); - printf("%s\n", osmo_pfcp_msg_to_str_c(loop_ctx, orig)); - msg = msgb_alloc(1024, __func__); - rc = osmo_pfcp_msg_encode(msg, orig); - printf("osmo_pfcp_msg_encode() rc = %d\n", rc); - printf("%s.\n", osmo_hexdump(msg->data, msg->len)); - - rc = osmo_pfcp_msg_decode_header(&tlv, &parsed, msg); - printf("osmo_pfcp_msg_decode_header() rc = %d\n", rc); - if (rc != msgb_length(msg)) { - printf("ERROR: expected rc = %d\n", msgb_length(msg)); - exit(1); - } else { - printf("rc == msgb_length()\n"); - } - - rc = osmo_pfcp_msg_decode_tlv(&parsed, &tlv); - printf("osmo_pfcp_msg_decode_tlv() rc = %d\n", rc); - - if (strcmp(osmo_pfcp_msg_to_str_c(loop_ctx, orig), - osmo_pfcp_msg_to_str_c(loop_ctx, &parsed))) { - printf(" ERROR: parsed != orig\n"); - printf(" orig: %s\n", - osmo_pfcp_msg_to_str_c(loop_ctx, orig)); - printf(" parsed: %s\n", - osmo_pfcp_msg_to_str_c(loop_ctx, &parsed)); - exit(1); - } else { - printf("parsed == orig\n"); - } - - msgb_free(msg); - printf("=== end %s[%d]\n", __func__, i); - talloc_free(loop_ctx); - } -} - -int main() -{ - ctx = talloc_named_const(NULL, 0, "pfcp_test"); - msgb_talloc_ctx_init(ctx, 0); - - test_enc_dec(); - - talloc_free(ctx); - return 0; -} diff --git a/tests/libosmo-pfcp/pfcp_test.ok b/tests/libosmo-pfcp/pfcp_test.ok deleted file mode 100644 index 2b8cc1a..0000000 --- a/tests/libosmo-pfcp/pfcp_test.ok +++ /dev/null @@ -1,154 +0,0 @@ - -=== start test_enc_dec[0] -encoding: HEARTBEAT_REQ -PFCPv1 HEARTBEAT_REQ hdr={seq=1} ies={ 'Recovery Time Stamp'=1234 } -osmo_pfcp_msg_encode() rc = 0 -20 01 00 0c 00 00 01 00 00 60 00 04 00 00 04 d2 . -osmo_pfcp_msg_decode_header() rc = 16 -rc == msgb_length() -osmo_pfcp_msg_decode_tlv() rc = 0 -parsed == orig -=== end test_enc_dec[0] - -=== start test_enc_dec[1] -encoding: HEARTBEAT_RESP -PFCPv1 HEARTBEAT_RESP hdr={seq=2} ies={ 'Recovery Time Stamp'=5678 } -osmo_pfcp_msg_encode() rc = 0 -20 02 00 0c 00 00 02 00 00 60 00 04 00 00 16 2e . -osmo_pfcp_msg_decode_header() rc = 16 -rc == msgb_length() -osmo_pfcp_msg_decode_tlv() rc = 0 -parsed == orig -=== end test_enc_dec[1] - -=== start test_enc_dec[2] -encoding: ASSOC_SETUP_REQ -PFCPv1 ASSOC_SETUP_REQ hdr={seq=3} ies={ 'Node ID'=v4:4.3.2.1 'Recovery Time Stamp'=724249387 } -osmo_pfcp_msg_encode() rc = 0 -20 05 00 15 00 00 03 00 00 3c 00 05 00 04 03 02 01 00 60 00 04 2b 2b 2b 2b . -osmo_pfcp_msg_decode_header() rc = 25 -rc == msgb_length() -osmo_pfcp_msg_decode_tlv() rc = 0 -parsed == orig -=== end test_enc_dec[2] - -=== start test_enc_dec[3] -encoding: ASSOC_SETUP_RESP -PFCPv1 ASSOC_SETUP_RESP hdr={seq=4} ies={ 'Node ID'=fqdn:"example.com" 'Cause'=Request accepted (success) 'Recovery Time Stamp'=724249387 'UP Function Features'=( BUCP PDIU ) } -osmo_pfcp_msg_encode() rc = 0 -20 06 00 2b 00 00 04 00 00 3c 00 0c 02 65 78 61 6d 70 6c 65 2e 63 6f 6d 00 13 00 01 01 00 60 00 04 2b 2b 2b 2b 00 2b 00 06 01 02 00 00 00 00 . -osmo_pfcp_msg_decode_header() rc = 47 -rc == msgb_length() -osmo_pfcp_msg_decode_tlv() rc = 0 -parsed == orig -=== end test_enc_dec[3] - -=== start test_enc_dec[4] -encoding: ASSOC_RELEASE_REQ -PFCPv1 ASSOC_RELEASE_REQ hdr={seq=5} ies={ 'Node ID'=v6:[102:304::] } -osmo_pfcp_msg_encode() rc = 0 -20 09 00 19 00 00 05 00 00 3c 00 11 01 01 02 03 04 00 00 00 00 00 00 00 00 00 00 00 00 . -osmo_pfcp_msg_decode_header() rc = 29 -rc == msgb_length() -osmo_pfcp_msg_decode_tlv() rc = 0 -parsed == orig -=== end test_enc_dec[4] - -=== start test_enc_dec[5] -encoding: ASSOC_RELEASE_RESP -PFCPv1 ASSOC_RELEASE_RESP hdr={seq=6} ies={ 'Node ID'=v4:4.3.2.1 'Cause'=Request rejected (reason not specified) } -osmo_pfcp_msg_encode() rc = 0 -20 0a 00 12 00 00 06 00 00 3c 00 05 00 04 03 02 01 00 13 00 01 40 . -osmo_pfcp_msg_decode_header() rc = 22 -rc == msgb_length() -osmo_pfcp_msg_decode_tlv() rc = 0 -parsed == orig -=== end test_enc_dec[5] - -=== start test_enc_dec[6] -encoding: SESSION_EST_REQ -PFCPv1 SESSION_EST_REQ hdr={seq=7 SEID=0x0} ies={ 'Node ID'=v4:127.0.0.1 'F-SEID'=0x1234567890abcdef,v4:10.9.8.7 'Create PDR'={ { 'PDR ID'=1 'Precedence'=255 'PDI'={ 'Source Interface'=Core 'UE IP Address'=,dst,v4:192.168.0.23 } 'FAR ID'=1 }, { 'PDR ID'=2 'Precedence'=255 'PDI'={ 'Source Interface'=Access 'F-TEID'=CHOOSE-v4 } 'Outer Header Removal'=GTP_U_UDP_IPV4 'FAR ID'=2 } } 'Create FAR'={ { 'FAR ID'=1 'Apply Action'=( FORW ) 'Forwarding Parameters'={ 'Destination Interface'=Access 'Outer Header Creation'=( GTP_U_UDP_IPV4 ),TEID:0xabcdef,v4:10.9.8.7 } }, { 'FAR ID'=2 'Apply Action'=( FORW ) 'Forwarding Parameters'={ 'Destination Interface'=Core } } } } -osmo_pfcp_msg_encode() rc = 0 -21 32 00 c3 00 00 00 00 00 00 00 00 00 00 07 00 00 3c 00 05 00 7f 00 00 01 00 39 00 0d 02 12 34 56 78 90 ab cd ef 0a 09 08 07 00 01 00 28 00 38 00 02 00 01 00 1d 00 04 00 00 00 ff 00 02 00 0e 00 14 00 01 01 00 5d 00 05 06 c0 a8 00 17 00 6c 00 04 00 00 00 01 00 01 00 29 00 38 00 02 00 02 00 1d 00 04 00 00 00 ff 00 02 00 0a 00 14 00 01 00 00 15 00 01 05 00 5f 00 01 00 00 6c 00 04 00 00 00 02 00 03 00 25 00 6c 00 04 00 00 00 01 00 2c 00 02 02 00 00 04 00 13 00 2a 00 01 00 00 54 00 0a 01 00 00 ab cd ef 0a 09 08 07 00 03 00 17 00 6c 00 04 00 00 00 02 00 2c 00 02 02 00 00 04 00 05 00 2a 00 01 01 . -osmo_pfcp_msg_decode_header() rc = 199 -rc == msgb_length() -osmo_pfcp_msg_decode_tlv() rc = 0 -parsed == orig -=== end test_enc_dec[6] - -=== start test_enc_dec[7] -encoding: SESSION_EST_RESP -PFCPv1 SESSION_EST_RESP hdr={seq=8 SEID=0x123456789abcdef} ies={ 'Node ID'=v4:127.0.0.2 'Cause'=Request accepted (success) 'F-SEID'=0x1234567890abcdef,v4:10.9.8.7 'Created PDR'={ { 'PDR ID'=1 }, { 'PDR ID'=2 'F-TEID'=TEID-0x4d2,v4:10.9.8.7 } } } -osmo_pfcp_msg_encode() rc = 0 -21 33 00 4c 01 23 45 67 89 ab cd ef 00 00 08 00 00 3c 00 05 00 7f 00 00 02 00 13 00 01 01 00 39 00 0d 02 12 34 56 78 90 ab cd ef 0a 09 08 07 00 08 00 06 00 38 00 02 00 01 00 08 00 13 00 38 00 02 00 02 00 15 00 09 01 00 00 04 d2 0a 09 08 07 . -osmo_pfcp_msg_decode_header() rc = 80 -rc == msgb_length() -osmo_pfcp_msg_decode_tlv() rc = 0 -parsed == orig -=== end test_enc_dec[7] - -=== start test_enc_dec[8] -encoding: SESSION_MOD_REQ -PFCPv1 SESSION_MOD_REQ hdr={seq=9 SEID=0x0} ies={ 'Remove PDR'={ { 'PDR ID'=1 } } 'Remove FAR'={ { 'FAR ID'=1 } } 'Create PDR'={ { 'PDR ID'=3 'Precedence'=255 'PDI'={ 'Source Interface'=Access 'F-TEID'=CHOOSE-v4 } 'Outer Header Removal'=GTP_U_UDP_IPV4 'FAR ID'=3 } } 'Create FAR'={ { 'FAR ID'=3 'Apply Action'=( FORW ) 'Forwarding Parameters'={ 'Destination Interface'=Access 'Outer Header Creation'=( GTP_U_UDP_IPV4 ),TEID:0xabcdef,v4:10.9.8.7 } } } 'Update PDR'={ { 'PDR ID'=1 'Outer Header Removal'=GTP_U_UDP_IPV4 'FAR ID'=1 } } 'Update FAR'={ { 'FAR ID'=1 'Update Forwarding Parameters'={ 'Network Instance'="internet" } } } } -osmo_pfcp_msg_encode() rc = 0 -21 34 00 ab 00 00 00 00 00 00 00 00 00 00 09 00 00 0f 00 06 00 38 00 02 00 01 00 10 00 08 00 6c 00 04 00 00 00 01 00 01 00 29 00 38 00 02 00 03 00 1d 00 04 00 00 00 ff 00 02 00 0a 00 14 00 01 00 00 15 00 01 05 00 5f 00 01 00 00 6c 00 04 00 00 00 03 00 03 00 25 00 6c 00 04 00 00 00 03 00 2c 00 02 02 00 00 04 00 13 00 2a 00 01 00 00 54 00 0a 01 00 00 ab cd ef 0a 09 08 07 00 09 00 13 00 38 00 02 00 01 00 5f 00 01 00 00 6c 00 04 00 00 00 01 00 0a 00 18 00 6c 00 04 00 00 00 01 00 0b 00 0c 00 16 00 08 69 6e 74 65 72 6e 65 74 . -osmo_pfcp_msg_decode_header() rc = 175 -rc == msgb_length() -osmo_pfcp_msg_decode_tlv() rc = 0 -parsed == orig -=== end test_enc_dec[8] - -=== start test_enc_dec[9] -encoding: SESSION_MOD_RESP -PFCPv1 SESSION_MOD_RESP hdr={seq=10 SEID=0x123456789abcdef} ies={ 'Cause'=Request accepted (success) 'Created PDR'={ { 'PDR ID'=3 'F-TEID'=TEID-0x4d2,v4:10.9.8.7 } } 'Updated PDR'={ { 'PDR ID'=1 'F-TEID'=TEID-0x4d2,v4:10.9.8.7 } } } -osmo_pfcp_msg_encode() rc = 0 -21 35 00 3f 01 23 45 67 89 ab cd ef 00 00 0a 00 00 13 00 01 01 00 08 00 13 00 38 00 02 00 03 00 15 00 09 01 00 00 04 d2 0a 09 08 07 01 00 00 13 00 38 00 02 00 01 00 15 00 09 01 00 00 04 d2 0a 09 08 07 . -osmo_pfcp_msg_decode_header() rc = 67 -rc == msgb_length() -osmo_pfcp_msg_decode_tlv() rc = 0 -parsed == orig -=== end test_enc_dec[9] - -=== start test_enc_dec[10] -encoding: SESSION_MOD_RESP -PFCPv1 SESSION_MOD_RESP hdr={seq=11 SEID=0x123456789abcdef} ies={ 'Cause'=Mandatory IE missing 'Offending IE'=Apply Action } -osmo_pfcp_msg_encode() rc = 0 -21 35 00 17 01 23 45 67 89 ab cd ef 00 00 0b 00 00 13 00 01 42 00 28 00 02 00 2c . -osmo_pfcp_msg_decode_header() rc = 27 -rc == msgb_length() -osmo_pfcp_msg_decode_tlv() rc = 0 -parsed == orig -=== end test_enc_dec[10] - -=== start test_enc_dec[11] -encoding: SESSION_DEL_REQ -PFCPv1 SESSION_DEL_REQ hdr={seq=12 SEID=0x123456789abcdef} ies={ } -osmo_pfcp_msg_encode() rc = 0 -21 36 00 0c 01 23 45 67 89 ab cd ef 00 00 0c 00 . -osmo_pfcp_msg_decode_header() rc = 16 -rc == msgb_length() -osmo_pfcp_msg_decode_tlv() rc = 0 -parsed == orig -=== end test_enc_dec[11] - -=== start test_enc_dec[12] -encoding: SESSION_DEL_RESP -PFCPv1 SESSION_DEL_RESP hdr={seq=13 SEID=0x123456789abcdef} ies={ 'Cause'=No established PFCP Association } -osmo_pfcp_msg_encode() rc = 0 -21 37 00 11 01 23 45 67 89 ab cd ef 00 00 0d 00 00 13 00 01 48 . -osmo_pfcp_msg_decode_header() rc = 21 -rc == msgb_length() -osmo_pfcp_msg_decode_tlv() rc = 0 -parsed == orig -=== end test_enc_dec[12] - -=== start test_enc_dec[13] -encoding: SESSION_DEL_RESP -PFCPv1 SESSION_DEL_RESP hdr={seq=13 SEID=0x123456789abcdef} ies={ 'Cause'=Request accepted (success) } -osmo_pfcp_msg_encode() rc = 0 -21 37 00 11 01 23 45 67 89 ab cd ef 00 00 0d 00 00 13 00 01 01 . -osmo_pfcp_msg_decode_header() rc = 21 -rc == msgb_length() -osmo_pfcp_msg_decode_tlv() rc = 0 -parsed == orig -=== end test_enc_dec[13] diff --git a/tests/testsuite.at b/tests/testsuite.at index 352fba9..09a77c3 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -1,8 +1,2 @@ AT_INIT AT_BANNER([Regression tests.]) - -AT_SETUP([pfcp]) -AT_KEYWORDS([pfcp]) -cat $abs_srcdir/libosmo-pfcp/pfcp_test.ok > expout -AT_CHECK([$abs_top_builddir/tests/libosmo-pfcp/pfcp_test], [], [expout], [ignore]) -AT_CLEANUP
null-- To view, visit https://gerrit.osmocom.org/c/osmo-upf/+/28306 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-upf Gerrit-Branch: master Gerrit-Change-Id: I1464cdd846b00707b0abba9126aa5bb784b7caf1 Gerrit-Change-Number: 28306 Gerrit-PatchSet: 1 Gerrit-Owner: neels nhofmeyr@sysmocom.de Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: laforge laforge@osmocom.org Gerrit-Reviewer: pespin pespin@sysmocom.de Gerrit-MessageType: merged