From 27a90869c7f72520311ba2e91eb8fe7a3a1beb09 Mon Sep 17 00:00:00 2001 From: Neels Janosch Hofmeyr Date: Thu, 9 Feb 2023 17:41:35 +0100 Subject: [PATCH] add unique_ids_test.c Verify that skipping used IDs works for: - PFCP UP-SEID - GTP local TEID - chain_id for nft rulesets -- so far expected to fail, fix follows in I139b46de0bd15185a7a06109d55f7c759755ec81. Related: OS#5900 Change-Id: I36acff15f22d23ade4d281c2af3eb117dfc10359 --- configure.ac | 1 + include/osmocom/upf/up_endpoint.h | 3 +- include/osmocom/upf/up_session.h | 3 +- include/osmocom/upf/upf.h | 3 +- src/osmo-upf/up_endpoint.c | 15 +- src/osmo-upf/up_peer.c | 2 +- src/osmo-upf/up_session.c | 11 +- src/osmo-upf/upf.c | 25 +- src/osmo-upf/upf_nft.c | 2 +- tests/Makefile.am | 4 + tests/testsuite.at | 7 + tests/unique_ids/Makefile.am | 41 ++ tests/unique_ids/unique_ids_test.c | 571 +++++++++++++++++++++++++++ tests/unique_ids/unique_ids_test.err | 412 +++++++++++++++++++ tests/unique_ids/unique_ids_test.ok | 0 15 files changed, 1076 insertions(+), 24 deletions(-) create mode 100644 tests/unique_ids/Makefile.am create mode 100644 tests/unique_ids/unique_ids_test.c create mode 100644 tests/unique_ids/unique_ids_test.err create mode 100644 tests/unique_ids/unique_ids_test.ok diff --git a/configure.ac b/configure.ac index 0108f92..5181131 100644 --- a/configure.ac +++ b/configure.ac @@ -203,6 +203,7 @@ AC_OUTPUT( src/osmo-pfcp-tool/Makefile tests/Makefile tests/atlocal + tests/unique_ids/Makefile doc/Makefile doc/examples/Makefile doc/manuals/Makefile diff --git a/include/osmocom/upf/up_endpoint.h b/include/osmocom/upf/up_endpoint.h index 58fe01c..ac240cd 100644 --- a/include/osmocom/upf/up_endpoint.h +++ b/include/osmocom/upf/up_endpoint.h @@ -41,7 +41,8 @@ struct up_endpoint { uint64_t next_up_seid_state; }; -struct up_endpoint *up_endpoint_init(void *ctx, const struct osmo_sockaddr *local_addr); +struct up_endpoint *up_endpoint_alloc(void *ctx, const struct osmo_sockaddr *local_addr); +int up_endpoint_bind(struct up_endpoint *up_ep); void up_endpoint_free(struct up_endpoint **ep); uint64_t up_endpoint_next_up_seid(struct up_endpoint *ep); diff --git a/include/osmocom/upf/up_session.h b/include/osmocom/upf/up_session.h index 215a414..c424df9 100644 --- a/include/osmocom/upf/up_session.h +++ b/include/osmocom/upf/up_session.h @@ -66,8 +66,7 @@ struct up_session { struct llist_head active_gtp_actions; }; -struct up_session *up_session_find_or_add(struct up_peer *peer, const struct osmo_pfcp_ie_f_seid *cp_f_seid, - const struct osmo_pfcp_ie_f_seid *up_f_seid); +struct up_session *up_session_find_or_add(struct up_peer *peer, const struct osmo_pfcp_ie_f_seid *cp_f_seid); struct up_session *up_session_find_by_up_seid(struct up_peer *peer, uint64_t up_seid); struct up_session *up_session_find_by_cp_f_seid(struct up_peer *peer, const struct osmo_pfcp_ie_f_seid *cp_f_seid); struct up_session *up_session_find_by_local_teid(struct up_peer *peer, uint32_t teid); diff --git a/include/osmocom/upf/upf.h b/include/osmocom/upf/upf.h index 041edea..c1dc39a 100644 --- a/include/osmocom/upf/upf.h +++ b/include/osmocom/upf/upf.h @@ -134,7 +134,8 @@ enum upf_log_subsys { void g_upf_alloc(void *ctx); void upf_vty_init(); -int upf_pfcp_listen(); +int upf_pfcp_init(void); +int upf_pfcp_listen(void); int upf_gtp_devs_open(); void upf_gtp_devs_close(); diff --git a/src/osmo-upf/up_endpoint.c b/src/osmo-upf/up_endpoint.c index 7a2628a..34351a6 100644 --- a/src/osmo-upf/up_endpoint.c +++ b/src/osmo-upf/up_endpoint.c @@ -233,9 +233,8 @@ static void up_endpoint_rx_cb(struct osmo_pfcp_endpoint *ep, struct osmo_pfcp_ms } } -struct up_endpoint *up_endpoint_init(void *ctx, const struct osmo_sockaddr *local_addr) +struct up_endpoint *up_endpoint_alloc(void *ctx, const struct osmo_sockaddr *local_addr) { - int rc; struct osmo_pfcp_endpoint_cfg cfg; struct up_endpoint *up_ep; up_ep = talloc_zero(ctx, struct up_endpoint); @@ -252,14 +251,16 @@ struct up_endpoint *up_endpoint_init(void *ctx, const struct osmo_sockaddr *loca up_ep->pfcp_ep = osmo_pfcp_endpoint_create(up_ep, &cfg); OSMO_ASSERT(up_ep->pfcp_ep); - rc = osmo_pfcp_endpoint_bind(up_ep->pfcp_ep); - if (rc) { - talloc_free(up_ep); - return NULL; - } return up_ep; } +int up_endpoint_bind(struct up_endpoint *up_ep) +{ + OSMO_ASSERT(up_ep); + OSMO_ASSERT(up_ep->pfcp_ep); + return osmo_pfcp_endpoint_bind(up_ep->pfcp_ep); +} + static struct up_session *up_endpoint_find_session(struct up_endpoint *ep, uint64_t up_seid) { struct up_peer *peer; diff --git a/src/osmo-upf/up_peer.c b/src/osmo-upf/up_peer.c index c0e43e4..08f7d12 100644 --- a/src/osmo-upf/up_peer.c +++ b/src/osmo-upf/up_peer.c @@ -299,7 +299,7 @@ static void up_peer_rx_session_est_req(struct up_peer *peer, struct osmo_pfcp_ms { enum osmo_pfcp_cause cause = OSMO_PFCP_CAUSE_REQUEST_ACCEPTED; struct osmo_pfcp_msg *resp; - struct up_session *session = up_session_find_or_add(peer, &m->ies.session_est_req.cp_f_seid, NULL); + struct up_session *session = up_session_find_or_add(peer, &m->ies.session_est_req.cp_f_seid); if (!session) { cause = OSMO_PFCP_CAUSE_NO_RESOURCES_AVAILABLE; diff --git a/src/osmo-upf/up_session.c b/src/osmo-upf/up_session.c index 5874f3c..593f131 100644 --- a/src/osmo-upf/up_session.c +++ b/src/osmo-upf/up_session.c @@ -1021,16 +1021,11 @@ static struct up_session *up_session_add(struct up_peer *peer, const struct osmo return session; } -struct up_session *up_session_find_or_add(struct up_peer *peer, const struct osmo_pfcp_ie_f_seid *cp_f_seid, - const struct osmo_pfcp_ie_f_seid *up_f_seid) +struct up_session *up_session_find_or_add(struct up_peer *peer, const struct osmo_pfcp_ie_f_seid *cp_f_seid) { struct up_session *session; - if (cp_f_seid) - session = up_session_find_by_cp_f_seid(peer, cp_f_seid); - else if (up_f_seid) - session = up_session_find_by_up_seid(peer, up_f_seid->seid); - else - return NULL; + OSMO_ASSERT(cp_f_seid); + session = up_session_find_by_cp_f_seid(peer, cp_f_seid); if (session) return session; diff --git a/src/osmo-upf/upf.c b/src/osmo-upf/upf.c index 047a6ff..41f6f62 100644 --- a/src/osmo-upf/upf.c +++ b/src/osmo-upf/upf.c @@ -67,7 +67,7 @@ void g_upf_alloc(void *ctx) INIT_LLIST_HEAD(&g_upf->netinst); } -int upf_pfcp_listen() +int upf_pfcp_init(void) { struct osmo_sockaddr_str local_addr_str; struct osmo_sockaddr local_addr; @@ -79,9 +79,8 @@ int upf_pfcp_listen() * osmo_sockaddr. */ osmo_sockaddr_str_from_str(&local_addr_str, g_upf->pfcp.vty_cfg.local_addr, g_upf->pfcp.vty_cfg.local_port); osmo_sockaddr_str_to_sockaddr(&local_addr_str, &local_addr.u.sas); - LOGP(DLPFCP, LOGL_NOTICE, "PFCP: Listening on %s\n", osmo_sockaddr_to_str_c(OTC_SELECT, &local_addr)); - g_upf->pfcp.ep = up_endpoint_init(g_upf, &local_addr); + g_upf->pfcp.ep = up_endpoint_alloc(g_upf, &local_addr); if (!g_upf->pfcp.ep) { fprintf(stderr, "Failed to allocate PFCP endpoint.\n"); return -1; @@ -89,6 +88,26 @@ int upf_pfcp_listen() return 0; } +int upf_pfcp_listen(void) +{ + int rc; + if (!g_upf->pfcp.ep) { + rc = upf_pfcp_init(); + if (rc) + return rc; + } + + rc = up_endpoint_bind(g_upf->pfcp.ep); + if (rc) { + LOGP(DLPFCP, LOGL_ERROR, "PFCP: failed to listen on %s\n", + osmo_sockaddr_to_str_c(OTC_SELECT, osmo_pfcp_endpoint_get_local_addr(g_upf->pfcp.ep->pfcp_ep))); + return rc; + } + LOGP(DLPFCP, LOGL_NOTICE, "PFCP: Listening on %s\n", + osmo_sockaddr_to_str_c(OTC_SELECT, osmo_pfcp_endpoint_get_local_addr(g_upf->pfcp.ep->pfcp_ep))); + return 0; +} + int upf_gtp_devs_open() { struct tunend_vty_cfg *c = &g_upf->tunend.vty_cfg; diff --git a/src/osmo-upf/upf_nft.c b/src/osmo-upf/upf_nft.c index ed3b921..e91443b 100644 --- a/src/osmo-upf/upf_nft.c +++ b/src/osmo-upf/upf_nft.c @@ -81,7 +81,7 @@ static int upf_nft_run(const char *ruleset) return -EIO; } - LOGP(DNFT, LOGL_DEBUG, "set up nft ruleset: %s\n", osmo_quote_str_c(OTC_SELECT, ruleset, -1)); + LOGP(DNFT, LOGL_DEBUG, "run nft ruleset: %s\n", osmo_quote_str_c(OTC_SELECT, ruleset, -1)); return 0; } diff --git a/tests/Makefile.am b/tests/Makefile.am index dbdb5f2..5e1d517 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,3 +1,7 @@ +SUBDIRS = \ + unique_ids \ + $(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/testsuite.at b/tests/testsuite.at index 09a77c3..45a5145 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -1,2 +1,9 @@ AT_INIT AT_BANNER([Regression tests.]) + +AT_SETUP([unique_ids_test]) +AT_KEYWORDS([unique_ids_test]) +cat $abs_srcdir/unique_ids/unique_ids_test.ok > expout +cat $abs_srcdir/unique_ids/unique_ids_test.err > experr +AT_CHECK([$abs_top_builddir/tests/unique_ids/unique_ids_test], [], [expout], [experr]) +AT_CLEANUP diff --git a/tests/unique_ids/Makefile.am b/tests/unique_ids/Makefile.am new file mode 100644 index 0000000..45eb9f9 --- /dev/null +++ b/tests/unique_ids/Makefile.am @@ -0,0 +1,41 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/include \ + $(NULL) + +AM_CFLAGS = \ + -Wall \ + $(LIBOSMOCORE_CFLAGS) \ + $(LIBOSMOVTY_CFLAGS) \ + $(LIBOSMOCTRL_CFLAGS) \ + $(LIBOSMOGTLV_CFLAGS) \ + $(LIBOSMOPFCP_CFLAGS) \ + $(LIBGTPNL_CFLAGS) \ + $(LIBNFTNL_CFLAGS) \ + $(LIBNFTABLES_CFLAGS) \ + $(COVERAGE_CFLAGS) \ + $(NULL) + +EXTRA_DIST = \ + unique_ids_test.ok \ + unique_ids_test.err \ + $(NULL) + +check_PROGRAMS = \ + unique_ids_test \ + $(NULL) + +unique_ids_test_SOURCES = \ + unique_ids_test.c \ + $(NULL) + +unique_ids_test_LDADD = \ + $(top_builddir)/src/osmo-upf/libupf.la \ + $(NULL) + +unique_ids_test_LDFLAGS = \ + -no-install \ + $(NULL) + +.PHONY: update_exp +update_exp: + $(builddir)/unique_ids_test >$(srcdir)/unique_ids_test.ok 2>$(srcdir)/unique_ids_test.err diff --git a/tests/unique_ids/unique_ids_test.c b/tests/unique_ids/unique_ids_test.c new file mode 100644 index 0000000..52cd9e8 --- /dev/null +++ b/tests/unique_ids/unique_ids_test.c @@ -0,0 +1,571 @@ +/* OsmoUPF: Verify that skipping used ids works for: UP-SEID, GTP local TEID, nft ruleset chain_id. */ + +/* (C) 2023 by sysmocom - s.f.m.c. GmbH + * + * All Rights Reserved + * + * Author: Neels Hofmeyr + * + * 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 . + * + */ + +#include + +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#define log(FMT, ARGS...) fprintf(stderr, FMT, ##ARGS) +#define log_assert(COND) do { \ + log("assert(" #COND ")\n"); \ + OSMO_ASSERT(COND); \ + } while (0) + +#define log_assert_expect_failure(COND) do { \ + log("assert(" #COND ") <-- EXPECTED TO FAIL (known error)\n"); \ + OSMO_ASSERT(!(COND)); \ + } while (0) + + +void *main_ctx; +void *ctx; + +/* The override of osmo_pfcp_endpoint_tx() stores any Session Establishment Response's UP-SEID here, so that this test + * can reference specific sessions later. + */ +uint64_t last_up_seid = 0; + +void select_poll(void) +{ + while (osmo_select_main_ctx(1)); +} + +static void setup(const char *name) +{ + log("\n===== START of %s\n", name); + ctx = talloc_named_const(main_ctx, 0, name); + g_upf_alloc(ctx); + osmo_talloc_replace_string(g_upf, &g_upf->pfcp.vty_cfg.local_addr, "1.1.1.1"); + + OSMO_ASSERT(netinst_add(g_upf, &g_upf->netinst, "default", "1.1.1.1", NULL)); + + /* PFCP endpoint recovery timestamp overridden by time() below */ + upf_pfcp_init(); + /* but do not upf_pfcp_listen() */ + + upf_nft_init(); + + select_poll(); + log("\n"); +} + +static void cleanup(void) +{ + up_endpoint_free(&g_upf->pfcp.ep); + upf_gtp_devs_close(); + + upf_gtp_genl_close(); + + upf_nft_free(); + + log("\n===== END of %s\n", talloc_get_name(ctx)); + talloc_free(ctx); +} + +static struct osmo_sockaddr *str2addr(const char *addr, uint16_t port) +{ + static struct osmo_sockaddr osa; + struct osmo_sockaddr_str str; + osmo_sockaddr_str_from_str(&str, addr, port); + osmo_sockaddr_str_to_sockaddr(&str, &osa.u.sas); + return &osa; +} + +static struct up_peer *have_peer(const char *remote_addr, uint16_t port) +{ + return up_peer_find_or_add(g_upf->pfcp.ep, str2addr(remote_addr, port)); +} + +static struct osmo_pfcp_msg *new_pfcp_msg_for_osmo_upf_rx(struct up_peer *from_peer, enum osmo_pfcp_message_type msg_type) +{ + /* pfcp_endpoint discards received messages immediately after dispatching; in this test, allocate them in + * OTC_SELECT so they get discarded on the next select_poll(). + * osmo_pfcp_msg_alloc_rx() is not useful here, it creates a blank struct to be decoded from raw data; instead, + * use osmo_pfcp_msg_alloc_tx_req() which properly sets up the internal structures to match the given msg_type, + * and when that is done set m->rx = true to indicate it is a message received by osmo-upf. */ + struct osmo_pfcp_msg *m = osmo_pfcp_msg_alloc_tx_req(OTC_SELECT, &from_peer->remote_addr, msg_type); + m->rx = true; + return m; +} + +static void peer_assoc(struct up_peer *peer) +{ + struct osmo_pfcp_msg *m = new_pfcp_msg_for_osmo_upf_rx(peer, OSMO_PFCP_MSGT_ASSOC_SETUP_REQ); + m->ies.assoc_setup_req.recovery_time_stamp = 1234; + osmo_fsm_inst_dispatch(peer->fi, UP_PEER_EV_RX_ASSOC_SETUP_REQ, m); + select_poll(); +} + +static int next_teid = 0x100; +static int next_cp_seid = 0x100; + +/* Send a PFCP Session Establishment Request, and return the created session */ +static struct up_session *session_est_tunmap(struct up_peer *peer) +{ + struct osmo_pfcp_msg *m; + + struct osmo_pfcp_ie_f_seid cp_f_seid; + + struct osmo_pfcp_ie_f_teid f_teid_access_local; + struct osmo_pfcp_ie_outer_header_creation ohc_access; + + struct osmo_pfcp_ie_f_teid f_teid_core_local; + struct osmo_pfcp_ie_outer_header_creation ohc_core; + + struct osmo_pfcp_ie_apply_action aa = {}; + + osmo_pfcp_bits_set(aa.bits, OSMO_PFCP_APPLY_ACTION_FORW, true); + + f_teid_access_local = (struct osmo_pfcp_ie_f_teid){ + .choose_flag = true, + .choose = { + .ipv4_addr = true, + }, + }; + + ohc_access = (struct osmo_pfcp_ie_outer_header_creation){ + .teid_present = true, + .teid = next_teid++, + .ip_addr = { + .v4_present = true, + .v4 = *str2addr("5.6.7.8", 0), + }, + }; + osmo_pfcp_bits_set(ohc_access.desc_bits, OSMO_PFCP_OUTER_HEADER_CREATION_GTP_U_UDP_IPV4, true); + + f_teid_core_local = (struct osmo_pfcp_ie_f_teid){ + .choose_flag = true, + .choose = { + .ipv4_addr = true, + }, + }; + + ohc_core = (struct osmo_pfcp_ie_outer_header_creation){ + .teid_present = true, + .teid = next_teid++, + .ip_addr = { + .v4_present = true, + .v4 = *str2addr("13.14.15.16", 0), + }, + }; + osmo_pfcp_bits_set(ohc_core.desc_bits, OSMO_PFCP_OUTER_HEADER_CREATION_GTP_U_UDP_IPV4, true); + + cp_f_seid = (struct osmo_pfcp_ie_f_seid){ + .seid = next_cp_seid++, + }; + osmo_pfcp_ip_addrs_set(&cp_f_seid.ip_addr, osmo_pfcp_endpoint_get_local_addr(g_upf->pfcp.ep->pfcp_ep)); + + m = new_pfcp_msg_for_osmo_upf_rx(peer, OSMO_PFCP_MSGT_SESSION_EST_REQ); + m->h.seid_present = true; + m->h.seid = 0; + /* GTP tunmap: remove header from both directions, and add header in both directions */ + m->ies.session_est_req = (struct osmo_pfcp_msg_session_est_req){ + .node_id = m->ies.session_est_req.node_id, + .cp_f_seid_present = true, + .cp_f_seid = cp_f_seid, + .create_pdr_count = 2, + .create_pdr = { + { + .pdr_id = 1, + .precedence = 255, + .pdi = { + .source_iface = OSMO_PFCP_SOURCE_IFACE_CORE, + .local_f_teid_present = true, + .local_f_teid = f_teid_core_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, + }, + { + .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, + }, + { + .far_id = 2, + .forw_params_present = true, + .forw_params = { + .destination_iface = OSMO_PFCP_DEST_IFACE_CORE, + .outer_header_creation_present = true, + .outer_header_creation = ohc_core, + }, + .apply_action = aa, + }, + }, + }; + + osmo_fsm_inst_dispatch(peer->fi, UP_PEER_EV_RX_SESSION_EST_REQ, m); + select_poll(); + + return up_session_find_by_up_seid(peer, last_up_seid); +} + +static void session_del(struct up_session *session) +{ + struct osmo_pfcp_msg *m; + + log_assert(session); + + m = new_pfcp_msg_for_osmo_upf_rx(session->up_peer, OSMO_PFCP_MSGT_SESSION_DEL_REQ); + m->h.seid_present = true; + m->h.seid = session->up_seid; + + osmo_fsm_inst_dispatch(session->fi, UP_SESSION_EV_RX_SESSION_DEL_REQ, m); + select_poll(); +} + +static void dump_state(void) +{ + struct up_peer *peer; + log("\n state:\n"); + llist_for_each_entry(peer, &g_upf->pfcp.ep->peers, entry) { + struct up_session *session; + int bkt; + log(" | peer %s %s\n", peer->fi->name, osmo_fsm_inst_state_name(peer->fi)); + hash_for_each(peer->sessions_by_up_seid, bkt, session, node_by_up_seid) { + struct up_gtp_action *a; + llist_for_each_entry(a, &session->active_gtp_actions, entry) { + if (a->kind != UP_GTP_U_TUNMAP) + continue; + log(" | session[%s]: UP-SEID 0x%"PRIx64"; chain_id access=%u core=%u;" + " local TEID access=0x%x core=0x%x\n", + osmo_fsm_inst_state_name(session->fi), + session->up_seid, + a->tunmap.access.chain_id, a->tunmap.core.chain_id, + a->tunmap.access.tun.local.teid, a->tunmap.core.tun.local.teid); + } + } + } + log("\n"); +} + +static void test_skip_used_id(void) +{ + struct up_peer *peer; + struct up_session *s1; + uint64_t s1_up_seid; + struct up_session *s2; + struct up_session *s3; + struct up_session *s4; + struct up_gtp_action *a; + + setup(__func__); + + log("PFCP Associate peer\n"); + peer = have_peer("1.2.3.4", 1234); + peer_assoc(peer); + dump_state(); + + /* Make sure to start out all IDs with 1 */ + g_upf->pfcp.ep->next_up_seid_state = 0; + g_upf->gtp.next_local_teid_state = 0; + g_upf->tunmap.next_chain_id_state = 0; + + log("set up tunmap, which assigns first UP-SEID 0x1, local-TEID 0x1 and 0x2, chain_ids 1 and 2\n"); + s1 = session_est_tunmap(peer); + dump_state(); + + log_assert(s1->up_seid == 1); + log_assert(a = llist_first_entry_or_null(&s1->active_gtp_actions, struct up_gtp_action, entry)); + log_assert(a->kind == UP_GTP_U_TUNMAP); + log_assert(a->tunmap.core.tun.local.teid == 1); + log_assert(a->tunmap.access.tun.local.teid == 2); + log_assert(a->tunmap.access.chain_id == 1); + log_assert(a->tunmap.core.chain_id == 2); + log("\n"); + + log("simulate wrapping of IDs back to 1\n"); + g_upf->pfcp.ep->next_up_seid_state = 0; + g_upf->gtp.next_local_teid_state = 0; + g_upf->tunmap.next_chain_id_state = 0; + + log("set up second tunmap, should use distinct IDs\n"); + s2 = session_est_tunmap(peer); + dump_state(); + + log_assert(s2->up_seid == 2); + log_assert(a = llist_first_entry_or_null(&s2->active_gtp_actions, struct up_gtp_action, entry)); + log_assert(a->kind == UP_GTP_U_TUNMAP); + log_assert(a->tunmap.core.tun.local.teid == 3); + log_assert(a->tunmap.access.tun.local.teid == 4); + log_assert_expect_failure(a->tunmap.access.chain_id == 3); + log_assert_expect_failure(a->tunmap.core.chain_id == 4); + log("\n"); + + log("drop first tunmap (%s)\n", s1->fi->name); + s1_up_seid = s1->up_seid; + session_del(s1); + dump_state(); + log_assert(up_session_find_by_up_seid(peer, s1_up_seid) == NULL); + log("\n"); + + log("again wrap all ID state back to 1\n"); + g_upf->pfcp.ep->next_up_seid_state = 0; + g_upf->gtp.next_local_teid_state = 0; + g_upf->tunmap.next_chain_id_state = 0; + + log("set up third tunmap, should now re-use same IDs as the first session\n"); + s3 = session_est_tunmap(peer); + dump_state(); + + log_assert(s3->up_seid == 1); + log_assert(a = llist_first_entry_or_null(&s3->active_gtp_actions, struct up_gtp_action, entry)); + log_assert(a->kind == UP_GTP_U_TUNMAP); + log_assert(a->tunmap.core.tun.local.teid == 1); + log_assert(a->tunmap.access.tun.local.teid == 2); + log_assert(a->tunmap.access.chain_id == 1); + log_assert(a->tunmap.core.chain_id == 2); + log("\n"); + + log("set up 4th tunmap; chain_id state would use 3 and 4, but they are in use, so should assign 5 and 6\n"); + s4 = session_est_tunmap(peer); + dump_state(); + + log_assert(s4->up_seid == 3); + log_assert(a = llist_first_entry_or_null(&s4->active_gtp_actions, struct up_gtp_action, entry)); + log_assert(a->kind == UP_GTP_U_TUNMAP); + log_assert(a->tunmap.core.tun.local.teid == 5); + log_assert(a->tunmap.access.tun.local.teid == 6); + log_assert_expect_failure(a->tunmap.access.chain_id == 5); + log_assert_expect_failure(a->tunmap.core.chain_id == 6); + log("\n"); + + cleanup(); +} + +static const struct log_info_cat test_default_categories[] = { + [DREF] = { + .name = "DREF", + .description = "Reference Counting", + .enabled = 1, .loglevel = LOGL_DEBUG, + .color = OSMO_LOGCOLOR_DARKGREY, + }, + [DPEER] = { + .name = "DPEER", + .description = "PFCP peer association", + .enabled = 1, .loglevel = LOGL_DEBUG, + .color = OSMO_LOGCOLOR_YELLOW, + }, + [DSESSION] = { + .name = "DSESSION", + .description = "PFCP sessions", + .enabled = 1, .loglevel = LOGL_DEBUG, + .color = OSMO_LOGCOLOR_BLUE, + }, + [DGTP] = { + .name = "DGTP", + .description = "GTP tunneling", + .enabled = 1, .loglevel = LOGL_DEBUG, + .color = OSMO_LOGCOLOR_PURPLE, + }, + [DNFT] = { + .name = "DNFT", + .description = "GTP forwarding rules via linux netfilter", + .enabled = 1, .loglevel = LOGL_DEBUG, + .color = OSMO_LOGCOLOR_PURPLE, + }, +}; + +const struct log_info log_info = { + .cat = test_default_categories, + .num_cat = ARRAY_SIZE(test_default_categories), +}; + +static struct { + bool verbose; +} cmdline_opts = { + .verbose = false, +}; + +static void print_help(const char *program) +{ + printf("Usage:\n" + " %s [-v]\n" + "Options:\n" + " -h --help show this text.\n" + " -v --verbose print source file and line numbers\n", + program + ); +} + +static void handle_options(int argc, char **argv) +{ + while (1) { + int option_index = 0, c; + static struct option long_options[] = { + {"help", 0, 0, 'h'}, + {"verbose", 1, 0, 'v'}, + {0, 0, 0, 0} + }; + + c = getopt_long(argc, argv, "hv", + long_options, &option_index); + if (c == -1) + break; + + switch (c) { + case 'h': + print_help(argv[0]); + exit(0); + case 'v': + cmdline_opts.verbose = true; + break; + default: + /* catch unknown options *as well as* missing arguments. */ + fprintf(stderr, "Error in command line options. Exiting.\n"); + exit(-1); + break; + } + } +} + +int main(int argc, char **argv) +{ + handle_options(argc, argv); + + main_ctx = talloc_named_const(NULL, 0, "main"); + + msgb_talloc_ctx_init(main_ctx, 0); + + osmo_fsm_set_dealloc_ctx(OTC_SELECT); + + osmo_init_logging2(main_ctx, &log_info); + log_set_print_category_hex(osmo_stderr_target, 0); + log_set_print_category(osmo_stderr_target, 1); + log_set_print_level(osmo_stderr_target, 1); + log_set_print_timestamp(osmo_stderr_target, 0); + log_set_print_extended_timestamp(osmo_stderr_target, 0); + log_set_all_filter(osmo_stderr_target, 1); + + if (cmdline_opts.verbose) { + log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_BASENAME); + log_set_print_filename_pos(osmo_stderr_target, LOG_FILENAME_POS_LINE_END); + log_set_use_color(osmo_stderr_target, 1); + } else { + log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE); + log_set_use_color(osmo_stderr_target, 0); + } + + osmo_fsm_log_timeouts(true); + osmo_fsm_log_addr(false); + + /* actual tests */ + test_skip_used_id(); + + log_fini(); + talloc_free(main_ctx); + return 0; +} + +/* overrides */ + +int osmo_pfcp_endpoint_tx(struct osmo_pfcp_endpoint *ep, struct osmo_pfcp_msg *m) +{ + enum osmo_pfcp_cause *cause; + + log("\n[test override] PFCP tx:\n%s\n\n", osmo_pfcp_msg_to_str_c(OTC_SELECT, m)); + + last_up_seid = 0; + + cause = osmo_pfcp_msg_cause(m); + switch (m->h.message_type) { + case OSMO_PFCP_MSGT_SESSION_EST_RESP: + if (*cause == OSMO_PFCP_CAUSE_REQUEST_ACCEPTED) { + last_up_seid = m->ies.session_est_resp.up_f_seid.seid; + log("osmo-upf created session 0x%"PRIx64"\n\n", last_up_seid); + } + break; + default: + break; + }; + osmo_pfcp_msg_free(m); + return 0; +} + +static void *fake_nft_ctx = (void *)0x1; + +struct nft_ctx *nft_ctx_new(uint32_t flags) +{ + log("[test override] %s()\n", __func__); + return fake_nft_ctx; +} + +void nft_ctx_free(struct nft_ctx *ctx) +{ + log("[test override] %s()\n", __func__); + log_assert(ctx == fake_nft_ctx); +} + +int nft_run_cmd_from_buffer(struct nft_ctx *nft, const char *buf) +{ + log("\n[test override] %s():\n%s\n", __func__, buf); + return 0; +} + +/* for deterministic recovery_time_stamp */ +time_t time(time_t *tloc) +{ + log("[test override] %s()\n", __func__); + return 0; +} diff --git a/tests/unique_ids/unique_ids_test.err b/tests/unique_ids/unique_ids_test.err new file mode 100644 index 0000000..dfd57ef --- /dev/null +++ b/tests/unique_ids/unique_ids_test.err @@ -0,0 +1,412 @@ + +===== START of test_skip_used_id +[test override] time() +[test override] time() +DLPFCP NOTICE PFCP endpoint: recovery timestamp = 0x83aa7e80 (0 seconds since UNIX epoch, which is 2208988800 seconds since NTP era 0; IETF RFC 5905) +[test override] nft_ctx_new() + +[test override] nft_run_cmd_from_buffer(): +add table inet osmo-upf { flags owner; }; + +DNFT DEBUG run nft ruleset: "add table inet osmo-upf { flags owner; };\n" +DNFT NOTICE Created nft table "osmo-upf" + +[test override] nft_run_cmd_from_buffer(): +add chain inet osmo-upf pre { type filter hook prerouting priority -300; policy accept; }; +add chain inet osmo-upf post { type filter hook postrouting priority 400; policy accept; }; +add map inet osmo-upf tunmap-pre { typeof ip daddr . @ih,32,32 : verdict; }; +add map inet osmo-upf tunmap-post { typeof meta mark : verdict; }; +add rule inet osmo-upf pre udp dport 2152 ip daddr . @ih,32,32 vmap @tunmap-pre; +add rule inet osmo-upf post meta mark vmap @tunmap-post; + +DNFT DEBUG run nft ruleset: "add chain inet osmo-upf pre { type filter hook prerouting priority -300; policy accept; };\nadd chain inet osmo-upf post { type filter hook postrouting priority 400; policy accept; };\nadd map inet osmo-upf tunmap-pre { typeof ip daddr . @ih,32,32 : verdict; };\nadd map inet osmo-upf tunmap-post { typeof meta mark : verdict; };\nadd rule inet osmo-upf pre udp dport 2152 ip daddr . @ih,32,32 vmap @tunmap-pre;\nadd rule inet osmo-upf post meta mark vmap @tunmap-post;\n" + +PFCP Associate peer +DPEER DEBUG up_peer{NOT_ASSOCIATED}: Allocated +DPEER DEBUG up_peer(1-2-3-4){NOT_ASSOCIATED}: Updated id +DPEER DEBUG up_peer(1-2-3-4){NOT_ASSOCIATED}: Received Event UP_PEER_EV_RX_ASSOC_SETUP_REQ +DPEER DEBUG up_peer(1-2-3-4){NOT_ASSOCIATED}: State change to ASSOCIATED (no timeout) +DREF INFO up_peer(1-2-3-4){ASSOCIATED}: + msg-tx: now used by 1 (msg-tx) + +[test override] PFCP tx: +PFCPv1 ASSOC_SETUP_RESP hdr={seq=0} ies={ 'Node ID'=v4:unsupported family 0 'Cause'=Request accepted (success) 'Recovery Time Stamp'=2208988800 'UP Function Features'=FTUP+BUNDL+RTTL } + +DREF INFO up_peer(1-2-3-4){ASSOCIATED}: - msg-tx: now used by 0 (-) +DPEER DEBUG up_peer(1-2-3-4){ASSOCIATED}: Received Event UP_PEER_EV_USE_COUNT_ZERO +DPEER NOTICE up_peer(1-2-3-4){ASSOCIATED}: Peer associated, Node-Id=v4:unsupported family 0. Local UP features: [FTUP+BUNDL+RTTL]; Peer CP features: [-] + + state: + | peer up_peer(1-2-3-4) ASSOCIATED + +set up tunmap, which assigns first UP-SEID 0x1, local-TEID 0x1 and 0x2, chain_ids 1 and 2 +DPEER DEBUG up_peer(1-2-3-4){ASSOCIATED}: Received Event UP_PEER_EV_RX_SESSION_EST_REQ +DSESSION DEBUG up_session(1-2-3-4){INIT}: Allocated +DSESSION DEBUG up_session(1-2-3-4){INIT}: is child of up_peer(1-2-3-4) +DSESSION INFO up_session(1-2-3-4){INIT}: Allocated new UP-SEID: 0x1 +DSESSION DEBUG up_session(1-2-3-4-0x1){INIT}: Updated id +DREF INFO up_peer(1-2-3-4){ASSOCIATED}: + msg-rx: now used by 1 (msg-rx) +DREF INFO up_session(1-2-3-4-0x1){INIT}: + msg-rx: now used by 1 (msg-rx) +DSESSION DEBUG up_session(1-2-3-4-0x1){INIT}: Received Event UP_SESSION_EV_RX_SESSION_EST_REQ +DREF DEBUG up_peer(1-2-3-4){ASSOCIATED}: + msg-tx: now used by 2 (msg-rx,msg-tx) +DREF DEBUG up_session(1-2-3-4-0x1){INIT}: + msg-tx: now used by 2 (msg-rx,msg-tx) +DSESSION INFO up_session(1-2-3-4-0x1){INIT}: Allocated new local F-TEID TEID-0x1,v4:1.1.1.1 +DSESSION INFO up_session(1-2-3-4-0x1){INIT}: New PDR-1{src:Core TEID-0x1,v4:1.1.1.1 decaps-GTP_U_UDP_IPV4} --> FAR-1{FORW dst:Access,GTP_U_UDP_IPV4,TEID:0x100,v4:5.6.7.8} +DSESSION INFO up_session(1-2-3-4-0x1){INIT}: Allocated new local F-TEID TEID-0x2,v4:1.1.1.1 +DSESSION INFO up_session(1-2-3-4-0x1){INIT}: New PDR-2{src:Access TEID-0x2,v4:1.1.1.1 decaps-GTP_U_UDP_IPV4} --> FAR-2{FORW dst:Core,GTP_U_UDP_IPV4,TEID:0x101,v4:13.14.15.16} +DSESSION DEBUG up_session(1-2-3-4-0x1){INIT}: Active PDR set: PDR-2{src:Access TEID-0x2,v4:1.1.1.1 decaps-GTP_U_UDP_IPV4} --> FAR-2{FORW dst:Core,GTP_U_UDP_IPV4,TEID:0x101,v4:13.14.15.16} +DSESSION DEBUG up_session(1-2-3-4-0x1){INIT}: Active PDR set: + PDR-1{src:Core TEID-0x1,v4:1.1.1.1 decaps-GTP_U_UDP_IPV4} --> FAR-1{FORW dst:Access,GTP_U_UDP_IPV4,TEID:0x100,v4:5.6.7.8} +DSESSION DEBUG up_session(1-2-3-4-0x1){INIT}: GTP actions: 0 previously active; want active: 1 +DSESSION DEBUG up_session(1-2-3-4-0x1){INIT}: want: GTP:tunmap GTP-access-r:5.6.7.8 TEID-access-r:0x100 GTP-access-l:1.1.1.1 TEID-access-l:0x2 GTP-core-r:13.14.15.16 TEID-core-r:0x101 GTP-core-l:1.1.1.1 TEID-core-l:0x1 PFCP-peer:1.2.3.4 SEID-l:0x1 PDR-access:2 PDR-core:1 +DSESSION DEBUG up_session(1-2-3-4-0x1){INIT}: enabling: GTP:tunmap GTP-access-r:5.6.7.8 TEID-access-r:0x100 GTP-access-l:1.1.1.1 TEID-access-l:0x2 GTP-core-r:13.14.15.16 TEID-core-r:0x101 GTP-core-l:1.1.1.1 TEID-core-l:0x1 PFCP-peer:1.2.3.4 SEID-l:0x1 PDR-access:2 PDR-core:1 + +[test override] nft_run_cmd_from_buffer(): +add chain inet osmo-upf tunmap-pre-1; +add rule inet osmo-upf tunmap-pre-1 ip daddr set 13.14.15.16 meta mark set 1 counter accept; +add chain inet osmo-upf tunmap-post-1; +add rule inet osmo-upf tunmap-post-1 ip saddr set 1.1.1.1 @ih,32,32 set 0x101 counter accept; +add element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x2 : jump tunmap-pre-1 }; +add element inet osmo-upf tunmap-post { 1 : jump tunmap-post-1 }; +add chain inet osmo-upf tunmap-pre-2; +add rule inet osmo-upf tunmap-pre-2 ip daddr set 5.6.7.8 meta mark set 2 counter accept; +add chain inet osmo-upf tunmap-post-2; +add rule inet osmo-upf tunmap-post-2 ip saddr set 1.1.1.1 @ih,32,32 set 0x100 counter accept; +add element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x1 : jump tunmap-pre-2 }; +add element inet osmo-upf tunmap-post { 2 : jump tunmap-post-2 }; + +DNFT DEBUG run nft ruleset: "add chain inet osmo-upf tunmap-pre-1;\nadd rule inet osmo-upf tunmap-pre-1 ip daddr set 13.14.15.16 meta mark set 1 counter accept;\nadd chain inet osmo-upf tunmap-post-1;\nadd rule inet osmo-upf tunmap-post-1 ip saddr set 1.1.1.1 @ih,32,32 set 0x101 counter accept;\nadd element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x2 : jump tunmap-pre-1 };\nadd element inet osmo-upf tunmap-post { 1 : jump tunmap-post-1 };\nadd chain inet osmo-upf tunmap-pre-2;\nadd rule inet osmo-upf tunmap-pre-2 ip daddr set 5.6.7.8 meta mark set 2 counter accept;\nadd chain inet osmo-upf tunmap-post-2;\nadd rule inet osmo-upf tunmap-post-2 ip saddr set 1.1.1.1 @ih,32,32 set 0x100 counter accept;\nadd element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x1 : jump tunmap-pre-2 };\nadd element inet osmo-upf tunmap-post { 2 : jump tunmap-post-2 };\n" +DGTP NOTICE GTP:tunmap GTP-access-r:5.6.7.8 TEID-access-r:0x100 GTP-access-l:1.1.1.1 TEID-access-l:0x2 GTP-core-r:13.14.15.16 TEID-core-r:0x101 GTP-core-l:1.1.1.1 TEID-core-l:0x1 PFCP-peer:1.2.3.4 SEID-l:0x1 PDR-access:2 PDR-core:1: Enabled tunmap, nft chain IDs: access--1-> <-2--core + +[test override] PFCP tx: +PFCPv1 SESSION_EST_RESP hdr={seq=0 SEID=0x100} ies={ 'Node ID'=v4:unsupported family 0 'Cause'=Request accepted (success) 'F-SEID'=0x1,v4:1.1.1.1 'Created PDR'={ { 'PDR ID'=1 'F-TEID'=TEID-0x1,v4:1.1.1.1 }, { 'PDR ID'=2 'F-TEID'=TEID-0x2,v4:1.1.1.1 } } } + +osmo-upf created session 0x1 + +DREF DEBUG up_session(1-2-3-4-0x1){INIT}: - msg-tx: now used by 1 (msg-rx) +DREF DEBUG up_peer(1-2-3-4){ASSOCIATED}: - msg-tx: now used by 1 (msg-rx) +DSESSION DEBUG up_session(1-2-3-4-0x1){INIT}: State change to ESTABLISHED (no timeout) +DSESSION NOTICE up_session(1-2-3-4-0x1){ESTABLISHED}: Session established: peer:1.2.3.4 SEID-r:0x100 SEID-l:0x1 state:ESTABLISHED PDR-active:2/2 FAR-active:2/2 GTP-active:1 +DREF INFO up_session(1-2-3-4-0x1){ESTABLISHED}: - msg-rx: now used by 0 (-) +DSESSION DEBUG up_session(1-2-3-4-0x1){ESTABLISHED}: Received Event UP_SESSION_EV_USE_COUNT_ZERO +DREF INFO up_peer(1-2-3-4){ASSOCIATED}: - msg-rx: now used by 0 (-) +DPEER DEBUG up_peer(1-2-3-4){ASSOCIATED}: Received Event UP_PEER_EV_USE_COUNT_ZERO + + state: + | peer up_peer(1-2-3-4) ASSOCIATED + | session[ESTABLISHED]: UP-SEID 0x1; chain_id access=1 core=2; local TEID access=0x2 core=0x1 + +assert(s1->up_seid == 1) +assert(a = llist_first_entry_or_null(&s1->active_gtp_actions, struct up_gtp_action, entry)) +assert(a->kind == UP_GTP_U_TUNMAP) +assert(a->tunmap.core.tun.local.teid == 1) +assert(a->tunmap.access.tun.local.teid == 2) +assert(a->tunmap.access.chain_id == 1) +assert(a->tunmap.core.chain_id == 2) + +simulate wrapping of IDs back to 1 +set up second tunmap, should use distinct IDs +DPEER DEBUG up_peer(1-2-3-4){ASSOCIATED}: Received Event UP_PEER_EV_RX_SESSION_EST_REQ +DSESSION DEBUG up_session(1-2-3-4){INIT}: Allocated +DSESSION DEBUG up_session(1-2-3-4){INIT}: is child of up_peer(1-2-3-4) +DSESSION INFO up_session(1-2-3-4){INIT}: Allocated new UP-SEID: 0x2 +DSESSION DEBUG up_session(1-2-3-4-0x2){INIT}: Updated id +DREF INFO up_peer(1-2-3-4){ASSOCIATED}: + msg-rx: now used by 1 (msg-rx) +DREF INFO up_session(1-2-3-4-0x2){INIT}: + msg-rx: now used by 1 (msg-rx) +DSESSION DEBUG up_session(1-2-3-4-0x2){INIT}: Received Event UP_SESSION_EV_RX_SESSION_EST_REQ +DREF DEBUG up_peer(1-2-3-4){ASSOCIATED}: + msg-tx: now used by 2 (msg-rx,msg-tx) +DREF DEBUG up_session(1-2-3-4-0x2){INIT}: + msg-tx: now used by 2 (msg-rx,msg-tx) +DSESSION INFO up_session(1-2-3-4-0x2){INIT}: Allocated new local F-TEID TEID-0x3,v4:1.1.1.1 +DSESSION INFO up_session(1-2-3-4-0x2){INIT}: New PDR-1{src:Core TEID-0x3,v4:1.1.1.1 decaps-GTP_U_UDP_IPV4} --> FAR-1{FORW dst:Access,GTP_U_UDP_IPV4,TEID:0x102,v4:5.6.7.8} +DSESSION INFO up_session(1-2-3-4-0x2){INIT}: Allocated new local F-TEID TEID-0x4,v4:1.1.1.1 +DSESSION INFO up_session(1-2-3-4-0x2){INIT}: New PDR-2{src:Access TEID-0x4,v4:1.1.1.1 decaps-GTP_U_UDP_IPV4} --> FAR-2{FORW dst:Core,GTP_U_UDP_IPV4,TEID:0x103,v4:13.14.15.16} +DSESSION DEBUG up_session(1-2-3-4-0x2){INIT}: Active PDR set: PDR-2{src:Access TEID-0x4,v4:1.1.1.1 decaps-GTP_U_UDP_IPV4} --> FAR-2{FORW dst:Core,GTP_U_UDP_IPV4,TEID:0x103,v4:13.14.15.16} +DSESSION DEBUG up_session(1-2-3-4-0x2){INIT}: Active PDR set: + PDR-1{src:Core TEID-0x3,v4:1.1.1.1 decaps-GTP_U_UDP_IPV4} --> FAR-1{FORW dst:Access,GTP_U_UDP_IPV4,TEID:0x102,v4:5.6.7.8} +DSESSION DEBUG up_session(1-2-3-4-0x2){INIT}: GTP actions: 0 previously active; want active: 1 +DSESSION DEBUG up_session(1-2-3-4-0x2){INIT}: want: GTP:tunmap GTP-access-r:5.6.7.8 TEID-access-r:0x102 GTP-access-l:1.1.1.1 TEID-access-l:0x4 GTP-core-r:13.14.15.16 TEID-core-r:0x103 GTP-core-l:1.1.1.1 TEID-core-l:0x3 PFCP-peer:1.2.3.4 SEID-l:0x2 PDR-access:2 PDR-core:1 +DSESSION DEBUG up_session(1-2-3-4-0x2){INIT}: enabling: GTP:tunmap GTP-access-r:5.6.7.8 TEID-access-r:0x102 GTP-access-l:1.1.1.1 TEID-access-l:0x4 GTP-core-r:13.14.15.16 TEID-core-r:0x103 GTP-core-l:1.1.1.1 TEID-core-l:0x3 PFCP-peer:1.2.3.4 SEID-l:0x2 PDR-access:2 PDR-core:1 + +[test override] nft_run_cmd_from_buffer(): +add chain inet osmo-upf tunmap-pre-1; +add rule inet osmo-upf tunmap-pre-1 ip daddr set 13.14.15.16 meta mark set 1 counter accept; +add chain inet osmo-upf tunmap-post-1; +add rule inet osmo-upf tunmap-post-1 ip saddr set 1.1.1.1 @ih,32,32 set 0x103 counter accept; +add element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x4 : jump tunmap-pre-1 }; +add element inet osmo-upf tunmap-post { 1 : jump tunmap-post-1 }; +add chain inet osmo-upf tunmap-pre-2; +add rule inet osmo-upf tunmap-pre-2 ip daddr set 5.6.7.8 meta mark set 2 counter accept; +add chain inet osmo-upf tunmap-post-2; +add rule inet osmo-upf tunmap-post-2 ip saddr set 1.1.1.1 @ih,32,32 set 0x102 counter accept; +add element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x3 : jump tunmap-pre-2 }; +add element inet osmo-upf tunmap-post { 2 : jump tunmap-post-2 }; + +DNFT DEBUG run nft ruleset: "add chain inet osmo-upf tunmap-pre-1;\nadd rule inet osmo-upf tunmap-pre-1 ip daddr set 13.14.15.16 meta mark set 1 counter accept;\nadd chain inet osmo-upf tunmap-post-1;\nadd rule inet osmo-upf tunmap-post-1 ip saddr set 1.1.1.1 @ih,32,32 set 0x103 counter accept;\nadd element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x4 : jump tunmap-pre-1 };\nadd element inet osmo-upf tunmap-post { 1 : jump tunmap-post-1 };\nadd chain inet osmo-upf tunmap-pre-2;\nadd rule inet osmo-upf tunmap-pre-2 ip daddr set 5.6.7.8 meta mark set 2 counter accept;\nadd chain inet osmo-upf tunmap-post-2;\nadd rule inet osmo-upf tunmap-post-2 ip saddr set 1.1.1.1 @ih,32,32 set 0x102 counter accept;\nadd element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x3 : jump tunmap-pre-2 };\nadd element inet osmo-upf tunmap-post { 2 : jump tunmap-post-2 };\n" +DGTP NOTICE GTP:tunmap GTP-access-r:5.6.7.8 TEID-access-r:0x102 GTP-access-l:1.1.1.1 TEID-access-l:0x4 GTP-core-r:13.14.15.16 TEID-core-r:0x103 GTP-core-l:1.1.1.1 TEID-core-l:0x3 PFCP-peer:1.2.3.4 SEID-l:0x2 PDR-access:2 PDR-core:1: Enabled tunmap, nft chain IDs: access--1-> <-2--core + +[test override] PFCP tx: +PFCPv1 SESSION_EST_RESP hdr={seq=0 SEID=0x101} ies={ 'Node ID'=v4:unsupported family 0 'Cause'=Request accepted (success) 'F-SEID'=0x2,v4:1.1.1.1 'Created PDR'={ { 'PDR ID'=1 'F-TEID'=TEID-0x3,v4:1.1.1.1 }, { 'PDR ID'=2 'F-TEID'=TEID-0x4,v4:1.1.1.1 } } } + +osmo-upf created session 0x2 + +DREF DEBUG up_session(1-2-3-4-0x2){INIT}: - msg-tx: now used by 1 (msg-rx) +DREF DEBUG up_peer(1-2-3-4){ASSOCIATED}: - msg-tx: now used by 1 (msg-rx) +DSESSION DEBUG up_session(1-2-3-4-0x2){INIT}: State change to ESTABLISHED (no timeout) +DSESSION NOTICE up_session(1-2-3-4-0x2){ESTABLISHED}: Session established: peer:1.2.3.4 SEID-r:0x101 SEID-l:0x2 state:ESTABLISHED PDR-active:2/2 FAR-active:2/2 GTP-active:1 +DREF INFO up_session(1-2-3-4-0x2){ESTABLISHED}: - msg-rx: now used by 0 (-) +DSESSION DEBUG up_session(1-2-3-4-0x2){ESTABLISHED}: Received Event UP_SESSION_EV_USE_COUNT_ZERO +DREF INFO up_peer(1-2-3-4){ASSOCIATED}: - msg-rx: now used by 0 (-) +DPEER DEBUG up_peer(1-2-3-4){ASSOCIATED}: Received Event UP_PEER_EV_USE_COUNT_ZERO + + state: + | peer up_peer(1-2-3-4) ASSOCIATED + | session[ESTABLISHED]: UP-SEID 0x1; chain_id access=1 core=2; local TEID access=0x2 core=0x1 + | session[ESTABLISHED]: UP-SEID 0x2; chain_id access=1 core=2; local TEID access=0x4 core=0x3 + +assert(s2->up_seid == 2) +assert(a = llist_first_entry_or_null(&s2->active_gtp_actions, struct up_gtp_action, entry)) +assert(a->kind == UP_GTP_U_TUNMAP) +assert(a->tunmap.core.tun.local.teid == 3) +assert(a->tunmap.access.tun.local.teid == 4) +assert(a->tunmap.access.chain_id == 3) <-- EXPECTED TO FAIL (known error) +assert(a->tunmap.core.chain_id == 4) <-- EXPECTED TO FAIL (known error) + +drop first tunmap (up_session(1-2-3-4-0x1)) +assert(session) +DSESSION DEBUG up_session(1-2-3-4-0x1){ESTABLISHED}: Received Event UP_SESSION_EV_RX_SESSION_DEL_REQ +DREF INFO up_peer(1-2-3-4){ASSOCIATED}: + msg-tx: now used by 1 (msg-tx) +DREF INFO up_session(1-2-3-4-0x1){ESTABLISHED}: + msg-tx: now used by 1 (msg-tx) + +[test override] PFCP tx: +PFCPv1 SESSION_DEL_RESP hdr={seq=0 SEID=0x100} ies={ 'Cause'=Request accepted (success) } + +DREF INFO up_session(1-2-3-4-0x1){ESTABLISHED}: - msg-tx: now used by 0 (-) +DSESSION DEBUG up_session(1-2-3-4-0x1){ESTABLISHED}: Received Event UP_SESSION_EV_USE_COUNT_ZERO +DREF INFO up_peer(1-2-3-4){ASSOCIATED}: - msg-tx: now used by 0 (-) +DPEER DEBUG up_peer(1-2-3-4){ASSOCIATED}: Received Event UP_PEER_EV_USE_COUNT_ZERO +DSESSION NOTICE up_session(1-2-3-4-0x1){ESTABLISHED}: Session releasing: peer:1.2.3.4 SEID-r:0x100 SEID-l:0x1 state:ESTABLISHED PDR-active:2/2 FAR-active:2/2 GTP-active:1 + +[test override] nft_run_cmd_from_buffer(): +delete element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x2 }; +delete element inet osmo-upf tunmap-post { 1 }; +delete chain inet osmo-upf tunmap-pre-1; +delete chain inet osmo-upf tunmap-post-1; +delete element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x1 }; +delete element inet osmo-upf tunmap-post { 2 }; +delete chain inet osmo-upf tunmap-pre-2; +delete chain inet osmo-upf tunmap-post-2; + +DNFT DEBUG run nft ruleset: "delete element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x2 };\ndelete element inet osmo-upf tunmap-post { 1 };\ndelete chain inet osmo-upf tunmap-pre-1;\ndelete chain inet osmo-upf tunmap-post-1;\ndelete element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x1 };\ndelete element inet osmo-upf tunmap-post { 2 };\ndelete chain inet osmo-upf tunmap-pre-2;\ndelete chain inet osmo-upf tunmap-post-2;\n" +DGTP NOTICE GTP:tunmap GTP-access-r:5.6.7.8 TEID-access-r:0x100 GTP-access-l:1.1.1.1 TEID-access-l:0x2 GTP-core-r:13.14.15.16 TEID-core-r:0x101 GTP-core-l:1.1.1.1 TEID-core-l:0x1 PFCP-peer:1.2.3.4 SEID-l:0x1 PDR-access:2 PDR-core:1: Disabled tunmap, nft chain IDs: access--1-> <-2--core +DSESSION DEBUG up_session(1-2-3-4-0x1){ESTABLISHED}: State change to WAIT_USE_COUNT (no timeout) +DSESSION DEBUG up_session(1-2-3-4-0x1){WAIT_USE_COUNT}: GTP actions: 0 previously active; want active: 0 +DSESSION DEBUG up_session(1-2-3-4-0x1){WAIT_USE_COUNT}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DSESSION DEBUG up_session(1-2-3-4-0x1){WAIT_USE_COUNT}: Removing from parent up_peer(1-2-3-4) +DSESSION DEBUG up_session(1-2-3-4-0x1){WAIT_USE_COUNT}: GTP actions: 0 previously active; want active: 0 +DSESSION DEBUG up_session(1-2-3-4-0x1){WAIT_USE_COUNT}: Freeing instance +DSESSION DEBUG up_session(1-2-3-4-0x1){WAIT_USE_COUNT}: Deallocated +DPEER DEBUG up_peer(1-2-3-4){ASSOCIATED}: Received Event UP_PEER_EV_SESSION_TERM + + state: + | peer up_peer(1-2-3-4) ASSOCIATED + | session[ESTABLISHED]: UP-SEID 0x2; chain_id access=1 core=2; local TEID access=0x4 core=0x3 + +assert(up_session_find_by_up_seid(peer, s1_up_seid) == NULL) + +again wrap all ID state back to 1 +set up third tunmap, should now re-use same IDs as the first session +DPEER DEBUG up_peer(1-2-3-4){ASSOCIATED}: Received Event UP_PEER_EV_RX_SESSION_EST_REQ +DSESSION DEBUG up_session(1-2-3-4){INIT}: Allocated +DSESSION DEBUG up_session(1-2-3-4){INIT}: is child of up_peer(1-2-3-4) +DSESSION INFO up_session(1-2-3-4){INIT}: Allocated new UP-SEID: 0x1 +DSESSION DEBUG up_session(1-2-3-4-0x1){INIT}: Updated id +DREF INFO up_peer(1-2-3-4){ASSOCIATED}: + msg-rx: now used by 1 (msg-rx) +DREF INFO up_session(1-2-3-4-0x1){INIT}: + msg-rx: now used by 1 (msg-rx) +DSESSION DEBUG up_session(1-2-3-4-0x1){INIT}: Received Event UP_SESSION_EV_RX_SESSION_EST_REQ +DREF DEBUG up_peer(1-2-3-4){ASSOCIATED}: + msg-tx: now used by 2 (msg-rx,msg-tx) +DREF DEBUG up_session(1-2-3-4-0x1){INIT}: + msg-tx: now used by 2 (msg-rx,msg-tx) +DSESSION INFO up_session(1-2-3-4-0x1){INIT}: Allocated new local F-TEID TEID-0x1,v4:1.1.1.1 +DSESSION INFO up_session(1-2-3-4-0x1){INIT}: New PDR-1{src:Core TEID-0x1,v4:1.1.1.1 decaps-GTP_U_UDP_IPV4} --> FAR-1{FORW dst:Access,GTP_U_UDP_IPV4,TEID:0x104,v4:5.6.7.8} +DSESSION INFO up_session(1-2-3-4-0x1){INIT}: Allocated new local F-TEID TEID-0x2,v4:1.1.1.1 +DSESSION INFO up_session(1-2-3-4-0x1){INIT}: New PDR-2{src:Access TEID-0x2,v4:1.1.1.1 decaps-GTP_U_UDP_IPV4} --> FAR-2{FORW dst:Core,GTP_U_UDP_IPV4,TEID:0x105,v4:13.14.15.16} +DSESSION DEBUG up_session(1-2-3-4-0x1){INIT}: Active PDR set: PDR-2{src:Access TEID-0x2,v4:1.1.1.1 decaps-GTP_U_UDP_IPV4} --> FAR-2{FORW dst:Core,GTP_U_UDP_IPV4,TEID:0x105,v4:13.14.15.16} +DSESSION DEBUG up_session(1-2-3-4-0x1){INIT}: Active PDR set: + PDR-1{src:Core TEID-0x1,v4:1.1.1.1 decaps-GTP_U_UDP_IPV4} --> FAR-1{FORW dst:Access,GTP_U_UDP_IPV4,TEID:0x104,v4:5.6.7.8} +DSESSION DEBUG up_session(1-2-3-4-0x1){INIT}: GTP actions: 0 previously active; want active: 1 +DSESSION DEBUG up_session(1-2-3-4-0x1){INIT}: want: GTP:tunmap GTP-access-r:5.6.7.8 TEID-access-r:0x104 GTP-access-l:1.1.1.1 TEID-access-l:0x2 GTP-core-r:13.14.15.16 TEID-core-r:0x105 GTP-core-l:1.1.1.1 TEID-core-l:0x1 PFCP-peer:1.2.3.4 SEID-l:0x1 PDR-access:2 PDR-core:1 +DSESSION DEBUG up_session(1-2-3-4-0x1){INIT}: enabling: GTP:tunmap GTP-access-r:5.6.7.8 TEID-access-r:0x104 GTP-access-l:1.1.1.1 TEID-access-l:0x2 GTP-core-r:13.14.15.16 TEID-core-r:0x105 GTP-core-l:1.1.1.1 TEID-core-l:0x1 PFCP-peer:1.2.3.4 SEID-l:0x1 PDR-access:2 PDR-core:1 + +[test override] nft_run_cmd_from_buffer(): +add chain inet osmo-upf tunmap-pre-1; +add rule inet osmo-upf tunmap-pre-1 ip daddr set 13.14.15.16 meta mark set 1 counter accept; +add chain inet osmo-upf tunmap-post-1; +add rule inet osmo-upf tunmap-post-1 ip saddr set 1.1.1.1 @ih,32,32 set 0x105 counter accept; +add element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x2 : jump tunmap-pre-1 }; +add element inet osmo-upf tunmap-post { 1 : jump tunmap-post-1 }; +add chain inet osmo-upf tunmap-pre-2; +add rule inet osmo-upf tunmap-pre-2 ip daddr set 5.6.7.8 meta mark set 2 counter accept; +add chain inet osmo-upf tunmap-post-2; +add rule inet osmo-upf tunmap-post-2 ip saddr set 1.1.1.1 @ih,32,32 set 0x104 counter accept; +add element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x1 : jump tunmap-pre-2 }; +add element inet osmo-upf tunmap-post { 2 : jump tunmap-post-2 }; + +DNFT DEBUG run nft ruleset: "add chain inet osmo-upf tunmap-pre-1;\nadd rule inet osmo-upf tunmap-pre-1 ip daddr set 13.14.15.16 meta mark set 1 counter accept;\nadd chain inet osmo-upf tunmap-post-1;\nadd rule inet osmo-upf tunmap-post-1 ip saddr set 1.1.1.1 @ih,32,32 set 0x105 counter accept;\nadd element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x2 : jump tunmap-pre-1 };\nadd element inet osmo-upf tunmap-post { 1 : jump tunmap-post-1 };\nadd chain inet osmo-upf tunmap-pre-2;\nadd rule inet osmo-upf tunmap-pre-2 ip daddr set 5.6.7.8 meta mark set 2 counter accept;\nadd chain inet osmo-upf tunmap-post-2;\nadd rule inet osmo-upf tunmap-post-2 ip saddr set 1.1.1.1 @ih,32,32 set 0x104 counter accept;\nadd element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x1 : jump tunmap-pre-2 };\nadd element inet osmo-upf tunmap-post { 2 : jump tunmap-post-2 };\n" +DGTP NOTICE GTP:tunmap GTP-access-r:5.6.7.8 TEID-access-r:0x104 GTP-access-l:1.1.1.1 TEID-access-l:0x2 GTP-core-r:13.14.15.16 TEID-core-r:0x105 GTP-core-l:1.1.1.1 TEID-core-l:0x1 PFCP-peer:1.2.3.4 SEID-l:0x1 PDR-access:2 PDR-core:1: Enabled tunmap, nft chain IDs: access--1-> <-2--core + +[test override] PFCP tx: +PFCPv1 SESSION_EST_RESP hdr={seq=0 SEID=0x102} ies={ 'Node ID'=v4:unsupported family 0 'Cause'=Request accepted (success) 'F-SEID'=0x1,v4:1.1.1.1 'Created PDR'={ { 'PDR ID'=1 'F-TEID'=TEID-0x1,v4:1.1.1.1 }, { 'PDR ID'=2 'F-TEID'=TEID-0x2,v4:1.1.1.1 } } } + +osmo-upf created session 0x1 + +DREF DEBUG up_session(1-2-3-4-0x1){INIT}: - msg-tx: now used by 1 (msg-rx) +DREF DEBUG up_peer(1-2-3-4){ASSOCIATED}: - msg-tx: now used by 1 (msg-rx) +DSESSION DEBUG up_session(1-2-3-4-0x1){INIT}: State change to ESTABLISHED (no timeout) +DSESSION NOTICE up_session(1-2-3-4-0x1){ESTABLISHED}: Session established: peer:1.2.3.4 SEID-r:0x102 SEID-l:0x1 state:ESTABLISHED PDR-active:2/2 FAR-active:2/2 GTP-active:1 +DREF INFO up_session(1-2-3-4-0x1){ESTABLISHED}: - msg-rx: now used by 0 (-) +DSESSION DEBUG up_session(1-2-3-4-0x1){ESTABLISHED}: Received Event UP_SESSION_EV_USE_COUNT_ZERO +DREF INFO up_peer(1-2-3-4){ASSOCIATED}: - msg-rx: now used by 0 (-) +DPEER DEBUG up_peer(1-2-3-4){ASSOCIATED}: Received Event UP_PEER_EV_USE_COUNT_ZERO + + state: + | peer up_peer(1-2-3-4) ASSOCIATED + | session[ESTABLISHED]: UP-SEID 0x1; chain_id access=1 core=2; local TEID access=0x2 core=0x1 + | session[ESTABLISHED]: UP-SEID 0x2; chain_id access=1 core=2; local TEID access=0x4 core=0x3 + +assert(s3->up_seid == 1) +assert(a = llist_first_entry_or_null(&s3->active_gtp_actions, struct up_gtp_action, entry)) +assert(a->kind == UP_GTP_U_TUNMAP) +assert(a->tunmap.core.tun.local.teid == 1) +assert(a->tunmap.access.tun.local.teid == 2) +assert(a->tunmap.access.chain_id == 1) +assert(a->tunmap.core.chain_id == 2) + +set up 4th tunmap; chain_id state would use 3 and 4, but they are in use, so should assign 5 and 6 +DPEER DEBUG up_peer(1-2-3-4){ASSOCIATED}: Received Event UP_PEER_EV_RX_SESSION_EST_REQ +DSESSION DEBUG up_session(1-2-3-4){INIT}: Allocated +DSESSION DEBUG up_session(1-2-3-4){INIT}: is child of up_peer(1-2-3-4) +DSESSION INFO up_session(1-2-3-4){INIT}: Allocated new UP-SEID: 0x3 +DSESSION DEBUG up_session(1-2-3-4-0x3){INIT}: Updated id +DREF INFO up_peer(1-2-3-4){ASSOCIATED}: + msg-rx: now used by 1 (msg-rx) +DREF INFO up_session(1-2-3-4-0x3){INIT}: + msg-rx: now used by 1 (msg-rx) +DSESSION DEBUG up_session(1-2-3-4-0x3){INIT}: Received Event UP_SESSION_EV_RX_SESSION_EST_REQ +DREF DEBUG up_peer(1-2-3-4){ASSOCIATED}: + msg-tx: now used by 2 (msg-rx,msg-tx) +DREF DEBUG up_session(1-2-3-4-0x3){INIT}: + msg-tx: now used by 2 (msg-rx,msg-tx) +DSESSION INFO up_session(1-2-3-4-0x3){INIT}: Allocated new local F-TEID TEID-0x5,v4:1.1.1.1 +DSESSION INFO up_session(1-2-3-4-0x3){INIT}: New PDR-1{src:Core TEID-0x5,v4:1.1.1.1 decaps-GTP_U_UDP_IPV4} --> FAR-1{FORW dst:Access,GTP_U_UDP_IPV4,TEID:0x106,v4:5.6.7.8} +DSESSION INFO up_session(1-2-3-4-0x3){INIT}: Allocated new local F-TEID TEID-0x6,v4:1.1.1.1 +DSESSION INFO up_session(1-2-3-4-0x3){INIT}: New PDR-2{src:Access TEID-0x6,v4:1.1.1.1 decaps-GTP_U_UDP_IPV4} --> FAR-2{FORW dst:Core,GTP_U_UDP_IPV4,TEID:0x107,v4:13.14.15.16} +DSESSION DEBUG up_session(1-2-3-4-0x3){INIT}: Active PDR set: PDR-2{src:Access TEID-0x6,v4:1.1.1.1 decaps-GTP_U_UDP_IPV4} --> FAR-2{FORW dst:Core,GTP_U_UDP_IPV4,TEID:0x107,v4:13.14.15.16} +DSESSION DEBUG up_session(1-2-3-4-0x3){INIT}: Active PDR set: + PDR-1{src:Core TEID-0x5,v4:1.1.1.1 decaps-GTP_U_UDP_IPV4} --> FAR-1{FORW dst:Access,GTP_U_UDP_IPV4,TEID:0x106,v4:5.6.7.8} +DSESSION DEBUG up_session(1-2-3-4-0x3){INIT}: GTP actions: 0 previously active; want active: 1 +DSESSION DEBUG up_session(1-2-3-4-0x3){INIT}: want: GTP:tunmap GTP-access-r:5.6.7.8 TEID-access-r:0x106 GTP-access-l:1.1.1.1 TEID-access-l:0x6 GTP-core-r:13.14.15.16 TEID-core-r:0x107 GTP-core-l:1.1.1.1 TEID-core-l:0x5 PFCP-peer:1.2.3.4 SEID-l:0x3 PDR-access:2 PDR-core:1 +DSESSION DEBUG up_session(1-2-3-4-0x3){INIT}: enabling: GTP:tunmap GTP-access-r:5.6.7.8 TEID-access-r:0x106 GTP-access-l:1.1.1.1 TEID-access-l:0x6 GTP-core-r:13.14.15.16 TEID-core-r:0x107 GTP-core-l:1.1.1.1 TEID-core-l:0x5 PFCP-peer:1.2.3.4 SEID-l:0x3 PDR-access:2 PDR-core:1 + +[test override] nft_run_cmd_from_buffer(): +add chain inet osmo-upf tunmap-pre-3; +add rule inet osmo-upf tunmap-pre-3 ip daddr set 13.14.15.16 meta mark set 3 counter accept; +add chain inet osmo-upf tunmap-post-3; +add rule inet osmo-upf tunmap-post-3 ip saddr set 1.1.1.1 @ih,32,32 set 0x107 counter accept; +add element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x6 : jump tunmap-pre-3 }; +add element inet osmo-upf tunmap-post { 3 : jump tunmap-post-3 }; +add chain inet osmo-upf tunmap-pre-4; +add rule inet osmo-upf tunmap-pre-4 ip daddr set 5.6.7.8 meta mark set 4 counter accept; +add chain inet osmo-upf tunmap-post-4; +add rule inet osmo-upf tunmap-post-4 ip saddr set 1.1.1.1 @ih,32,32 set 0x106 counter accept; +add element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x5 : jump tunmap-pre-4 }; +add element inet osmo-upf tunmap-post { 4 : jump tunmap-post-4 }; + +DNFT DEBUG run nft ruleset: "add chain inet osmo-upf tunmap-pre-3;\nadd rule inet osmo-upf tunmap-pre-3 ip daddr set 13.14.15.16 meta mark set 3 counter accept;\nadd chain inet osmo-upf tunmap-post-3;\nadd rule inet osmo-upf tunmap-post-3 ip saddr set 1.1.1.1 @ih,32,32 set 0x107 counter accept;\nadd element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x6 : jump tunmap-pre-3 };\nadd element inet osmo-upf tunmap-post { 3 : jump tunmap-post-3 };\nadd chain inet osmo-upf tunmap-pre-4;\nadd rule inet osmo-upf tunmap-pre-4 ip daddr set 5.6.7.8 meta mark set 4 counter accept;\nadd chain inet osmo-upf tunmap-post-4;\nadd rule inet osmo-upf tunmap-post-4 ip saddr set 1.1.1.1 @ih,32,32 set 0x106 counter accept;\nadd element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x5 : jump tunmap-pre-4 };\nadd element inet osmo-upf tunmap-post { 4 : jump tunmap-post-4 };\n" +DGTP NOTICE GTP:tunmap GTP-access-r:5.6.7.8 TEID-access-r:0x106 GTP-access-l:1.1.1.1 TEID-access-l:0x6 GTP-core-r:13.14.15.16 TEID-core-r:0x107 GTP-core-l:1.1.1.1 TEID-core-l:0x5 PFCP-peer:1.2.3.4 SEID-l:0x3 PDR-access:2 PDR-core:1: Enabled tunmap, nft chain IDs: access--3-> <-4--core + +[test override] PFCP tx: +PFCPv1 SESSION_EST_RESP hdr={seq=0 SEID=0x103} ies={ 'Node ID'=v4:unsupported family 0 'Cause'=Request accepted (success) 'F-SEID'=0x3,v4:1.1.1.1 'Created PDR'={ { 'PDR ID'=1 'F-TEID'=TEID-0x5,v4:1.1.1.1 }, { 'PDR ID'=2 'F-TEID'=TEID-0x6,v4:1.1.1.1 } } } + +osmo-upf created session 0x3 + +DREF DEBUG up_session(1-2-3-4-0x3){INIT}: - msg-tx: now used by 1 (msg-rx) +DREF DEBUG up_peer(1-2-3-4){ASSOCIATED}: - msg-tx: now used by 1 (msg-rx) +DSESSION DEBUG up_session(1-2-3-4-0x3){INIT}: State change to ESTABLISHED (no timeout) +DSESSION NOTICE up_session(1-2-3-4-0x3){ESTABLISHED}: Session established: peer:1.2.3.4 SEID-r:0x103 SEID-l:0x3 state:ESTABLISHED PDR-active:2/2 FAR-active:2/2 GTP-active:1 +DREF INFO up_session(1-2-3-4-0x3){ESTABLISHED}: - msg-rx: now used by 0 (-) +DSESSION DEBUG up_session(1-2-3-4-0x3){ESTABLISHED}: Received Event UP_SESSION_EV_USE_COUNT_ZERO +DREF INFO up_peer(1-2-3-4){ASSOCIATED}: - msg-rx: now used by 0 (-) +DPEER DEBUG up_peer(1-2-3-4){ASSOCIATED}: Received Event UP_PEER_EV_USE_COUNT_ZERO + + state: + | peer up_peer(1-2-3-4) ASSOCIATED + | session[ESTABLISHED]: UP-SEID 0x3; chain_id access=3 core=4; local TEID access=0x6 core=0x5 + | session[ESTABLISHED]: UP-SEID 0x1; chain_id access=1 core=2; local TEID access=0x2 core=0x1 + | session[ESTABLISHED]: UP-SEID 0x2; chain_id access=1 core=2; local TEID access=0x4 core=0x3 + +assert(s4->up_seid == 3) +assert(a = llist_first_entry_or_null(&s4->active_gtp_actions, struct up_gtp_action, entry)) +assert(a->kind == UP_GTP_U_TUNMAP) +assert(a->tunmap.core.tun.local.teid == 5) +assert(a->tunmap.access.tun.local.teid == 6) +assert(a->tunmap.access.chain_id == 5) <-- EXPECTED TO FAIL (known error) +assert(a->tunmap.core.chain_id == 6) <-- EXPECTED TO FAIL (known error) + +DPEER DEBUG up_peer(1-2-3-4){ASSOCIATED}: Terminating (cause = OSMO_FSM_TERM_REGULAR) +DSESSION DEBUG up_session(1-2-3-4-0x3){ESTABLISHED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DSESSION DEBUG up_session(1-2-3-4-0x3){ESTABLISHED}: Removing from parent up_peer(1-2-3-4) +DSESSION DEBUG up_session(1-2-3-4-0x3){ESTABLISHED}: GTP actions: 1 previously active; want active: 0 +DSESSION DEBUG up_session(1-2-3-4-0x3){ESTABLISHED}: active: GTP:tunmap GTP-access-r:5.6.7.8 TEID-access-r:0x106 GTP-access-l:1.1.1.1 TEID-access-l:0x6 GTP-core-r:13.14.15.16 TEID-core-r:0x107 GTP-core-l:1.1.1.1 TEID-core-l:0x5 PFCP-peer:1.2.3.4 SEID-l:0x3 PDR-access:2 PDR-core:1 +DSESSION DEBUG up_session(1-2-3-4-0x3){ESTABLISHED}: disabling: GTP:tunmap GTP-access-r:5.6.7.8 TEID-access-r:0x106 GTP-access-l:1.1.1.1 TEID-access-l:0x6 GTP-core-r:13.14.15.16 TEID-core-r:0x107 GTP-core-l:1.1.1.1 TEID-core-l:0x5 PFCP-peer:1.2.3.4 SEID-l:0x3 PDR-access:2 PDR-core:1 + +[test override] nft_run_cmd_from_buffer(): +delete element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x6 }; +delete element inet osmo-upf tunmap-post { 3 }; +delete chain inet osmo-upf tunmap-pre-3; +delete chain inet osmo-upf tunmap-post-3; +delete element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x5 }; +delete element inet osmo-upf tunmap-post { 4 }; +delete chain inet osmo-upf tunmap-pre-4; +delete chain inet osmo-upf tunmap-post-4; + +DNFT DEBUG run nft ruleset: "delete element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x6 };\ndelete element inet osmo-upf tunmap-post { 3 };\ndelete chain inet osmo-upf tunmap-pre-3;\ndelete chain inet osmo-upf tunmap-post-3;\ndelete element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x5 };\ndelete element inet osmo-upf tunmap-post { 4 };\ndelete chain inet osmo-upf tunmap-pre-4;\ndelete chain inet osmo-upf tunmap-post-4;\n" +DGTP NOTICE GTP:tunmap GTP-access-r:5.6.7.8 TEID-access-r:0x106 GTP-access-l:1.1.1.1 TEID-access-l:0x6 GTP-core-r:13.14.15.16 TEID-core-r:0x107 GTP-core-l:1.1.1.1 TEID-core-l:0x5 PFCP-peer:1.2.3.4 SEID-l:0x3 PDR-access:2 PDR-core:1: Disabled tunmap, nft chain IDs: access--3-> <-4--core +DSESSION DEBUG up_session(1-2-3-4-0x3){ESTABLISHED}: Freeing instance +DSESSION DEBUG up_session(1-2-3-4-0x3){ESTABLISHED}: Deallocated +DSESSION DEBUG up_session(1-2-3-4-0x1){ESTABLISHED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DSESSION DEBUG up_session(1-2-3-4-0x1){ESTABLISHED}: Removing from parent up_peer(1-2-3-4) +DSESSION DEBUG up_session(1-2-3-4-0x1){ESTABLISHED}: GTP actions: 1 previously active; want active: 0 +DSESSION DEBUG up_session(1-2-3-4-0x1){ESTABLISHED}: active: GTP:tunmap GTP-access-r:5.6.7.8 TEID-access-r:0x104 GTP-access-l:1.1.1.1 TEID-access-l:0x2 GTP-core-r:13.14.15.16 TEID-core-r:0x105 GTP-core-l:1.1.1.1 TEID-core-l:0x1 PFCP-peer:1.2.3.4 SEID-l:0x1 PDR-access:2 PDR-core:1 +DSESSION DEBUG up_session(1-2-3-4-0x1){ESTABLISHED}: disabling: GTP:tunmap GTP-access-r:5.6.7.8 TEID-access-r:0x104 GTP-access-l:1.1.1.1 TEID-access-l:0x2 GTP-core-r:13.14.15.16 TEID-core-r:0x105 GTP-core-l:1.1.1.1 TEID-core-l:0x1 PFCP-peer:1.2.3.4 SEID-l:0x1 PDR-access:2 PDR-core:1 + +[test override] nft_run_cmd_from_buffer(): +delete element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x2 }; +delete element inet osmo-upf tunmap-post { 1 }; +delete chain inet osmo-upf tunmap-pre-1; +delete chain inet osmo-upf tunmap-post-1; +delete element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x1 }; +delete element inet osmo-upf tunmap-post { 2 }; +delete chain inet osmo-upf tunmap-pre-2; +delete chain inet osmo-upf tunmap-post-2; + +DNFT DEBUG run nft ruleset: "delete element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x2 };\ndelete element inet osmo-upf tunmap-post { 1 };\ndelete chain inet osmo-upf tunmap-pre-1;\ndelete chain inet osmo-upf tunmap-post-1;\ndelete element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x1 };\ndelete element inet osmo-upf tunmap-post { 2 };\ndelete chain inet osmo-upf tunmap-pre-2;\ndelete chain inet osmo-upf tunmap-post-2;\n" +DGTP NOTICE GTP:tunmap GTP-access-r:5.6.7.8 TEID-access-r:0x104 GTP-access-l:1.1.1.1 TEID-access-l:0x2 GTP-core-r:13.14.15.16 TEID-core-r:0x105 GTP-core-l:1.1.1.1 TEID-core-l:0x1 PFCP-peer:1.2.3.4 SEID-l:0x1 PDR-access:2 PDR-core:1: Disabled tunmap, nft chain IDs: access--1-> <-2--core +DSESSION DEBUG up_session(1-2-3-4-0x1){ESTABLISHED}: Freeing instance +DSESSION DEBUG up_session(1-2-3-4-0x1){ESTABLISHED}: Deallocated +DSESSION DEBUG up_session(1-2-3-4-0x2){ESTABLISHED}: Terminating (cause = OSMO_FSM_TERM_PARENT) +DSESSION DEBUG up_session(1-2-3-4-0x2){ESTABLISHED}: Removing from parent up_peer(1-2-3-4) +DSESSION DEBUG up_session(1-2-3-4-0x2){ESTABLISHED}: GTP actions: 1 previously active; want active: 0 +DSESSION DEBUG up_session(1-2-3-4-0x2){ESTABLISHED}: active: GTP:tunmap GTP-access-r:5.6.7.8 TEID-access-r:0x102 GTP-access-l:1.1.1.1 TEID-access-l:0x4 GTP-core-r:13.14.15.16 TEID-core-r:0x103 GTP-core-l:1.1.1.1 TEID-core-l:0x3 PFCP-peer:1.2.3.4 SEID-l:0x2 PDR-access:2 PDR-core:1 +DSESSION DEBUG up_session(1-2-3-4-0x2){ESTABLISHED}: disabling: GTP:tunmap GTP-access-r:5.6.7.8 TEID-access-r:0x102 GTP-access-l:1.1.1.1 TEID-access-l:0x4 GTP-core-r:13.14.15.16 TEID-core-r:0x103 GTP-core-l:1.1.1.1 TEID-core-l:0x3 PFCP-peer:1.2.3.4 SEID-l:0x2 PDR-access:2 PDR-core:1 + +[test override] nft_run_cmd_from_buffer(): +delete element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x4 }; +delete element inet osmo-upf tunmap-post { 1 }; +delete chain inet osmo-upf tunmap-pre-1; +delete chain inet osmo-upf tunmap-post-1; +delete element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x3 }; +delete element inet osmo-upf tunmap-post { 2 }; +delete chain inet osmo-upf tunmap-pre-2; +delete chain inet osmo-upf tunmap-post-2; + +DNFT DEBUG run nft ruleset: "delete element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x4 };\ndelete element inet osmo-upf tunmap-post { 1 };\ndelete chain inet osmo-upf tunmap-pre-1;\ndelete chain inet osmo-upf tunmap-post-1;\ndelete element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x3 };\ndelete element inet osmo-upf tunmap-post { 2 };\ndelete chain inet osmo-upf tunmap-pre-2;\ndelete chain inet osmo-upf tunmap-post-2;\n" +DGTP NOTICE GTP:tunmap GTP-access-r:5.6.7.8 TEID-access-r:0x102 GTP-access-l:1.1.1.1 TEID-access-l:0x4 GTP-core-r:13.14.15.16 TEID-core-r:0x103 GTP-core-l:1.1.1.1 TEID-core-l:0x3 PFCP-peer:1.2.3.4 SEID-l:0x2 PDR-access:2 PDR-core:1: Disabled tunmap, nft chain IDs: access--1-> <-2--core +DSESSION DEBUG up_session(1-2-3-4-0x2){ESTABLISHED}: Freeing instance +DSESSION DEBUG up_session(1-2-3-4-0x2){ESTABLISHED}: Deallocated +DPEER NOTICE up_peer(1-2-3-4){ASSOCIATED}: Peer removed +DPEER DEBUG up_peer(1-2-3-4){ASSOCIATED}: Freeing instance +DPEER DEBUG up_peer(1-2-3-4){ASSOCIATED}: Deallocated +[test override] nft_ctx_free() +assert(ctx == fake_nft_ctx) + +===== END of test_skip_used_id diff --git a/tests/unique_ids/unique_ids_test.ok b/tests/unique_ids/unique_ids_test.ok new file mode 100644 index 0000000..e69de29