23 Commits

Author SHA1 Message Date
Neels Hofmeyr
c7df62a281 gtp probe 2024-03-18 08:08:34 +01:00
Neels Hofmeyr
d9e653c46b wip 2024-03-18 04:46:43 +01:00
Neels Hofmeyr
de1569327f gtp probe 2024-03-18 02:56:59 +01:00
Neels Janosch Hofmeyr
a71e1d7c3e gtp probe checksum
Change-Id: I48d9cec67f1851e00ab95da67dbc64cbf19a35a6
2024-03-18 02:38:07 +01:00
Neels Hofmeyr
0e9724e0df gtp-probe fu 2024-03-16 07:02:43 +01:00
Neels Janosch Hofmeyr
048fee5059 wip
Change-Id: Ic2c9c483cd106fdb32f02b234103565ccffbb9f5
2024-03-16 05:16:39 +01:00
Neels Janosch Hofmeyr
1e4b5aae65 shorten nft rulesets: 'tunmap-pre' -> 'mpre'
Change-Id: Ie72fbab7a1b2455e24c80e93197399d1452264bd
2024-03-16 05:16:39 +01:00
Neels Janosch Hofmeyr
a3ee024150 perf
Change-Id: I162456349287ec0e0ff3e4ff802d7df76a756b17
2024-03-16 05:16:39 +01:00
Neels Janosch Hofmeyr
97cf37ee7a gtp probe
Change-Id: Iaf1255379808135970b788361185cce2a7f2912c
2024-03-16 05:16:39 +01:00
Neels Janosch Hofmeyr
2a5ee44e06 pfcp_tool.h
Change-Id: I351cd4bb6130c80da63cfb76b670c86d9d5e1d07
2024-03-16 05:16:39 +01:00
Neels Janosch Hofmeyr
3e2cbe57d4 wip
Change-Id: I27d6af9e0a44262edd66f457c91702ec83bf2fcc
2024-03-16 05:16:39 +01:00
Neels Janosch Hofmeyr
5db4af220a pfcp_tool.h
Change-Id: Ibca7bb2bb760263bdde726378bd16d629de2fe4e
2024-03-16 05:16:39 +01:00
Neels Janosch Hofmeyr
2aab3f62dd gtp_probe
Change-Id: I1be96bdc05c0e4298b0815a9feb263d488054113
2024-03-16 05:16:39 +01:00
Neels Janosch Hofmeyr
2ddb739ee3 fix two null deref on incoming data
Change-Id: I134ceb583deb12fa8318b2140ed04bf9b6fba4e7
2024-03-16 05:16:39 +01:00
Neels Janosch Hofmeyr
077eba97ab gtp_probe
Change-Id: I051f5e56c73593090c783e522b1fbdd17ed6b059
2024-03-16 05:16:39 +01:00
Neels Janosch Hofmeyr
340c1abd44 tunend.vty
Change-Id: I5cfe47abfd3c9a13f6191922f31b39e5c562a1a8
2024-03-16 05:16:39 +01:00
Neels Janosch Hofmeyr
9d56082698 perf fu
Change-Id: Ie59b53b88a77a2e6535887ca7ae697cca7d01d27
2024-03-16 05:16:39 +01:00
Neels Janosch Hofmeyr
44a574b6b6 nftq
Change-Id: Ib0a8e86b29bab1559d94fc55a89daa00ec670318
2024-03-16 05:16:39 +01:00
Neels Janosch Hofmeyr
b85a53ccf8 pfcp_tool: add 'date'
Allow scripts to output timestamps to easily measure how long certain
actions took to complete. Related: measuring PFCP session management
performance bounds of osmo-upf.

Change-Id: I0486cc92ea298bb9926a0e5c26da17ba5970a72c
2024-03-16 05:16:39 +01:00
Neels Janosch Hofmeyr
50e70f61bb pfcp tool less batch size
Change-Id: I4956d290f8ea929b6ad6301b6f61c3b979a11093
2024-03-16 05:16:39 +01:00
Neels Janosch Hofmeyr
61379149d3 perf
Change-Id: I39d12c0ae6d9be18178e13a55ea8b70869265c84
2024-03-16 05:16:39 +01:00
Neels Janosch Hofmeyr
bbe0cfc8c0 contrib/perf/bpftrace.txt: separate id lookups from nft
Change-Id: Ic821b3a2375f91d5ad1becde8239481e11be5f5b
2024-03-16 05:16:39 +01:00
Neels Janosch Hofmeyr
f85f180aa6 bpftrace probing
Change-Id: I2717b736e23552bffe1492604cbd073f22977c84
2024-03-16 05:16:39 +01:00
25 changed files with 1893 additions and 206 deletions

View File

@@ -198,6 +198,7 @@ AC_OUTPUT(
include/Makefile
include/osmocom/Makefile
include/osmocom/upf/Makefile
include/osmocom/pfcptool/Makefile
src/Makefile
src/osmo-upf/Makefile
src/osmo-pfcp-tool/Makefile

View File

@@ -0,0 +1,8 @@
log stderr
logging level set-all error
timer pfcp x23 5
timer pfcp x24 5000
local-addr 127.0.0.2
listen

26
contrib/perf/osmo-upf.cfg Normal file
View File

@@ -0,0 +1,26 @@
log stderr
logging filter all 1
logging color 1
logging print level 1
logging print category 1
logging print category-hex 0
logging print file basename last
#logging print timestamp date
logging level set-all info
line vty
bind 127.0.0.1
ctrl
bind 127.0.0.1
# PFCP retransmissions
timer pfcp x23 0
# PFCP response timeout
timer pfcp x24 0
pfcp
local-addr 127.0.0.1
tunmap
table-name osmo-upf
tunend
dev create apn23 192.168.2.52

7
contrib/perf/tunend.vty Normal file
View File

@@ -0,0 +1,7 @@
pfcp-peer 127.0.0.1
tx assoc-setup-req
sleep 1
date
n 10000 session create tunend
wait responses
date

34
contrib/perf/tunmap.vty Normal file
View File

@@ -0,0 +1,34 @@
pfcp-peer 127.0.0.1
tx assoc-setup-req
sleep 1
date
n 1000 session create tunmap
wait responses
date
n 1000 session create tunmap
wait responses
date
n 1000 session create tunmap
wait responses
date
n 1000 session create tunmap
wait responses
date
n 1000 session create tunmap
wait responses
date
n 1000 session create tunmap
wait responses
date
n 1000 session create tunmap
wait responses
date
n 1000 session create tunmap
wait responses
date
n 1000 session create tunmap
wait responses
date
n 1000 session create tunmap
wait responses
date

97
contrib/perf/upf-1.bt Normal file
View File

@@ -0,0 +1,97 @@
uprobe:/usr/local/lib/libosmo-pfcp.so.0.1.0:osmo_pfcp_fd_cb {
@pfcp_rx_start_at = nsecs;
}
uprobe:/usr/local/bin/osmo-upf:up_endpoint_rx_cb {
@pfcp_handle_start_at = nsecs;
}
uprobe:/usr/local/lib/libnftables.so.1.1.0:nft_run_cmd_from_buffer {
@nft_run_cmd_from_buffer_start_at = nsecs;
@nft_run_cmd_from_buffer_us_val = (uint64)0;
}
uretprobe:/usr/local/lib/libnftables.so.1.1.0:nft_run_cmd_from_buffer {
@nft_run_cmd_from_buffer_us_val = (nsecs - @nft_run_cmd_from_buffer_start_at)/1000;
@nft_run_cmd_from_buffer_us = hist(@nft_run_cmd_from_buffer_us_val);
}
uprobe:/usr/local/lib/libosmo-pfcp.so.0.1.0:osmo_pfcp_fd_write_cb {
@pfcp_write_cb_start_at = nsecs;
@pfcp_write_cb_us_val = (uint64)0;
}
uretprobe:/usr/local/lib/libosmo-pfcp.so.0.1.0:osmo_pfcp_fd_write_cb {
@pfcp_write_cb_us_val = (nsecs - @pfcp_write_cb_start_at) / 1000;
@pfcp_write_cb_us = hist(@pfcp_write_cb_us_val);
}
uprobe:/usr/local/lib/libosmo-pfcp.so.0.1.0:osmo_pfcp_endpoint_tx_data_no_logging {
@pfcp_tx_start_at = nsecs;
@pfcp_tx_us_val = (uint64)0;
}
uretprobe:/usr/local/lib/libosmo-pfcp.so.0.1.0:osmo_pfcp_endpoint_tx_data_no_logging {
@pfcp_tx_us_val = (nsecs - @pfcp_tx_start_at) / 1000;
@pfcp_tx_us = hist(@pfcp_tx_us_val);
}
uretprobe:/usr/local/lib/libosmo-pfcp.so.0.1.0:osmo_pfcp_fd_cb {
@pfcp_rx_count = @pfcp_rx_count + 1;
$pfcp_rx_end_at = nsecs;
if (@pfcp_handle_start_at > @pfcp_rx_start_at) {
$pfcp_rx_total_us_val = ($pfcp_rx_end_at - @pfcp_rx_start_at) / 1000;
$pfcp_decode_us_val = (@pfcp_handle_start_at - @pfcp_rx_start_at) / 1000;
@pfcp_decode_us = hist($pfcp_decode_us_val);
$pfcp_decode_percent_val = 100 * $pfcp_decode_us_val / $pfcp_rx_total_us_val;
@pfcp_decode_percent = lhist($pfcp_decode_percent_val, 0, 120, 10);
$pfcp_handle_us_val = ($pfcp_rx_end_at - @pfcp_handle_start_at) / 1000;
@pfcp_handle_us = hist($pfcp_handle_us_val);
$pfcp_handle_percent_val = 100 * $pfcp_handle_us_val / $pfcp_rx_total_us_val;
@pfcp_handle_percent = lhist($pfcp_handle_percent_val, 0, 120, 10);
if (@nft_run_cmd_from_buffer_start_at > @pfcp_rx_start_at && @nft_run_cmd_from_buffer_us_val) {
$nft_run_cmd_from_buffer_percent_val = 100 * @nft_run_cmd_from_buffer_us_val / $pfcp_rx_total_us_val;
@nft_run_cmd_from_buffer_percent = lhist($nft_run_cmd_from_buffer_percent_val, 0, 100, 10);
}
if (@pfcp_tx_start_at > @pfcp_rx_start_at && @pfcp_tx_us_val) {
$pfcp_tx_percent_val = 100 * @pfcp_tx_us_val / $pfcp_rx_total_us_val;
@pfcp_tx_percent = lhist($pfcp_tx_percent_val, 0, 120, 10);
}
if (@pfcp_write_cb_start_at > @pfcp_rx_start_at && @pfcp_write_cb_us_val) {
$pfcp_write_cb_percent_val = 100 * @pfcp_write_cb_us_val / $pfcp_rx_total_us_val;
@pfcp_write_cb_percent = lhist($pfcp_write_cb_percent_val, 0, 120, 10);
}
}
}
interval:s:1 {
$pfcp_rx_per_s_val = @pfcp_rx_count;
@pfcp_rx_count = 0;
@pfcp_rx_per_s = hist($pfcp_rx_per_s_val);
}
interval:s:10 {
printf("==========================================================");
time("%Y-%m-%d %H:%M:%S\n");
print(@pfcp_decode_us);
print(@pfcp_handle_us);
print(@nft_run_cmd_from_buffer_us);
print(@pfcp_tx_us);
print(@pfcp_write_cb_us);
print(@pfcp_decode_percent);
print(@pfcp_handle_percent);
print(@nft_run_cmd_from_buffer_percent);
print(@pfcp_tx_percent);
print(@pfcp_write_cb_percent);
print(@pfcp_rx_per_s);
}

44
contrib/perf/upf-2.bt Normal file
View File

@@ -0,0 +1,44 @@
BEGIN {
@poll__last_nsecs = nsecs;
}
tracepoint:syscalls:sys_enter_poll /comm == "osmo-upf"/ {
$elapsed = (nsecs - @poll__last_nsecs)/1000000;
@poll__last_nsecs = nsecs;
@poll__ms = hist($elapsed);
}
uprobe:/usr/local/bin/osmo-upf:up_gtp_action_enable {
@up_gtp_action_enable__start = nsecs;
}
uprobe:/usr/local/lib/libnftables.so.1.1.0:nft_run_cmd_from_buffer {
$up_gtp_action_enable__duration = (nsecs - @up_gtp_action_enable__start)/1000;
@up_gtp_action_enable__us = hist($up_gtp_action_enable__duration);
@nft_run_cmd_from_buffer__start = nsecs;
}
uretprobe:/usr/local/lib/libnftables.so.1.1.0:nft_run_cmd_from_buffer {
$nft_run_cmd_from_buffer__duration = (nsecs - @nft_run_cmd_from_buffer__start)/1000000;
@nft_run_cmd_from_buffer__ms = hist($nft_run_cmd_from_buffer__duration);
}
uprobe:/usr/local/lib/libosmocore.so.20.0.0:logp2 {
@logp2__start = nsecs;
}
uretprobe:/usr/local/lib/libosmocore.so.20.0.0:logp2 {
$logp2__duration = (nsecs - @logp2__start)/1000;
@logp2__us = hist($logp2__duration);
}
interval:s:10 {
printf("==========================================================");
time("%Y-%m-%d %H:%M:%S\n");
print(@poll__ms);
print(@logp2__us);
print(@up_gtp_action_enable__us);
print(@nft_run_cmd_from_buffer__ms);
}

View File

@@ -1,3 +1,4 @@
SUBDIRS = \
upf \
pfcptool \
$(NULL)

View File

@@ -0,0 +1,4 @@
noinst_HEADERS = \
gtp_probe.h \
pfcp_tool.h \
$(NULL)

View File

@@ -0,0 +1,33 @@
#pragma once
#include <osmocom/core/sockaddr_str.h>
#include <osmocom/core/select.h>
#include <osmocom/core/socket.h>
struct pfcp_tool_gtp_tun;
struct gtp_probe_target {
struct osmo_sockaddr_str cfg;
struct osmo_sockaddr addr;
struct osmo_fd ofd;
};
struct gtp_probe_state {
struct gtp_probe_target ip_target;
struct gtp_probe_target gtp_target;
};
int gtp_probe_target_bind(struct gtp_probe_state *s, struct gtp_probe_target *t);
int gtp_probe_bind_ip_target(struct gtp_probe_state *state);
int gtp_probe_bind_gtp_target(struct gtp_probe_state *state);
int gtp_probe_run_tunend(void *ctx,
struct gtp_probe_state *s, struct pfcp_tool_gtp_tun *inject_gtp,
struct osmo_sockaddr_str *ue_ip,
struct gtp_probe_target *expect_rx_on_ip);
extern unsigned int g_gtp_probes_submitted;
extern unsigned int g_gtp_probes_pending;
extern unsigned int g_gtp_probes_successful;

View File

@@ -32,6 +32,7 @@
#include <osmocom/pfcp/pfcp_msg.h>
#include <osmocom/upf/up_gtp_action.h>
#include <osmocom/pfcptool/gtp_probe.h>
struct osmo_tdef;
struct ctrl_handle;
@@ -48,6 +49,7 @@ struct pfcp_tool_peer {
uint64_t next_seid_state;
/* list of struct pfcp_tool_session */
struct llist_head sessions;
};
@@ -57,6 +59,7 @@ struct pfcp_tool_gtp_tun_ep {
};
struct pfcp_tool_gtp_tun {
uint16_t local_pdr_id;
struct pfcp_tool_gtp_tun_ep local;
struct pfcp_tool_gtp_tun_ep remote;
};
@@ -100,6 +103,16 @@ struct g_pfcp_tool {
struct osmo_pfcp_endpoint *ep;
struct llist_head peers;
struct {
struct {
struct pfcp_tool_gtp_tun_ep remote;
} access;
} gtp_state;
uint32_t next_ue_addr_state;
struct gtp_probe_state gtp_probe;
};
extern struct g_pfcp_tool *g_pfcp_tool;
@@ -108,7 +121,7 @@ void g_pfcp_tool_alloc(void *ctx);
void pfcp_tool_vty_init_cfg();
void pfcp_tool_vty_init_cmds();
int pfcp_tool_mainloop();
int pfcp_tool_mainloop(int poll);
struct pfcp_tool_peer *pfcp_tool_peer_find_or_create(const struct osmo_sockaddr *remote_addr);
struct pfcp_tool_session *pfcp_tool_session_find_or_create(struct pfcp_tool_peer *peer, uint64_t cp_seid,
@@ -117,3 +130,6 @@ void pfcp_tool_rx_msg(struct osmo_pfcp_endpoint *ep, struct osmo_pfcp_msg *m, st
int peer_tx(struct pfcp_tool_peer *peer, struct osmo_pfcp_msg *m);
uint64_t peer_new_seid(struct pfcp_tool_peer *peer);
uint32_t pfcp_tool_new_teid(void);
int pfcp_tool_next_ue_addr(struct osmo_sockaddr_str *dst);

View File

@@ -44,6 +44,7 @@ struct nft_ctx;
#define PORT_GTP1_U 2152
extern struct osmo_tdef_group g_upf_tdef_groups[];
extern struct osmo_tdef g_upf_nft_tdefs[];
struct pfcp_vty_cfg {
char *local_addr;

View File

@@ -49,3 +49,6 @@ char *upf_nft_tunmap_get_ruleset_str(void *ctx, struct upf_tunmap *tunmap);
char *upf_nft_tunmap_get_ruleset_del_str(void *ctx, struct upf_tunmap *tunmap);
int upf_nft_tunmap_create(struct upf_tunmap *tunmap);
int upf_nft_tunmap_delete(struct upf_tunmap *tunmap);
char *upf_nft_tunmap_get_ruleset_dump_all(void *ctx);
char *upf_nft_tunmap_get_ruleset_dump(void *ctx, const char *countername, uint32_t chain_id);

View File

@@ -22,10 +22,6 @@ AM_LDFLAGS = \
$(COVERAGE_LDFLAGS) \
$(NULL)
noinst_HEADERS = \
pfcp_tool.h \
$(NULL)
bin_PROGRAMS = \
osmo-pfcp-tool \
$(NULL)
@@ -34,4 +30,6 @@ osmo_pfcp_tool_SOURCES = \
osmo_pfcp_tool_main.c \
pfcp_tool.c \
pfcp_tool_vty.c \
gtp_probe.c \
checksum.c \
$(NULL)

View File

@@ -0,0 +1,211 @@
/*
*
* INET An implementation of the TCP/IP protocol suite for the LINUX
* operating system. INET is implemented using the BSD Socket
* interface as the means of communication with the user level.
*
* IP/TCP/UDP checksumming routines
*
* Authors: Jorge Cwik, <jorge@laser.satlink.net>
* Arnt Gulbrandsen, <agulbra@nvg.unit.no>
* Tom May, <ftom@netcom.com>
* Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de>
* Lots of code moved from tcp.c and ip.c; see those files
* for more names.
*
* 03/02/96 Jes Sorensen, Andreas Schwab, Roman Hodek:
* Fixed some nasty bugs, causing some horrible crashes.
* A: At some points, the sum (%0) was used as
* length-counter instead of the length counter
* (%1). Thanks to Roman Hodek for pointing this out.
* B: GCC seems to mess up if one uses too many
* data-registers to hold input values and one tries to
* specify d0 and d1 as scratch registers. Letting gcc
* choose these registers itself solves the problem.
*
* 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.
*/
/* Revised by Kenneth Albanowski for m68knommu. Basic problem: unaligned access
kills, so most of the assembly has to go. */
#if defined(__FreeBSD__)
#define _KERNEL /* needed on FreeBSD 10.x for s6_addr32 */
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/endian.h>
#endif
#include "checksum.h"
#include <arpa/inet.h>
static inline unsigned short from32to16(unsigned int x)
{
/* add up 16-bit and 16-bit for 16+c bit */
x = (x & 0xffff) + (x >> 16);
/* add up carry.. */
x = (x & 0xffff) + (x >> 16);
return x;
}
static unsigned int do_csum(const unsigned char *buff, int len)
{
int odd;
unsigned int result = 0;
if (len <= 0)
goto out;
odd = 1 & (unsigned long) buff;
if (odd) {
#if BYTE_ORDER == LITTLE_ENDIAN
result += (*buff << 8);
#else
result = *buff;
#endif
len--;
buff++;
}
if (len >= 2) {
if (2 & (unsigned long) buff) {
result += *(unsigned short *) buff;
len -= 2;
buff += 2;
}
if (len >= 4) {
const unsigned char *end = buff + ((unsigned)len & ~3);
unsigned int carry = 0;
do {
unsigned int w = *(unsigned int *) buff;
buff += 4;
result += carry;
result += w;
carry = (w > result);
} while (buff < end);
result += carry;
result = (result & 0xffff) + (result >> 16);
}
if (len & 2) {
result += *(unsigned short *) buff;
buff += 2;
}
}
if (len & 1)
#if BYTE_ORDER == LITTLE_ENDIAN
result += *buff;
#else
result += (*buff << 8);
#endif
result = from32to16(result);
if (odd)
result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
out:
return result;
}
/*
* This is a version of ip_compute_csum() optimized for IP headers,
* which always checksum on 4 octet boundaries.
*/
uint16_t ip_fast_csum(const void *iph, unsigned int ihl)
{
return (uint16_t)~do_csum(iph, ihl*4);
}
/*
* computes the checksum of a memory block at buff, length len,
* and adds in "sum" (32-bit)
*
* returns a 32-bit number suitable for feeding into itself
* or csum_tcpudp_magic
*
* this function must be called with even lengths, except
* for the last fragment, which may be odd
*
* it's best to have buff aligned on a 32-bit boundary
*/
uint32_t csum_partial(const void *buff, int len, uint32_t wsum)
{
unsigned int sum = (unsigned int)wsum;
unsigned int result = do_csum(buff, len);
/* add in old sum, and carry.. */
result += sum;
if (sum > result)
result += 1;
return (uint32_t)result;
}
/*
* this routine is used for miscellaneous IP-like checksums, mainly
* in icmp.c
*/
uint16_t ip_compute_csum(const void *buff, int len)
{
return (uint16_t)~do_csum(buff, len);
}
uint16_t csum_ipv6_magic(const struct in6_addr *saddr,
const struct in6_addr *daddr,
uint32_t len, uint8_t proto, uint32_t csum)
{
int carry;
uint32_t ulen;
uint32_t uproto;
uint32_t sum = (uint32_t)csum;
sum += (uint32_t)saddr->s6_addr32[0];
carry = (sum < (uint32_t)saddr->s6_addr32[0]);
sum += carry;
sum += (uint32_t)saddr->s6_addr32[1];
carry = (sum < (uint32_t)saddr->s6_addr32[1]);
sum += carry;
sum += (uint32_t)saddr->s6_addr32[2];
carry = (sum < (uint32_t)saddr->s6_addr32[2]);
sum += carry;
sum += (uint32_t)saddr->s6_addr32[3];
carry = (sum < (uint32_t)saddr->s6_addr32[3]);
sum += carry;
sum += (uint32_t)daddr->s6_addr32[0];
carry = (sum < (uint32_t)daddr->s6_addr32[0]);
sum += carry;
sum += (uint32_t)daddr->s6_addr32[1];
carry = (sum < (uint32_t)daddr->s6_addr32[1]);
sum += carry;
sum += (uint32_t)daddr->s6_addr32[2];
carry = (sum < (uint32_t)daddr->s6_addr32[2]);
sum += carry;
sum += (uint32_t)daddr->s6_addr32[3];
carry = (sum < (uint32_t)daddr->s6_addr32[3]);
sum += carry;
ulen = (uint32_t)htonl((uint32_t) len);
sum += ulen;
carry = (sum < ulen);
sum += carry;
uproto = (uint32_t)htonl(proto);
sum += uproto;
carry = (sum < uproto);
sum += carry;
return csum_fold((uint32_t)sum);
}
/* fold a partial checksum */
uint16_t csum_fold(uint32_t csum)
{
uint32_t sum = (uint32_t)csum;
sum = (sum & 0xffff) + (sum >> 16);
sum = (sum & 0xffff) + (sum >> 16);
return (uint16_t)~sum;
}

View File

@@ -0,0 +1,13 @@
#pragma once
#include <stdint.h>
#include <netinet/in.h>
uint16_t ip_fast_csum(const void *iph, unsigned int ihl);
uint32_t csum_partial(const void *buff, int len, uint32_t wsum);
uint16_t ip_compute_csum(const void *buff, int len);
uint16_t csum_ipv6_magic(const struct in6_addr *saddr,
const struct in6_addr *daddr,
uint32_t len, uint8_t proto, uint32_t csum);
uint16_t csum_fold(uint32_t csum);

View File

@@ -0,0 +1,285 @@
/*
* (C) 2024 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 <netinet/ip.h>
#include <netinet/udp.h>
#include <osmocom/core/logging.h>
#include <osmocom/pfcptool/gtp_probe.h>
#include <osmocom/pfcptool/pfcp_tool.h>
#include "checksum.h"
void gtp_probe_target_close(struct gtp_probe_target *t)
{
if (t->ofd.fd > 0) {
osmo_fd_unregister(&t->ofd);
close(t->ofd.fd);
}
t->ofd.fd = -1;
t->addr = (struct osmo_sockaddr){};
}
LLIST_HEAD(g_expect_probes);
unsigned int g_gtp_probes_submitted = 0;
unsigned int g_gtp_probes_pending = 0;
unsigned int g_gtp_probes_successful = 0;
struct expect_probe {
struct llist_head entry;
struct osmo_sockaddr from;
uint8_t payload[8];
size_t payload_len;
};
static int gtp_probe_cb(struct osmo_fd *ofd, unsigned int what)
{
int rc;
struct gtp_probe_state *s = ofd->data;
struct osmo_sockaddr remote;
socklen_t remote_len = sizeof(remote);
struct osmo_sockaddr_str remote_str;
char strbuf[64];
uint8_t rxbuf[2048];
size_t rxlen = 0;
if (!(what & OSMO_FD_READ))
return 0;
rc = recvfrom(ofd->fd, rxbuf, sizeof(rxbuf), 0, (struct sockaddr *)&remote, &remote_len);
if (rc <= 0 || rc > sizeof(rxbuf)) {
fprintf(stderr, "problem receiving on UDP probe: rc %d > sizeof(rxbuf) %zu\n", rc, sizeof(rxbuf));
return -EIO;
}
rxlen = rc;
osmo_sockaddr_str_from_sockaddr(&remote_str, &remote.u.sas);
if (ofd->priv_nr)
osmo_escape_cstr_buf(strbuf, sizeof(strbuf), (char *)rxbuf, rxlen);
else
osmo_hexdump_buf(strbuf, sizeof(strbuf), rxbuf, rc, NULL, false);
struct expect_probe *p;
bool expected = false;
llist_for_each_entry (p, &g_expect_probes, entry) {
if (rxlen != p->payload_len)
continue;
if (memcmp(rxbuf, p->payload, p->payload_len))
continue;
if (osmo_sockaddr_cmp(&remote, &p->from))
continue;
expected = true;
llist_del(&p->entry);
g_gtp_probes_pending--;
g_gtp_probes_successful++;
talloc_free(p);
break;
}
LOGP(DLGLOBAL, LOGL_NOTICE,
"RX %s probe: " OSMO_SOCKADDR_STR_FMT " -> " OSMO_SOCKADDR_STR_FMT
" '%s' (%u submitted, %u successful, %u pending)\n",
expected ? "expected" : "UNEXPECTED",
OSMO_SOCKADDR_STR_FMT_ARGS(&remote_str),
OSMO_SOCKADDR_STR_FMT_ARGS(&s->ip_target.cfg),
strbuf,
g_gtp_probes_submitted,
g_gtp_probes_successful,
g_gtp_probes_pending);
return 0;
}
int gtp_probe_target_bind(struct gtp_probe_state *s, struct gtp_probe_target *t)
{
int rc;
/* close the existing socket, if any */
gtp_probe_target_close(t);
/* create the new socket, binding to configured local address */
t->ofd.data = s;
t->ofd.cb = gtp_probe_cb;
osmo_sockaddr_str_to_sockaddr(&t->cfg, &t->addr.u.sas);
rc = osmo_sock_init_osa_ofd(&t->ofd, SOCK_DGRAM, IPPROTO_UDP, &t->addr, NULL, OSMO_SOCK_F_BIND);
if (rc < 0) {
t->addr = (struct osmo_sockaddr){};
return rc;
}
LOGP(DLGLOBAL, LOGL_NOTICE, "Bound probe port: " OSMO_SOCKADDR_STR_FMT "\n",
OSMO_SOCKADDR_STR_FMT_ARGS(&t->cfg));
return 0;
}
/* According to 3GPP TS 29.060. */
struct gtp1u_hdr {
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
uint8_t pn:1, s:1, e:1, spare:1, pt:1, version:3;
#else
uint8_t version:3, pt:1, spare:1, e:1, s:1, pn:1;
#endif
uint8_t type;
uint16_t length;
uint32_t tei;
};
struct gtp_pdu {
struct gtp1u_hdr gtp;
struct iphdr ip;
struct udphdr udp;
char data[1024];
} __attribute__ ((packed));
int gtp_probe_run_tunend(void *ctx,
struct gtp_probe_state *s, struct pfcp_tool_gtp_tun *inject_gtp,
struct osmo_sockaddr_str *ue_ip,
struct gtp_probe_target *expect_rx_on_ip)
{
int rc;
/* remote-GTP this session's ACCESS side gtp_probe UDP
* |--------UDP/GTP---->|--------------------------->[...]--->|
* | |
* inject | expect UDP
* from | at the ip_target
* remote-GTP-IP:2152 to UPF's F-TEID
*/
//struct osmo_sockaddr_str *remote_gtp = &inject_gtp->remote.addr;
struct osmo_sockaddr_str upf_gtp = inject_gtp->local.addr;
upf_gtp.port = 2152;
struct osmo_sockaddr sendto_addr;
uint32_t upf_rx_teid = inject_gtp->local.teid;
struct osmo_sockaddr_str *payload_dst = &expect_rx_on_ip->cfg;
struct osmo_sockaddr_str payload_src = *ue_ip;
payload_src.port = payload_dst->port;
static uint16_t ip_id = 1;
struct gtp_pdu pdu = {
.gtp = {
.pn = 0,
.s = 0,
.e = 0,
.spare = 0,
.pt = 1,
.version = 1,
.type = 0xff, /* G-PDU */
.length = 0, /* filled in later */
.tei = htonl(upf_rx_teid),
},
.ip = {
.ihl = 5,
.version = 4,
.id = htons(ip_id++),
.frag_off = htons(0x4000),
.ttl = 64,
.protocol = IPPROTO_UDP,
},
.udp = {
.source = htons(payload_src.port),
.dest = htons(payload_dst->port),
.check = 0, // TODO
},
.data = "hello!",
};
size_t data_len = strlen(pdu.data) + 1;
uint16_t *id = (void *)pdu.data;
static uint16_t next_id = 0;
*id = next_id++;
data_len = 2;
size_t udp_len = sizeof(pdu.udp) + data_len;
size_t ip_len = sizeof(pdu.ip) + udp_len;
size_t gtp_len = sizeof(pdu.gtp) + ip_len;
uint32_t i32;
pdu.gtp.length = htons(gtp_len);
pdu.ip.tot_len = htons(ip_len);
pdu.udp.len = htons(udp_len);
g_gtp_probes_submitted++;
rc = osmo_sockaddr_str_to_32(&payload_src, &i32);
if (rc) {
LOGP(DLGLOBAL, LOGL_ERROR, "invalid payload source address: " OSMO_SOCKADDR_STR_FMT "\n",
OSMO_SOCKADDR_STR_FMT_ARGS(&payload_src));
return rc;
}
pdu.ip.saddr = i32;
rc = osmo_sockaddr_str_to_32(payload_dst, &i32);
if (rc) {
LOGP(DLGLOBAL, LOGL_ERROR, "invalid payload destination address: " OSMO_SOCKADDR_STR_FMT "\n",
OSMO_SOCKADDR_STR_FMT_ARGS(payload_dst));
return rc;
}
pdu.ip.daddr = i32;
#if 0
/* Skip GTP tunnel for debugging */
upf_gtp = *payload_dst;
#endif
rc = osmo_sockaddr_str_to_sockaddr(&upf_gtp, &sendto_addr.u.sas);
if (rc) {
LOGP(DLGLOBAL, LOGL_ERROR, "invalid UPF GTP address: " OSMO_SOCKADDR_STR_FMT "\n",
OSMO_SOCKADDR_STR_FMT_ARGS(&upf_gtp));
return rc;
}
pdu.ip.check = ip_fast_csum(&pdu.ip, pdu.ip.ihl);
LOGP(DLGLOBAL, LOGL_INFO, "GTP-probe sending: " OSMO_SOCKADDR_STR_FMT " -> " OSMO_SOCKADDR_STR_FMT ":TEID-0x%x:"
" payload: UDP " OSMO_SOCKADDR_STR_FMT " -> " OSMO_SOCKADDR_STR_FMT " (now %u probes pending)\n",
OSMO_SOCKADDR_STR_FMT_ARGS(&s->gtp_target.cfg),
OSMO_SOCKADDR_STR_FMT_ARGS(&upf_gtp),
upf_rx_teid,
OSMO_SOCKADDR_STR_FMT_ARGS(&payload_src),
OSMO_SOCKADDR_STR_FMT_ARGS(payload_dst),
g_gtp_probes_pending + 1);
/* add g_expect_probes entry */
struct expect_probe *p = talloc_zero(ctx, struct expect_probe);
osmo_sockaddr_str_to_osa(&payload_src, &p->from);
p->payload_len = data_len;
memcpy(p->payload, pdu.data, data_len);
llist_add_tail(&p->entry, &g_expect_probes);
g_gtp_probes_pending++;
// FIXME: allow more than just one gtp_target, and figure out here which one to use from remote_gtp above.
rc = sendto(s->gtp_target.ofd.fd, (void *)&pdu, gtp_len, 0,
&sendto_addr.u.sa, sizeof(sendto_addr));
if (rc != gtp_len) {
LOGP(DLGLOBAL, LOGL_ERROR, "%s.sendto(%s) failed: rc = %d != length %zu; errno = %d %s\n",
osmo_sock_get_name(OTC_SELECT, s->gtp_target.ofd.fd),
osmo_sockaddr_to_str_c(OTC_SELECT, &sendto_addr), rc, gtp_len,
errno, strerror(errno));
llist_del(&p->entry);
g_gtp_probes_pending--;
talloc_free(p);
return -EIO;
}
return 0;
}

View File

@@ -42,7 +42,7 @@
#include <osmocom/pfcp/pfcp_endpoint.h>
#include "pfcp_tool.h"
#include <osmocom/pfcptool/pfcp_tool.h>
#define _GNU_SOURCE
#include <getopt.h>
@@ -226,14 +226,15 @@ const struct log_info log_info = {
.num_cat = ARRAY_SIZE(pfcp_tool_default_categories),
};
int pfcp_tool_mainloop()
int pfcp_tool_mainloop(int poll)
{
int rc;
log_reset_context();
osmo_select_main_ctx(0);
rc = osmo_select_main_ctx(poll);
/* If the user hits Ctrl-C the third time, just terminate immediately. */
if (quit >= 3)
return 1;
return -1;
/* Has SIGTERM been received (and not yet been handled)? */
if (quit && !osmo_select_shutdown_requested()) {
@@ -243,7 +244,7 @@ int pfcp_tool_mainloop()
osmo_select_shutdown_request();
/* continue the main select loop until all write queues are serviced. */
}
return 0;
return rc;
}
int main(int argc, char **argv)
@@ -326,7 +327,7 @@ int main(int argc, char **argv)
}
}
pfcp_tool_mainloop();
pfcp_tool_mainloop(1);
pfcp_tool_vty_init_cmds();
@@ -341,14 +342,14 @@ int main(int argc, char **argv)
printf("Done reading '%s', waiting for retransmission queue...\n",
pfcp_tool_cmdline_config.command_file);
do {
if (pfcp_tool_mainloop())
if (pfcp_tool_mainloop(0) == -1)
break;
} while (osmo_pfcp_endpoint_retrans_queue_is_busy(g_pfcp_tool->ep));
printf("Done\n");
} else {
printf("Listening for commands on VTY...\n");
do {
if (pfcp_tool_mainloop())
if (pfcp_tool_mainloop(0) == -1)
break;
} while (!osmo_select_shutdown_done());
}

View File

@@ -26,7 +26,7 @@
#include <osmocom/pfcp/pfcp_endpoint.h>
#include "pfcp_tool.h"
#include <osmocom/pfcptool/pfcp_tool.h>
struct g_pfcp_tool *g_pfcp_tool = NULL;
@@ -48,6 +48,9 @@ void g_pfcp_tool_alloc(void *ctx)
};
INIT_LLIST_HEAD(&g_pfcp_tool->peers);
osmo_sockaddr_str_from_str(&g_pfcp_tool->gtp_state.access.remote.addr, "10.99.0.2", 2152);
g_pfcp_tool->next_ue_addr_state = 0xc0a90001;
}
struct pfcp_tool_peer *pfcp_tool_peer_find(const struct osmo_sockaddr *remote_addr)
@@ -70,7 +73,7 @@ struct pfcp_tool_peer *pfcp_tool_peer_find_or_create(const struct osmo_sockaddr
peer->remote_addr = *remote_addr;
peer->next_seid_state = 0x1234567;
INIT_LLIST_HEAD(&peer->sessions);
llist_add(&peer->entry, &g_pfcp_tool->peers);
llist_add_tail(&peer->entry, &g_pfcp_tool->peers);
return peer;
}
@@ -97,7 +100,7 @@ struct pfcp_tool_session *pfcp_tool_session_find_or_create(struct pfcp_tool_peer
.cp_seid = cp_seid,
.kind = kind,
};
llist_add(&session->entry, &peer->sessions);
llist_add_tail(&session->entry, &peer->sessions);
return session;
}
@@ -144,6 +147,32 @@ static void rx_session_est_resp(struct osmo_pfcp_endpoint *ep, struct osmo_pfcp_
if (!session)
return;
session->up_f_seid = m->ies.session_est_resp.up_f_seid;
/* Retrieve the local-F-TEIDs that the UPF has created */
for (int i = 0; i < m->ies.session_est_resp.created_pdr_count; i++) {
struct osmo_pfcp_ie_created_pdr *cpdr = &m->ies.session_est_resp.created_pdr[i];
struct pfcp_tool_gtp_tun_ep *target = NULL;
if (!cpdr->local_f_teid_present)
continue;
if (cpdr->local_f_teid.choose_flag)
continue;
switch (session->kind) {
case UP_GTP_U_TUNEND:
if (session->tunend.access.local_pdr_id == cpdr->pdr_id)
target = &session->tunend.access.local;
break;
default:
OSMO_ASSERT(0);
// TODO
}
if (target) {
osmo_pfcp_ip_addrs_get_str(&target->addr, NULL, &cpdr->local_f_teid.fixed.ip_addr);
target->teid = cpdr->local_f_teid.fixed.teid;
}
}
}
void pfcp_tool_rx_msg(struct osmo_pfcp_endpoint *ep, struct osmo_pfcp_msg *m, struct osmo_pfcp_msg *req)
@@ -183,3 +212,17 @@ uint64_t peer_new_seid(struct pfcp_tool_peer *peer)
{
return peer->next_seid_state++;
}
uint32_t pfcp_tool_new_teid(void)
{
return g_pfcp_tool->gtp_state.access.remote.teid++;
}
int pfcp_tool_next_ue_addr(struct osmo_sockaddr_str *dst)
{
uint32_t addr = g_pfcp_tool->next_ue_addr_state++;
osmo_sockaddr_str_from_32h(dst, addr, 0);
printf("XXXXX addr=%u 0x%x htonl=%x %s\n", addr, addr, htonl(addr), dst->ip);
fflush(stdout);
return 0;
}

View File

@@ -34,7 +34,7 @@
#include <osmocom/vty/vty.h>
#include <osmocom/vty/command.h>
#include "pfcp_tool.h"
#include <osmocom/pfcptool/pfcp_tool.h>
enum pfcp_tool_vty_node {
PEER_NODE = _LAST_OSMOVTY_NODE + 1,
@@ -97,7 +97,7 @@ DEFUN(c_listen, c_listen_cmd,
rc = osmo_pfcp_endpoint_bind(g_pfcp_tool->ep);
if (rc) {
vty_out(vty, "Failed to bind PFCP endpoint on %s: %s%s\n",
vty_out(vty, "Failed to bind PFCP endpoint on %s: %s%s",
osmo_sockaddr_to_str_c(OTC_SELECT, osmo_pfcp_endpoint_get_local_addr(g_pfcp_tool->ep)),
strerror(-rc), VTY_NEWLINE);
return CMD_WARNING;
@@ -108,7 +108,7 @@ DEFUN(c_listen, c_listen_cmd,
DEFUN(c_sleep, c_sleep_cmd,
"sleep <0-999999> [<0-999>]",
"Let some time pass\n"
"Seconds to wait\n")
"Seconds to wait\n" "Additional milliseconds to wait\n")
{
int secs = atoi(argv[0]);
int msecs = 0;
@@ -124,7 +124,7 @@ DEFUN(c_sleep, c_sleep_cmd,
/* Still operate the message pump while waiting for time to pass */
while (t.active && !osmo_select_shutdown_done()) {
if (pfcp_tool_mainloop())
if (pfcp_tool_mainloop(0) == -1)
break;
}
@@ -134,6 +134,74 @@ DEFUN(c_sleep, c_sleep_cmd,
return CMD_SUCCESS;
}
DEFUN(c_date, c_date_cmd,
"date",
"print a timestamp\n")
{
struct timeval tv = {};
struct tm tm = {};
osmo_gettimeofday(&tv, NULL);
localtime_r(&tv.tv_sec, &tm);
vty_out(vty,"%04d-%02d-%02d,%02d:%02d:%02d.%03d%s",
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec,
(int)(tv.tv_usec / 1000), VTY_NEWLINE);
vty_flush(vty);
return CMD_SUCCESS;
}
#define GTP_PROBE_STR "Configure GTP probing parameters\n"
int gtp_probe_set_target(struct vty *vty, int argc, const char **argv, struct gtp_probe_target *t)
{
int rc;
const char *local_ip_str = argv[0];
const char *local_port_str = "2152";
if (argc > 1) {
local_port_str = argv[1];
t->ofd.priv_nr = 1;
} else {
t->ofd.priv_nr = 0;
}
osmo_sockaddr_str_from_str(&t->cfg, local_ip_str, atoi(local_port_str));
rc = gtp_probe_target_bind(&g_pfcp_tool->gtp_probe, t);
if (rc) {
vty_out(vty, "Failed to bind for GTP probe on UDP %s %s%s", local_ip_str, local_port_str, VTY_NEWLINE);
return CMD_WARNING;
}
return CMD_SUCCESS;
}
DEFUN(c_gtp_probe_ip_target, c_gtp_probe_ip_target_cmd,
"gtp-probe ip-target ADDR <1-65535>",
GTP_PROBE_STR
"Set the target address in IP space. osmo-pfcp-tool must be able to bind on this IP address locally. This can"
" be used for GTP tunnel endpoints: when injecting some GTP, expect to receive it in IP space by listening on"
" this UDP address.\n"
"IP address to bind on, to send/receive on for probing.\n"
"UDP port to receive on for probing.\n")
{
OSMO_ASSERT(g_pfcp_tool);
return gtp_probe_set_target(vty, argc, argv, &g_pfcp_tool->gtp_probe.ip_target);
}
DEFUN(c_gtp_probe_gtp_target, c_gtp_probe_gtp_target_cmd,
"gtp-probe gtp-target ADDR [2152]",
GTP_PROBE_STR
"For GTP tunnel injection: when injecting GTP-U PDUs into a tunnel, use this GTP endpoint for it."
" osmo-pfcp-tool must be able to bind on this IP address locally.\n"
"IP address to bind on, to send/receive on for probing.\n"
"UDP port to receive on for probing.\n")
{
OSMO_ASSERT(g_pfcp_tool);
return gtp_probe_set_target(vty, argc, argv, &g_pfcp_tool->gtp_probe.gtp_target);
}
static struct cmd_node peer_node = {
PEER_NODE,
"%s(peer)# ",
@@ -397,9 +465,45 @@ DEFUN(s_f_teid_choose, s_f_teid_choose_cmd,
return CMD_SUCCESS;
}
int session_tunend_tx_est_req(struct vty *vty, const char **argv, int argc)
DEFUN(s_gtp_probe_run, s_gtp_probe_run_cmd,
"gtp-probe run",
"Probe a GTP tunnel: send one payload in each direction and verify reception\n"
"Run a GTP probe on this session's GTP tunnel\n")
{
struct pfcp_tool_session *session = vty->index;
int rc;
switch (session->kind) {
case UP_GTP_U_TUNEND:
rc = gtp_probe_run_tunend(g_pfcp_tool,
&g_pfcp_tool->gtp_probe,
&session->tunend.access,
&session->tunend.core.ue_local_addr,
&g_pfcp_tool->gtp_probe.ip_target);
if (rc)
return CMD_WARNING;
return CMD_SUCCESS;
case UP_GTP_U_TUNMAP:
vty_out(vty, "%% Error: GTP probing for tunmap not implemented%s", VTY_NEWLINE);
return CMD_WARNING;
default:
OSMO_ASSERT(0);
}
return CMD_SUCCESS;
}
enum pdr_id_fixed {
PDR_ID_CORE = 1,
PDR_ID_ACCESS = 2,
};
const char * const gtp_ip_core = "10.99.0.1";
const char * const gtp_ip_access = "10.99.0.2";
int session_tunend_tx_est_req(struct pfcp_tool_session *session, bool forw, osmo_pfcp_resp_cb resp_cb)
{
struct pfcp_tool_peer *peer = session->peer;
int rc;
struct osmo_pfcp_msg *m;
@@ -411,27 +515,25 @@ int session_tunend_tx_est_req(struct vty *vty, const char **argv, int argc)
OSMO_ASSERT(session->kind == UP_GTP_U_TUNEND);
if (!g_pfcp_tool->ep) {
vty_out(vty, "Endpoint not configured%s", VTY_NEWLINE);
if (!g_pfcp_tool->ep)
return CMD_WARNING;
}
if (argc > 0 && !strcmp("drop", argv[0]))
osmo_pfcp_bits_set(aa.bits, OSMO_PFCP_APPLY_ACTION_DROP, true);
else
if (forw)
osmo_pfcp_bits_set(aa.bits, OSMO_PFCP_APPLY_ACTION_FORW, true);
else
osmo_pfcp_bits_set(aa.bits, OSMO_PFCP_APPLY_ACTION_DROP, true);
#define STR_TO_ADDR(DST, SRC) do { \
if (osmo_sockaddr_str_to_sockaddr(&SRC, &DST.u.sas)) { \
vty_out(vty, "Error in " #SRC ": " OSMO_SOCKADDR_STR_FMT "%s", \
OSMO_SOCKADDR_STR_FMT_ARGS(&SRC), VTY_NEWLINE); \
LOGP(DLGLOBAL, LOGL_ERROR, "Error in " #SRC ": " OSMO_SOCKADDR_STR_FMT "\n", \
OSMO_SOCKADDR_STR_FMT_ARGS(&SRC)); \
return CMD_WARNING; \
} \
} while (0)
STR_TO_ADDR(ue_addr, session->tunend.core.ue_local_addr);
if (session->tunend.access.local.teid == 0) {
if (!*session->tunend.access.local.addr.ip) {
f_teid_access_local = (struct osmo_pfcp_ie_f_teid){
.choose_flag = true,
.choose = {
@@ -449,6 +551,7 @@ int session_tunend_tx_est_req(struct vty *vty, const char **argv, int argc)
};
STR_TO_ADDR(f_teid_access_local.fixed.ip_addr.v4, session->tunend.access.local.addr);
}
session->tunend.access.local_pdr_id = PDR_ID_ACCESS;
ohc_access = (struct osmo_pfcp_ie_outer_header_creation){
.teid_present = true,
@@ -464,6 +567,10 @@ int session_tunend_tx_est_req(struct vty *vty, const char **argv, int argc)
osmo_pfcp_ip_addrs_set(&cp_f_seid.ip_addr, osmo_pfcp_endpoint_get_local_addr(g_pfcp_tool->ep));
m = osmo_pfcp_msg_alloc_tx_req(OTC_SELECT, &peer->remote_addr, OSMO_PFCP_MSGT_SESSION_EST_REQ);
m->ctx.resp_cb = resp_cb;
m->ctx.priv = session;
m->h.seid_present = true;
/* the UPF has yet to assign a SEID for itself, no matter what SEID we (the CPF) use for this session */
m->h.seid = 0;
@@ -475,7 +582,7 @@ int session_tunend_tx_est_req(struct vty *vty, const char **argv, int argc)
.create_pdr_count = 2,
.create_pdr = {
{
.pdr_id = 1,
.pdr_id = PDR_ID_CORE,
.precedence = 255,
.pdi = {
.source_iface = OSMO_PFCP_SOURCE_IFACE_CORE,
@@ -492,7 +599,7 @@ int session_tunend_tx_est_req(struct vty *vty, const char **argv, int argc)
.far_id = 1,
},
{
.pdr_id = 2,
.pdr_id = PDR_ID_ACCESS,
.precedence = 255,
.pdi = {
.source_iface = OSMO_PFCP_SOURCE_IFACE_ACCESS,
@@ -532,15 +639,14 @@ int session_tunend_tx_est_req(struct vty *vty, const char **argv, int argc)
rc = peer_tx(peer, m);
if (rc) {
vty_out(vty, "Failed to transmit: %s%s", strerror(-rc), VTY_NEWLINE);
LOGP(DLGLOBAL, LOGL_ERROR, "Failed to transmit: %s\n", strerror(-rc));
return CMD_WARNING;
}
return CMD_SUCCESS;
}
int session_tunmap_tx_est_req(struct vty *vty, const char **argv, int argc)
int session_tunmap_tx_est_req(struct pfcp_tool_session *session, bool forw, osmo_pfcp_resp_cb resp_cb)
{
struct pfcp_tool_session *session = vty->index;
struct pfcp_tool_peer *peer = session->peer;
int rc;
struct osmo_pfcp_msg *m;
@@ -555,15 +661,13 @@ int session_tunmap_tx_est_req(struct vty *vty, const char **argv, int argc)
struct osmo_pfcp_ie_apply_action aa = {};
if (!g_pfcp_tool->ep) {
vty_out(vty, "Endpoint not configured%s", VTY_NEWLINE);
if (!g_pfcp_tool->ep)
return CMD_WARNING;
}
if (argc > 0 && !strcmp("drop", argv[0]))
osmo_pfcp_bits_set(aa.bits, OSMO_PFCP_APPLY_ACTION_DROP, true);
else
if (forw)
osmo_pfcp_bits_set(aa.bits, OSMO_PFCP_APPLY_ACTION_FORW, true);
else
osmo_pfcp_bits_set(aa.bits, OSMO_PFCP_APPLY_ACTION_DROP, true);
if (session->tunmap.access.local.teid == 0) {
f_teid_access_local = (struct osmo_pfcp_ie_f_teid){
@@ -625,6 +729,10 @@ int session_tunmap_tx_est_req(struct vty *vty, const char **argv, int argc)
osmo_pfcp_ip_addrs_set(&cp_f_seid.ip_addr, osmo_pfcp_endpoint_get_local_addr(g_pfcp_tool->ep));
m = osmo_pfcp_msg_alloc_tx_req(OTC_SELECT, &peer->remote_addr, OSMO_PFCP_MSGT_SESSION_EST_REQ);
m->ctx.resp_cb = resp_cb;
m->ctx.priv = session;
m->h.seid_present = true;
m->h.seid = 0;
/* GTP tunmap: remove header from both directions, and add header in both directions */
@@ -635,7 +743,7 @@ int session_tunmap_tx_est_req(struct vty *vty, const char **argv, int argc)
.create_pdr_count = 2,
.create_pdr = {
{
.pdr_id = 1,
.pdr_id = PDR_ID_CORE,
.precedence = 255,
.pdi = {
.source_iface = OSMO_PFCP_SOURCE_IFACE_CORE,
@@ -650,7 +758,7 @@ int session_tunmap_tx_est_req(struct vty *vty, const char **argv, int argc)
.far_id = 1,
},
{
.pdr_id = 2,
.pdr_id = PDR_ID_ACCESS,
.precedence = 255,
.pdi = {
.source_iface = OSMO_PFCP_SOURCE_IFACE_ACCESS,
@@ -692,7 +800,7 @@ int session_tunmap_tx_est_req(struct vty *vty, const char **argv, int argc)
rc = peer_tx(peer, m);
if (rc) {
vty_out(vty, "Failed to transmit: %s%s", strerror(-rc), VTY_NEWLINE);
LOGP(DLGLOBAL, LOGL_ERROR, "Failed to transmit PFCP: %s\n", strerror(-rc));
return CMD_WARNING;
}
return CMD_SUCCESS;
@@ -705,39 +813,33 @@ DEFUN(session_tx_est_req, session_tx_est_req_cmd,
"Set FAR to DROP = 1\n")
{
struct pfcp_tool_session *session = vty->index;
bool forw = (argc == 0 || !strcmp("forw", argv[0]));
switch (session->kind) {
case UP_GTP_U_TUNEND:
return session_tunend_tx_est_req(vty, argv, argc);
return session_tunend_tx_est_req(session, forw, NULL);
case UP_GTP_U_TUNMAP:
return session_tunmap_tx_est_req(vty, argv, argc);
return session_tunmap_tx_est_req(session, forw, NULL);
default:
vty_out(vty, "unknown gtp action%s", VTY_NEWLINE);
return CMD_WARNING;
}
}
DEFUN(session_tx_mod_req, session_tx_mod_req_cmd,
"tx session-mod-req far [(forw|drop)]",
TX_STR "Send a Session Modification Request\n"
"Set FAR to FORW = 1\n"
"Set FAR to DROP = 1\n")
int session_tunmap_tx_mod_req(struct pfcp_tool_session *session, bool forw, osmo_pfcp_resp_cb resp_cb)
{
struct pfcp_tool_session *session = vty->index;
struct pfcp_tool_peer *peer = session->peer;
int rc;
struct osmo_pfcp_msg *m;
struct osmo_pfcp_ie_apply_action aa = {};
struct osmo_pfcp_ie_f_seid cp_f_seid;
if (!g_pfcp_tool->ep) {
vty_out(vty, "Endpoint not configured%s", VTY_NEWLINE);
if (!g_pfcp_tool->ep)
return CMD_WARNING;
}
if (argc > 0 && !strcmp("drop", argv[0]))
osmo_pfcp_bits_set(aa.bits, OSMO_PFCP_APPLY_ACTION_DROP, true);
else
if (forw)
osmo_pfcp_bits_set(aa.bits, OSMO_PFCP_APPLY_ACTION_FORW, true);
else
osmo_pfcp_bits_set(aa.bits, OSMO_PFCP_APPLY_ACTION_DROP, true);
cp_f_seid = (struct osmo_pfcp_ie_f_seid){
.seid = session->cp_seid,
@@ -745,6 +847,10 @@ DEFUN(session_tx_mod_req, session_tx_mod_req_cmd,
osmo_pfcp_ip_addrs_set(&cp_f_seid.ip_addr, osmo_pfcp_endpoint_get_local_addr(g_pfcp_tool->ep));
m = osmo_pfcp_msg_alloc_tx_req(OTC_SELECT, &peer->remote_addr, OSMO_PFCP_MSGT_SESSION_MOD_REQ);
m->ctx.resp_cb = resp_cb;
m->ctx.priv = session;
m->h.seid_present = true;
m->h.seid = session->up_f_seid.seid;
m->ies.session_mod_req = (struct osmo_pfcp_msg_session_mod_req){
@@ -766,13 +872,25 @@ DEFUN(session_tx_mod_req, session_tx_mod_req_cmd,
};
rc = peer_tx(peer, m);
if (rc) {
vty_out(vty, "Failed to transmit: %s%s", strerror(-rc), VTY_NEWLINE);
if (rc)
return CMD_WARNING;
}
return CMD_SUCCESS;
}
DEFUN(session_tx_mod_req, session_tx_mod_req_cmd,
"tx session-mod-req far [(forw|drop)]",
TX_STR "Send a Session Modification Request\n"
"Set FAR to FORW = 1\n"
"Set FAR to DROP = 1\n")
{
struct pfcp_tool_session *session = vty->index;
bool forw = (argc == 0 || !strcmp("forw", argv[0]));
int rc = session_tunmap_tx_mod_req(session, forw, NULL);
if (rc != CMD_SUCCESS)
vty_out(vty, "Failed to send Session Modification Request%s", VTY_NEWLINE);
return rc;
}
DEFUN(session_tx_del_req, session_tx_del_req_cmd,
"tx session-del-req",
TX_STR "Send a Session Deletion Request\n")
@@ -799,6 +917,378 @@ DEFUN(session_tx_del_req, session_tx_del_req_cmd,
return CMD_SUCCESS;
}
/* N SESSIONS */
static int g_pfcp_responses_pending = 0;
DEFUN(wait_responses, wait_responses_cmd,
"wait responses",
"Let some time pass until events have occured\n"
"Wait for all PFCP responses for pending PFCP requests\n")
{
if (!g_pfcp_responses_pending) {
vty_out(vty, "no responses pending, not waiting.%s", VTY_NEWLINE);
return CMD_SUCCESS;
}
vty_out(vty, "waiting for %d PFCP responses, %u GTP probes...%s", g_pfcp_responses_pending,
g_gtp_probes_pending, VTY_NEWLINE);
vty_flush(vty);
/* Still operate the message pump while waiting for time to pass */
while (!osmo_select_shutdown_done()) {
if (pfcp_tool_mainloop(0) == -1) {
vty_out(vty, "waiting for responses interrupted.%s", VTY_NEWLINE);
vty_flush(vty);
break;
}
if (g_pfcp_responses_pending == 0 && g_gtp_probes_pending == 0)
break;
}
if (g_pfcp_responses_pending || g_gtp_probes_pending)
vty_out(vty, "...still pending: %d PFCP resposes, %u GTP probes.%s", g_pfcp_responses_pending,
g_gtp_probes_pending, VTY_NEWLINE);
vty_out(vty, "...done waiting for responses%s", VTY_NEWLINE);
vty_flush(vty);
return CMD_SUCCESS;
}
/* N SESSIONS TUNEND */
int one_session_mod_tunend_resp_cb(struct osmo_pfcp_msg *req, struct osmo_pfcp_msg *rx_resp, const char *errmsg)
{
g_pfcp_responses_pending--;
return 0;
}
int one_session_mod_tunend(struct pfcp_tool_session *session)
{
int rc;
rc = session_tunmap_tx_mod_req(session, true, one_session_mod_tunend_resp_cb);
if (rc == CMD_SUCCESS)
g_pfcp_responses_pending++;
return rc;
}
void est_resp_get_created_f_teid(struct pfcp_tool_gtp_tun_ep *dst, const struct osmo_pfcp_msg *rx_resp, uint16_t pdr_id)
{
int i;
const struct osmo_pfcp_msg_session_est_resp *r;
if (rx_resp->h.message_type != OSMO_PFCP_MSGT_SESSION_EST_RESP)
return;
r = &rx_resp->ies.session_est_resp;
for (i = 0; i < r->created_pdr_count; i++) {
const struct osmo_pfcp_ie_created_pdr *p = &r->created_pdr[i];
if (p->pdr_id != pdr_id)
continue;
if (!p->local_f_teid_present)
continue;
osmo_sockaddr_str_from_sockaddr(&dst->addr,
&p->local_f_teid.fixed.ip_addr.v4.u.sas);
dst->teid = p->local_f_teid.fixed.teid;
}
}
int one_session_create_tunend_resp_cb(struct osmo_pfcp_msg *req, struct osmo_pfcp_msg *rx_resp, const char *errmsg)
{
struct pfcp_tool_session *session = req->ctx.priv;
enum osmo_pfcp_cause *cause;
const struct osmo_pfcp_msg_session_est_resp *r = NULL;
if (rx_resp)
r = &rx_resp->ies.session_est_resp;
g_pfcp_responses_pending--;
if (errmsg)
LOGP(DLPFCP, LOGL_ERROR, "%s\n", errmsg);
cause = rx_resp ? osmo_pfcp_msg_cause(rx_resp) : NULL;
if (!cause || *cause != OSMO_PFCP_CAUSE_REQUEST_ACCEPTED)
return 0;
/* store SEID */
if (r && r->up_f_seid_present)
session->up_f_seid = r->up_f_seid;
/* store access local F-TEID */
est_resp_get_created_f_teid(&session->tunend.access.local, rx_resp, PDR_ID_ACCESS);
/* Success response, now continue with second step: Session Mod to set the CORE's remote side GTP */
one_session_mod_tunend(session);
return 0;
}
static int one_session_create_tunend(struct pfcp_tool_peer *peer)
{
struct pfcp_tool_session *session;
struct pfcp_tool_tunend *te;
int rc;
session = pfcp_tool_session_find_or_create(peer, peer_new_seid(peer), UP_GTP_U_TUNEND);
te = &session->tunend;
/* Access: set remote GTP address */
te->access.remote = g_pfcp_tool->gtp_state.access.remote;
te->access.remote.teid = pfcp_tool_new_teid();
/* Set local F-TEIDs == CHOOSE */
te->access.local = (struct pfcp_tool_gtp_tun_ep){};
pfcp_tool_next_ue_addr(&te->core.ue_local_addr);
/* Send initial Session Establishment Request */
rc = session_tunend_tx_est_req(session, false, one_session_create_tunend_resp_cb);
if (rc == CMD_SUCCESS)
g_pfcp_responses_pending++;
return rc;
}
/* N SESSIONS TUNMAP */
int one_session_mod_tunmap_resp_cb(struct osmo_pfcp_msg *req, struct osmo_pfcp_msg *rx_resp, const char *errmsg)
{
g_pfcp_responses_pending--;
return 0;
}
int one_session_mod_tunmap(struct pfcp_tool_session *session)
{
struct pfcp_tool_gtp_tun_ep *dst;
int rc;
dst = &session->tunmap.core.remote;
if (osmo_sockaddr_str_from_str2(&dst->addr, gtp_ip_core)) {
LOGP(DLGLOBAL, LOGL_ERROR, "Error setting GTP IP address from %s\n",
osmo_quote_cstr_c(OTC_SELECT, gtp_ip_core, -1));
return CMD_WARNING;
}
dst->teid = pfcp_tool_new_teid();
rc = session_tunmap_tx_mod_req(session, true, one_session_mod_tunmap_resp_cb);
if (rc == CMD_SUCCESS)
g_pfcp_responses_pending++;
return rc;
}
int one_session_create_tunmap_resp_cb(struct osmo_pfcp_msg *req, struct osmo_pfcp_msg *rx_resp, const char *errmsg)
{
struct pfcp_tool_session *session = req->ctx.priv;
enum osmo_pfcp_cause *cause;
g_pfcp_responses_pending--;
if (errmsg)
LOGP(DLPFCP, LOGL_ERROR, "%s\n", errmsg);
cause = rx_resp ? osmo_pfcp_msg_cause(rx_resp) : NULL;
if (!cause || *cause != OSMO_PFCP_CAUSE_REQUEST_ACCEPTED)
return 0;
/* store SEID */
if (rx_resp->ies.session_est_resp.up_f_seid_present)
session->up_f_seid = rx_resp->ies.session_est_resp.up_f_seid;
/* store local F-TEIDs */
est_resp_get_created_f_teid(&session->tunmap.access.local, rx_resp, PDR_ID_ACCESS);
est_resp_get_created_f_teid(&session->tunmap.core.local, rx_resp, PDR_ID_CORE);
/* Success response, now continue with second step: Session Mod to set the CORE's remote side GTP */
one_session_mod_tunmap(session);
return 0;
}
static int one_session_create_tunmap(struct pfcp_tool_peer *peer)
{
struct pfcp_tool_session *session;
struct pfcp_tool_tunmap *tm;
struct pfcp_tool_gtp_tun_ep *dst;
int rc;
session = pfcp_tool_session_find_or_create(peer, peer_new_seid(peer), UP_GTP_U_TUNMAP);
tm = &session->tunmap;
/* Access: set remote GTP address */
dst = &tm->access.remote;
if (osmo_sockaddr_str_from_str2(&dst->addr, gtp_ip_access)) {
LOGP(DLGLOBAL, LOGL_ERROR, "Error setting GTP IP address from %s\n",
osmo_quote_cstr_c(OTC_SELECT, gtp_ip_access, -1));
return CMD_WARNING;
}
dst->teid = pfcp_tool_new_teid();
/* Core: set remote GTP address */
dst = &tm->core.remote;
if (osmo_sockaddr_str_from_str2(&dst->addr, gtp_ip_core)) {
LOGP(DLGLOBAL, LOGL_ERROR, "Error setting GTP IP address from %s\n",
osmo_quote_cstr_c(OTC_SELECT, gtp_ip_core, -1));
return CMD_WARNING;
}
dst->teid = pfcp_tool_new_teid();
/* Set local F-TEIDs == CHOOSE */
tm->access.local = (struct pfcp_tool_gtp_tun_ep){};
tm->core.local = (struct pfcp_tool_gtp_tun_ep){};
/* Send initial Session Establishment Request */
rc = session_tunmap_tx_est_req(session, false, one_session_create_tunmap_resp_cb);
if (rc == CMD_SUCCESS)
g_pfcp_responses_pending++;
return rc;
return CMD_WARNING;
}
static void n_sessions_create(struct vty *vty, struct pfcp_tool_peer *peer, int n, enum up_gtp_action_kind kind)
{
int i;
for (i = 0; i < n; i++) {
int rc;
if (kind == UP_GTP_U_TUNMAP)
rc = one_session_create_tunmap(peer);
else
rc = one_session_create_tunend(peer);
if (rc != CMD_SUCCESS)
goto aborted;
/* handle any pending select work */
while (!osmo_select_shutdown_done()) {
rc = pfcp_tool_mainloop(1);
/* quit requested */
if (rc < 0)
goto aborted;
/* no fd needed service */
if (rc == 0)
break;
}
/* Every N created sessions, wait for pending responses */
if (!(i & 0x3f) && g_pfcp_responses_pending) {
vty_out(vty, "waiting for %d responses...%s", g_pfcp_responses_pending, VTY_NEWLINE);
vty_flush(vty);
while (!osmo_select_shutdown_done()) {
if (pfcp_tool_mainloop(0) == -1)
break;
if (g_pfcp_responses_pending == 0)
break;
}
}
}
return;
aborted:
vty_out(vty, "Aborted at session nr %d%s", i, VTY_NEWLINE);
vty_flush(vty);
}
static void n_sessions_delete(struct pfcp_tool_peer *peer, int n, enum up_gtp_action_kind kind)
{
}
DEFUN(n_cfg_session_gtp_access, n_cfg_session_gtp_access_cmd,
"n cfg session access remote f-teid start ADDR <0-65535>",
"Batch run\n"
"Configure batch run parameters\n"
"Batch run on PFCP sessions\n"
"Configure GTP Access side\n"
"Configure remote GTP tunnel endpoint, as seem from UPF\n"
"Configure F-TEID, the GTP address and the tunnel's TEID at that address\n"
"Set the first addr+TEID to use, increment the TEID for each 'n session'\n"
"IP address (GTP)\n" "TEID\n")
{
osmo_sockaddr_str_from_str(&g_pfcp_tool->gtp_state.access.remote.addr, argv[0], 0);
g_pfcp_tool->gtp_state.access.remote.teid = atoi(argv[1]);
return CMD_SUCCESS;
}
DEFUN(n_cfg_session_ue_addr, n_cfg_session_ue_addr_cmd,
"n cfg session ue-addr start ADDR",
"Batch run\n"
"Configure batch run parameters\n"
"Batch run on PFCP sessions\n"
"Configure first UE address\n"
"Set the first addr to use, increment for each 'n session'\n"
"UE IP address\n")
{
struct osmo_sockaddr_str addr;
osmo_sockaddr_str_from_str(&addr, argv[0], 0);
osmo_sockaddr_str_to_32h(&addr, &g_pfcp_tool->next_ue_addr_state);
return CMD_SUCCESS;
}
DEFUN(n_sessions, n_sessions_cmd,
"n (<0-2147483647>|all) session (create|delete) (tunend|tunmap)",
"Batch run\n"
"Perform the action N times\n" "Perform the action on all available entries\n"
"Batch run on PFCP sessions\n"
"Create N new sessions\n"
"Delete N sessions created earlier\n"
TUNEND_STR TUNMAP_STR)
{
struct pfcp_tool_peer *peer = vty->index;
int n = (strcmp("all", argv[0]) == 0? -1 : atoi(argv[0]));
bool create = (strcmp("create", argv[1]) == 0);
enum up_gtp_action_kind kind;
if (!strcmp(argv[2], "tunmap"))
kind = UP_GTP_U_TUNMAP;
else
kind = UP_GTP_U_TUNEND;
if (create)
n_sessions_create(vty, peer, n, kind);
else
n_sessions_delete(peer, n, kind);
return CMD_SUCCESS;
}
static void n_sessions_gtp_probe_run(struct vty *vty, struct pfcp_tool_peer *peer, enum up_gtp_action_kind kind)
{
struct pfcp_tool_session *s;
int batch;
batch = 0;
llist_for_each_entry (s, &peer->sessions, entry) {
if (s->kind != kind)
continue;
/* operate the select loop while dispatching probes */
if (batch >= 10) {
if (osmo_select_shutdown_done())
break;
while (!osmo_select_shutdown_done() && g_gtp_probes_pending) {
if (pfcp_tool_mainloop(0) < 0)
break;
}
batch = 0;
}
batch++;
switch (s->kind) {
case UP_GTP_U_TUNEND:
gtp_probe_run_tunend(g_pfcp_tool,
&g_pfcp_tool->gtp_probe,
&s->tunend.access,
&s->tunend.core.ue_local_addr,
&g_pfcp_tool->gtp_probe.ip_target);
break;
default:
break;
}
}
}
DEFUN(n_sessions_gtp_probe, n_sessions_gtp_probe_cmd,
"n all session gtp-probe run tunend",
"Batch run\n"
"Perform the action on all available entries\n"
"Batch run on PFCP sessions\n"
"Run a GTP probe on the GTP tunnel created by this session\n"
"Run only on tunend sessions\n")
{
struct pfcp_tool_peer *peer = vty->index;
n_sessions_gtp_probe_run(vty, peer, UP_GTP_U_TUNEND);
return CMD_SUCCESS;
}
static void install_ve_and_config(struct cmd_element *cmd)
{
install_element_ve(cmd);
@@ -818,23 +1308,35 @@ void pfcp_tool_vty_init_cmds()
OSMO_ASSERT(g_pfcp_tool != NULL);
install_ve_and_config(&c_sleep_cmd);
install_ve_and_config(&c_date_cmd);
install_ve_and_config(&wait_responses_cmd);
install_ve_and_config(&c_gtp_probe_ip_target_cmd);
install_ve_and_config(&c_gtp_probe_gtp_target_cmd);
install_ve_and_config(&peer_cmd);
install_node(&peer_node, NULL);
install_element(PEER_NODE, &c_sleep_cmd);
install_element(PEER_NODE, &c_date_cmd);
install_element(PEER_NODE, &peer_tx_heartbeat_cmd);
install_element(PEER_NODE, &peer_tx_assoc_setup_req_cmd);
install_element(PEER_NODE, &peer_retrans_req_cmd);
install_element(PEER_NODE, &n_cfg_session_gtp_access_cmd);
install_element(PEER_NODE, &n_cfg_session_ue_addr_cmd);
install_element(PEER_NODE, &n_sessions_cmd);
install_element(PEER_NODE, &n_sessions_gtp_probe_cmd);
install_element(PEER_NODE, &wait_responses_cmd);
install_element(PEER_NODE, &session_cmd);
install_element(PEER_NODE, &session_endecaps_cmd);
install_node(&session_node, NULL);
install_element(SESSION_NODE, &c_sleep_cmd);
install_element(SESSION_NODE, &c_date_cmd);
install_element(SESSION_NODE, &session_tx_est_req_cmd);
install_element(SESSION_NODE, &session_tx_mod_req_cmd);
install_element(SESSION_NODE, &session_tx_del_req_cmd);
install_element(SESSION_NODE, &s_ue_cmd);
install_element(SESSION_NODE, &s_f_teid_cmd);
install_element(SESSION_NODE, &s_f_teid_choose_cmd);
install_element(SESSION_NODE, &s_gtp_probe_run_cmd);
}

View File

@@ -36,8 +36,20 @@
struct g_upf *g_upf = NULL;
struct osmo_tdef g_upf_nft_tdefs[] = {
{ .T = -32, .default_val = 1000, .unit = OSMO_TDEF_MS,
.desc = "How long to wait for more nft rulesets before flushing in batch",
},
{ .T = -33, .default_val = 64, .unit = OSMO_TDEF_CUSTOM,
.desc = "When reaching this nr of queued nft rulesets, flush the queue",
.max_val = 128,
},
{}
};
struct osmo_tdef_group g_upf_tdef_groups[] = {
{ "pfcp", "PFCP endpoint timers", osmo_pfcp_tdefs, },
{ "nft", "netfilter timers", g_upf_nft_tdefs, },
{}
};

View File

@@ -26,6 +26,7 @@
#include <osmocom/core/talloc.h>
#include <osmocom/core/logging.h>
#include <osmocom/core/timer.h>
#include <osmocom/upf/upf.h>
#include <osmocom/upf/upf_nft.h>
@@ -39,18 +40,18 @@ static char *upf_nft_ruleset_vmap_init(void *ctx, const char *table_name, int pr
{
/* 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
* add map inet osmo-upf mpre { typeof ip daddr . @ih,32,32 : verdict; }
* add map inet osmo-upf mpost { typeof meta mark : verdict; }
* add rule inet osmo-upf pre udp dport 2152 ip daddr . @ih,32,32 vmap @mpre
* add rule inet osmo-upf post meta mark vmap @mpost
*/
return talloc_asprintf(ctx,
"add chain inet %s pre { type filter hook prerouting priority %d; policy accept; };\n"
"add chain inet %s post { type filter hook postrouting priority %d; policy accept; };\n"
"add map inet %s tunmap-pre { typeof ip daddr . @ih,32,32 : verdict; };\n"
"add map inet %s tunmap-post { typeof meta mark : verdict; };\n"
"add rule inet %s pre udp dport %u ip daddr . @ih,32,32 vmap @tunmap-pre;\n"
"add rule inet %s post meta mark vmap @tunmap-post;\n",
"add map inet %s mpre { typeof ip daddr . @ih,32,32 : verdict; };\n"
"add map inet %s mpost { typeof meta mark : verdict; };\n"
"add rule inet %s pre udp dport %u ip daddr . @ih,32,32 vmap @mpre;\n"
"add rule inet %s post meta mark vmap @mpost;\n",
table_name, priority_pre,
table_name, priority_post,
table_name,
@@ -59,9 +60,10 @@ static char *upf_nft_ruleset_vmap_init(void *ctx, const char *table_name, int pr
table_name);
}
static int upf_nft_run(const char *ruleset)
static int upf_nft_run_now(const char *ruleset)
{
int rc;
const int logmax = 256;
if (g_upf->tunmap.mockup) {
LOGP(DNFT, LOGL_NOTICE, "tunmap/mockup active: not running nft ruleset: '%s'\n", ruleset);
@@ -81,14 +83,135 @@ static int upf_nft_run(const char *ruleset)
return -EIO;
}
LOGP(DNFT, LOGL_DEBUG, "run nft ruleset: %s\n", osmo_quote_str_c(OTC_SELECT, ruleset, -1));
if (log_check_level(DNFT, LOGL_DEBUG)) {
size_t l = strlen(ruleset);
LOGP(DNFT, LOGL_DEBUG, "ran nft ruleset, %zu chars: \"%s%s\"\n",
l,
osmo_escape_cstr_c(OTC_SELECT, ruleset, OSMO_MIN(logmax, l)),
l > logmax ? "..." : "");
}
return 0;
}
struct nft_queue {
struct osmo_tdef *flush_time_tdef;
struct osmo_tdef *ruleset_max_tdef;
struct osmo_strbuf sb;
/* 128 NFT rulesets amount to about 110 kb of char */
char buf[1<<17];
unsigned int ruleset_count;
struct osmo_timer_list timer;
};
static void nft_queue_clear_buf(struct nft_queue *q)
{
q->sb = (struct osmo_strbuf){ .buf = q->buf, .len = sizeof(q->buf) };
q->buf[0] = '\0';
}
static void nft_queue_init(void *ctx, struct nft_queue *q,
struct osmo_tdef *flush_time_tdef,
struct osmo_tdef *ruleset_max_tdef)
{
*q = (struct nft_queue){
.flush_time_tdef = flush_time_tdef,
.ruleset_max_tdef = ruleset_max_tdef,
};
nft_queue_clear_buf(q);
}
static void nft_queue_flush(struct nft_queue *q, const char *reason)
{
static unsigned int flush_count = 0;
static unsigned int ruleset_count = 0;
/* We will now flush the queue empty. A timer needs to run only when the next pending entry is added. */
osmo_timer_del(&q->timer);
/* Nothing to send? */
if (!q->sb.chars_needed)
return;
flush_count++;
ruleset_count += q->ruleset_count;
LOGP(DNFT, LOGL_INFO, "Flushing NFT ruleset queue: %s: n:%u strlen:%zu (flush count: %u avg rules per flush: %s)\n",
reason,
q->ruleset_count, q->sb.chars_needed,
flush_count, osmo_int_to_float_str_c(OTC_SELECT, 10 * ruleset_count / flush_count, 1));
q->ruleset_count = 0;
upf_nft_run_now(q->sb.buf);
nft_queue_clear_buf(q);
}
static void nft_queue_flush_cb(void *q)
{
nft_queue_flush(q, "timeout");
}
static int nft_enqueue(struct nft_queue *q,
int (*tunmap_to_str_buf)(char *buf, size_t len, struct upf_tunmap *tunmap),
struct upf_tunmap *tunmap)
{
int ruleset_max;
struct osmo_strbuf q_sb_was = q->sb;
OSMO_STRBUF_APPEND(q->sb, tunmap_to_str_buf, tunmap);
/* is that being cut off? then revert the addition. This should never happen in practice. */
if (q->sb.chars_needed >= q->sb.len) {
q->sb = q_sb_was;
if (q->sb.pos)
*q->sb.pos = '\0';
nft_queue_flush(q, "reached max nr of chars");
OSMO_STRBUF_APPEND(q->sb, tunmap_to_str_buf, tunmap);
}
/* Append separator -- no problem if that gets cut off. */
OSMO_STRBUF_PRINTF(q->sb, "\n");
q->ruleset_count++;
LOGP(DNFT, LOGL_INFO, "Added NFT ruleset to queue: n:%u strlen:%zu\n",
q->ruleset_count, q->sb.chars_needed);
/* Added a rule, see if it has reached ruleset_max. */
ruleset_max = osmo_tdef_get(q->ruleset_max_tdef, q->ruleset_max_tdef->T, OSMO_TDEF_CUSTOM, 128);
if (q->ruleset_count >= ruleset_max) {
nft_queue_flush(q, "reached max nr of rules");
return 0;
}
/* Item added. If the timer is not running yet, schedule a flush in given timeout */
if (!osmo_timer_pending(&q->timer)) {
struct osmo_tdef *t;
unsigned long us;
osmo_timer_setup(&q->timer, nft_queue_flush_cb, q);
t = q->flush_time_tdef;
us = osmo_tdef_get(t, t->T, OSMO_TDEF_US, 100000);
osmo_timer_schedule(&q->timer, us / 1000000, us % 1000000);
}
return 0;
}
static void nft_queue_free(struct nft_queue *q)
{
osmo_timer_del(&q->timer);
}
static struct nft_queue g_nft_queue = {};
int upf_nft_init()
{
int rc;
nft_queue_init(g_upf, &g_nft_queue,
osmo_tdef_get_entry(g_upf_nft_tdefs, -32),
osmo_tdef_get_entry(g_upf_nft_tdefs, -33));
/* Always set up the default settings, also in mockup mode, so that the VTY reflects sane values */
if (!g_upf->tunmap.table_name)
g_upf->tunmap.table_name = talloc_strdup(g_upf, "osmo-upf");
@@ -106,7 +229,7 @@ int upf_nft_init()
return -EIO;
}
rc = upf_nft_run(upf_nft_tunmap_get_table_init_str(OTC_SELECT));
rc = upf_nft_run_now(upf_nft_tunmap_get_table_init_str(OTC_SELECT));
if (rc) {
LOGP(DNFT, LOGL_ERROR, "Failed to create nft table %s\n",
osmo_quote_str_c(OTC_SELECT, g_upf->tunmap.table_name, -1));
@@ -114,7 +237,7 @@ int upf_nft_init()
}
LOGP(DNFT, LOGL_NOTICE, "Created nft table %s\n", osmo_quote_str_c(OTC_SELECT, g_upf->tunmap.table_name, -1));
rc = upf_nft_run(upf_nft_tunmap_get_vmap_init_str(OTC_SELECT));
rc = upf_nft_run_now(upf_nft_tunmap_get_vmap_init_str(OTC_SELECT));
if (rc) {
LOGP(DNFT, LOGL_ERROR, "Failed to initialize nft verdict map in table %s\n", g_upf->tunmap.table_name);
return rc;
@@ -124,6 +247,7 @@ int upf_nft_init()
int upf_nft_free()
{
nft_queue_free(&g_nft_queue);
if (!g_upf->tunmap.nft_ctx)
return 0;
nft_ctx_free(g_upf->tunmap.nft_ctx);
@@ -170,46 +294,46 @@ static int tunmap_add_single_direction(char *buf, size_t buflen,
}
/* # add chain for verdict map in prerouting
* add chain inet osmo-upf tunmap-pre-123
* add chain inet osmo-upf mpre123
* # mangle destination address at prerouting
* add rule inet osmo-upf tunmap-pre-123 ip daddr set 1.1.1.1 meta mark set 123 counter accept
* add rule inet osmo-upf mpre123 ip daddr set 1.1.1.1 meta mark set 123 counter accept
*
* # add chain for verdict map in postrouting
* add chain inet osmo-upf tunmap-post-123
* add chain inet osmo-upf mpost123
* # mangle source address and GTP TID at postrouting
* add rule inet osmo-upf tunmap-post-123 ip saddr set 2.2.2.1 @ih,32,32 set 0x00000102 counter accept
* add rule inet osmo-upf mpost123 ip saddr set 2.2.2.1 @ih,32,32 set 0x00000102 counter accept
*
* # add elements to verdict map, jump to chain
* add element inet osmo-upf tunmap-pre { 2.2.2.3 . 0x00000203 : jump tunmap-pre-123 }
* add element inet osmo-upf tunmap-post { 123 : jump tunmap-post-123 }
* add element inet osmo-upf mpre { 2.2.2.3 . 0x00000203 : jump mpre123 }
* add element inet osmo-upf mpost { 123 : jump mpost123 }
*/
OSMO_STRBUF_PRINTF(sb, "add chain inet %s tunmap-pre-%u;\n",
OSMO_STRBUF_PRINTF(sb, "add chain inet %s mpre%u;\n",
args->table_name, from_peer->chain_id);
OSMO_STRBUF_PRINTF(sb, "add rule inet %s tunmap-pre-%u",
OSMO_STRBUF_PRINTF(sb, "add rule inet %s mpre%u",
args->table_name, from_peer->chain_id);
OSMO_STRBUF_PRINTF(sb, " ip daddr set ");
OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, to_peer->addr_remote);
OSMO_STRBUF_PRINTF(sb, " meta mark set %u counter accept;\n", from_peer->chain_id);
OSMO_STRBUF_PRINTF(sb, "add chain inet %s tunmap-post-%u;\n",
OSMO_STRBUF_PRINTF(sb, "add chain inet %s mpost%u;\n",
args->table_name, from_peer->chain_id);
OSMO_STRBUF_PRINTF(sb, "add rule inet %s tunmap-post-%u",
OSMO_STRBUF_PRINTF(sb, "add rule inet %s mpost%u",
args->table_name, from_peer->chain_id);
OSMO_STRBUF_PRINTF(sb, " ip saddr set ");
OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, to_peer->addr_local);
OSMO_STRBUF_PRINTF(sb, " @ih,32,32 set 0x%x", to_peer->teid_remote);
OSMO_STRBUF_PRINTF(sb, " counter accept;\n");
OSMO_STRBUF_PRINTF(sb, "add element inet %s tunmap-pre { ",
OSMO_STRBUF_PRINTF(sb, "add element inet %s mpre { ",
args->table_name);
OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, from_peer->addr_local);
OSMO_STRBUF_PRINTF(sb, " . 0x%x : jump tunmap-pre-%u };\n",
OSMO_STRBUF_PRINTF(sb, " . 0x%x : jump mpre%u };\n",
from_peer->teid_local, from_peer->chain_id);
OSMO_STRBUF_PRINTF(sb, "add element inet %s tunmap-post { %u : jump tunmap-post-%u };\n",
OSMO_STRBUF_PRINTF(sb, "add element inet %s mpost { %u : jump mpost%u };\n",
args->table_name, from_peer->chain_id, from_peer->chain_id);
return sb.chars_needed;
@@ -227,24 +351,24 @@ static int tunmap_del_single_direction(char *buf, size_t buflen,
else
from_peer = &args->peer_b;
/* delete element inet osmo-upf tunmap-pre { 2.2.2.3 . 0x203 }
* delete element inet osmo-upf tunmap-post { 123 }
* delete chain inet osmo-upf tunmap-pre-123
* delete chain inet osmo-upf tunmap-post-123
/* delete element inet osmo-upf mpre { 2.2.2.3 . 0x203 }
* delete element inet osmo-upf mpost { 123 }
* delete chain inet osmo-upf mpre123
* delete chain inet osmo-upf mpost123
*/
OSMO_STRBUF_PRINTF(sb, "delete element inet %s tunmap-pre { ",
OSMO_STRBUF_PRINTF(sb, "delete element inet %s mpre { ",
args->table_name);
OSMO_STRBUF_APPEND(sb, osmo_sockaddr_to_str_buf2, from_peer->addr_local);
OSMO_STRBUF_PRINTF(sb, " . 0x%x };\n", from_peer->teid_local);
OSMO_STRBUF_PRINTF(sb, "delete element inet %s tunmap-post { %u };\n",
OSMO_STRBUF_PRINTF(sb, "delete element inet %s mpost { %u };\n",
args->table_name, from_peer->chain_id);
OSMO_STRBUF_PRINTF(sb, "delete chain inet %s tunmap-pre-%u;\n",
OSMO_STRBUF_PRINTF(sb, "delete chain inet %s mpre%u;\n",
args->table_name, from_peer->chain_id);
OSMO_STRBUF_PRINTF(sb, "delete chain inet %s tunmap-post-%u;\n",
OSMO_STRBUF_PRINTF(sb, "delete chain inet %s mpost%u;\n",
args->table_name, from_peer->chain_id);
return sb.chars_needed;
@@ -262,11 +386,6 @@ static int upf_nft_ruleset_tunmap_create_buf(char *buf, size_t buflen, const str
return sb.chars_needed;
}
static char *upf_nft_ruleset_tunmap_create_c(void *ctx, const struct upf_nft_args *args)
{
OSMO_NAME_C_IMPL(ctx, 1024, "ERROR", upf_nft_ruleset_tunmap_create_buf, args)
}
static int upf_nft_ruleset_tunmap_delete_buf(char *buf, size_t buflen, const struct upf_nft_args *args)
{
struct osmo_strbuf sb = { .buf = buf, .len = buflen };
@@ -279,11 +398,6 @@ static int upf_nft_ruleset_tunmap_delete_buf(char *buf, size_t buflen, const str
return sb.chars_needed;
}
static char *upf_nft_ruleset_tunmap_delete_c(void *ctx, const struct upf_nft_args *args)
{
OSMO_NAME_C_IMPL(ctx, 512, "ERROR", upf_nft_ruleset_tunmap_delete_buf, args)
}
int upf_nft_tunmap_to_str_buf(char *buf, size_t buflen, const struct upf_tunmap *tunmap)
{
struct osmo_strbuf sb = { .buf = buf, .len = buflen };
@@ -343,18 +457,28 @@ char *upf_nft_tunmap_get_vmap_init_str(void *ctx)
g_upf->tunmap.priority_post);
}
char *upf_nft_tunmap_get_ruleset_str(void *ctx, struct upf_tunmap *tunmap)
int upf_nft_tunmap_get_ruleset_str_buf(char *buf, size_t len, struct upf_tunmap *tunmap)
{
struct upf_nft_args args;
upf_nft_args_from_tunmap(&args, tunmap);
return upf_nft_ruleset_tunmap_create_c(ctx, &args);
return upf_nft_ruleset_tunmap_create_buf(buf, len, &args);
}
char *upf_nft_tunmap_get_ruleset_str(void *ctx, struct upf_tunmap *tunmap)
{
OSMO_NAME_C_IMPL(ctx, 1024, "ERROR", upf_nft_tunmap_get_ruleset_str_buf, tunmap)
}
int upf_nft_tunmap_get_ruleset_del_str_buf(char *buf, size_t len, struct upf_tunmap *tunmap)
{
struct upf_nft_args args;
upf_nft_args_from_tunmap(&args, tunmap);
return upf_nft_ruleset_tunmap_delete_buf(buf, len, &args);
}
char *upf_nft_tunmap_get_ruleset_del_str(void *ctx, struct upf_tunmap *tunmap)
{
struct upf_nft_args args;
upf_nft_args_from_tunmap(&args, tunmap);
return upf_nft_ruleset_tunmap_delete_c(ctx, &args);
OSMO_NAME_C_IMPL(ctx, 1024, "ERROR", upf_nft_tunmap_get_ruleset_del_str_buf, tunmap)
}
static int upf_nft_tunmap_ensure_chain_id(struct upf_nft_tun *tun)
@@ -372,10 +496,101 @@ int upf_nft_tunmap_create(struct upf_tunmap *tunmap)
if (upf_nft_tunmap_ensure_chain_id(&tunmap->access)
|| upf_nft_tunmap_ensure_chain_id(&tunmap->core))
return -ENOSPC;
return upf_nft_run(upf_nft_tunmap_get_ruleset_str(OTC_SELECT, tunmap));
return nft_enqueue(&g_nft_queue, upf_nft_tunmap_get_ruleset_str_buf, tunmap);
}
int upf_nft_tunmap_delete(struct upf_tunmap *tunmap)
{
return upf_nft_run(upf_nft_tunmap_get_ruleset_del_str(OTC_SELECT, tunmap));
return nft_enqueue(&g_nft_queue, upf_nft_tunmap_get_ruleset_del_str_buf, tunmap);
}
char *upf_nft_tunmap_get_ruleset_dump_all(void *ctx)
{
int rc;
const int logmax = 256;
struct nft_ctx *nft = g_upf->tunmap.nft_ctx;
char *output = NULL;
char *cmd;
if (g_upf->tunmap.mockup) {
LOGP(DNFT, LOGL_NOTICE, "tunmap/mockup active: not retrieving ruleset\n");
return 0;
}
if (!nft)
return NULL;
cmd = talloc_asprintf(g_upf, "list table inet %s", g_upf->tunmap.table_name);
rc = nft_ctx_buffer_output(nft);
if (rc) {
LOGP(DNFT, LOGL_ERROR, "error: nft_ctx_buffer_output() returned failure: rc=%d cmd=%s\n",
rc, osmo_quote_str_c(OTC_SELECT, cmd, -1));
goto unbuffer_and_exit;
}
rc = nft_run_cmd_from_buffer(nft, cmd);
if (rc < 0) {
LOGP(DNFT, LOGL_ERROR, "error running nft cmd: rc=%d cmd=%s\n",
rc, osmo_quote_str_c(OTC_SELECT, cmd, -1));
goto unbuffer_and_exit;
}
if (log_check_level(DNFT, LOGL_DEBUG)) {
size_t l = strlen(cmd);
LOGP(DNFT, LOGL_DEBUG, "ran nft cmd, %zu chars: \"%s%s\"\n",
l,
osmo_escape_cstr_c(OTC_SELECT, cmd, OSMO_MIN(logmax, l)),
l > logmax ? "..." : "");
}
output = talloc_strdup(ctx, nft_ctx_get_output_buffer(nft));
unbuffer_and_exit:
talloc_free(cmd);
nft_ctx_unbuffer_output(nft);
return output;
}
char *upf_nft_tunmap_get_ruleset_dump(void *ctx, const char *countername, uint32_t chain_id)
{
int rc;
const int logmax = 256;
struct nft_ctx *nft = g_upf->tunmap.nft_ctx;
char *output = NULL;
char *cmd;
if (g_upf->tunmap.mockup) {
LOGP(DNFT, LOGL_NOTICE, "tunmap/mockup active: not retrieving ruleset\n");
return 0;
}
if (!nft)
return NULL;
cmd = talloc_asprintf(g_upf, "list chain inet %s %s%u", g_upf->tunmap.table_name,
countername, chain_id);
rc = nft_ctx_buffer_output(nft);
if (rc) {
LOGP(DNFT, LOGL_ERROR, "error: nft_ctx_buffer_output() returned failure: rc=%d cmd=%s\n",
rc, osmo_quote_str_c(OTC_SELECT, cmd, -1));
goto unbuffer_and_exit;
}
rc = nft_run_cmd_from_buffer(nft, cmd);
if (rc < 0) {
LOGP(DNFT, LOGL_ERROR, "error running nft cmd: rc=%d cmd=%s\n",
rc, osmo_quote_str_c(OTC_SELECT, cmd, -1));
goto unbuffer_and_exit;
}
if (log_check_level(DNFT, LOGL_DEBUG)) {
size_t l = strlen(cmd);
LOGP(DNFT, LOGL_DEBUG, "ran nft cmd, %zu chars: \"%s%s\"\n",
l,
osmo_escape_cstr_c(OTC_SELECT, cmd, OSMO_MIN(logmax, l)),
l > logmax ? "..." : "");
}
output = talloc_strdup(ctx, nft_ctx_get_output_buffer(nft));
unbuffer_and_exit:
talloc_free(cmd);
nft_ctx_unbuffer_output(nft);
return output;
}

View File

@@ -336,6 +336,112 @@ DEFUN(show_nft_rule_tunmap_example, show_nft_rule_tunmap_example_cmd,
return CMD_SUCCESS;
}
DEFUN(show_nft_ruleset2, show_nft_ruleset2_cmd,
"show nft-ruleset2",
SHOW_STR "Retrieve and dump the complete nft ruleset (may be huge)\n")
{
char *ruleset;
char *pos;
char buf1[64];
char buf2[64];
vty_out(vty, "Retrieving ruleset...%s", VTY_NEWLINE);
ruleset = upf_nft_tunmap_get_ruleset_dump_all(g_upf);
pos = ruleset;
while (*pos) {
char *chain, *chain_end;
char *counter, *counter_end;
chain = strstr(pos, "chain mp");
if (!chain)
break;
chain += 6;
chain_end = strstr(chain, " {");
if (!chain_end)
break;
counter = strstr(chain_end, "counter packets ");
if (!counter)
break;
counter += 8;
counter_end = strstr(counter, " accept");
if (!counter_end)
break;
osmo_escape_cstr_buf(buf1, sizeof(buf1), chain, chain_end - chain);
osmo_escape_cstr_buf(buf2, sizeof(buf2), counter, counter_end - counter);
vty_out(vty, "%s %s%s", buf1, buf2, VTY_NEWLINE);
pos = counter_end;
}
talloc_free(ruleset);
return CMD_SUCCESS;
}
DEFUN(show_nft_ruleset, show_nft_ruleset_cmd,
"show nft-ruleset",
SHOW_STR "Retrieve and dump the complete nft ruleset (may be huge)\n")
{
char *ruleset;
char *pos;
char buf1[64];
char buf2[64];
vty_out(vty, "Retrieving ruleset...%s", VTY_NEWLINE);
struct up_peer *peer;
llist_for_each_entry(peer, &g_upf->pfcp.ep->peers, entry) {
struct up_session *session;
int bkt;
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;
const char *ctrs[] = { "mpre", "mpost" };
const uint32_t chain_ids[] = { a->tunmap.access.chain_id, a->tunmap.core.chain_id };
for (int j = 0; j < 2; j++)
for (int i = 0; i < 2; i++) {
ruleset = upf_nft_tunmap_get_ruleset_dump(g_upf, ctrs[i], chain_ids[j]);
pos = ruleset;
while (*pos) {
char *chain, *chain_end;
char *counter, *counter_end;
chain = strstr(pos, "chain mp");
if (!chain)
break;
chain += 6;
chain_end = strstr(chain, " {");
if (!chain_end)
break;
counter = strstr(chain_end, "counter packets ");
if (!counter)
break;
counter += 8;
counter_end = strstr(counter, " accept");
if (!counter_end)
break;
osmo_escape_cstr_buf(buf1, sizeof(buf1), chain, chain_end - chain);
osmo_escape_cstr_buf(buf2, sizeof(buf2), counter, counter_end - counter);
vty_out(vty, "%s %s%s", buf1, buf2, VTY_NEWLINE);
pos = counter_end;
}
talloc_free(ruleset);
}
}
}
}
return CMD_SUCCESS;
}
static struct cmd_node cfg_netinst_node = {
NETINST_NODE,
"%s(config-netinst)# ",
@@ -495,6 +601,8 @@ void upf_vty_init()
install_element_ve(&show_session_cmd);
install_element_ve(&show_netinst_cmd);
install_element_ve(&show_nft_rule_append_cmd);
install_element_ve(&show_nft_ruleset_cmd);
install_element_ve(&show_nft_ruleset2_cmd);
install_node(&cfg_pfcp_node, config_write_pfcp);
install_element(CONFIG_NODE, &cfg_pfcp_cmd);

View File

@@ -4,7 +4,7 @@ OsmoUPF(config)# tunmap
OsmoUPF(config-tunmap)# show nft-rule tunmap example
% init verdict map:
add table inet osmo-upf { flags owner; };
add table inet osmo-upf { };
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; };

View File

@@ -8,18 +8,18 @@ DLPFCP NOTICE PFCP endpoint: recovery timestamp = 0x83aa7e80 (0 seconds since UN
[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 DEBUG ran nft ruleset, 42 chars: "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;
add map inet osmo-upf mpre { typeof ip daddr . @ih,32,32 : verdict; };
add map inet osmo-upf mpost { typeof meta mark : verdict; };
add rule inet osmo-upf pre udp dport 2152 ip daddr . @ih,32,32 vmap @mpre;
add rule inet osmo-upf post meta mark vmap @mpost;
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"
DNFT DEBUG ran nft ruleset, 441 chars: "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 mpre { typeof ip daddr . @ih,32,32 : verdict; };\nad..."
PFCP Associate peer
DPEER DEBUG up_peer{NOT_ASSOCIATED}: Allocated
@@ -58,22 +58,25 @@ DSESSION DEBUG up_session(1-2-3-4-0x1){INIT}: Active PDR set: + PDR-1{src:Core T
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
DNFT INFO Added NFT ruleset to queue: n:1 strlen:701
DNFT INFO Flushing NFT ruleset queue: reached max nr of rules: n:1 strlen:701 (flush count: 1 avg rules per flush: 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 };
add chain inet osmo-upf mpre1;
add rule inet osmo-upf mpre1 ip daddr set 13.14.15.16 meta mark set 1 counter accept;
add chain inet osmo-upf mpost1;
add rule inet osmo-upf mpost1 ip saddr set 1.1.1.1 @ih,32,32 set 0x101 counter accept;
add element inet osmo-upf mpre { 1.1.1.1 . 0x2 : jump mpre1 };
add element inet osmo-upf mpost { 1 : jump mpost1 };
add chain inet osmo-upf mpre2;
add rule inet osmo-upf mpre2 ip daddr set 5.6.7.8 meta mark set 2 counter accept;
add chain inet osmo-upf mpost2;
add rule inet osmo-upf mpost2 ip saddr set 1.1.1.1 @ih,32,32 set 0x100 counter accept;
add element inet osmo-upf mpre { 1.1.1.1 . 0x1 : jump mpre2 };
add element inet osmo-upf mpost { 2 : jump mpost2 };
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"
DNFT DEBUG ran nft ruleset, 701 chars: "add chain inet osmo-upf mpre1;\nadd rule inet osmo-upf mpre1 ip daddr set 13.14.15.16 meta mark set 1 counter accept;\nadd chain inet osmo-upf mpost1;\nadd rule inet osmo-upf mpost1 ip saddr set 1.1.1.1 @ih,32,32 set 0x101 counter accept;\nadd element inet osm..."
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:
@@ -123,22 +126,25 @@ DSESSION DEBUG up_session(1-2-3-4-0x2){INIT}: Active PDR set: + PDR-1{src:Core T
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
DNFT INFO Added NFT ruleset to queue: n:1 strlen:701
DNFT INFO Flushing NFT ruleset queue: reached max nr of rules: n:1 strlen:701 (flush count: 2 avg rules per flush: 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 0x103 counter accept;
add element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x4 : 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 0x102 counter accept;
add element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x3 : jump tunmap-pre-4 };
add element inet osmo-upf tunmap-post { 4 : jump tunmap-post-4 };
add chain inet osmo-upf mpre3;
add rule inet osmo-upf mpre3 ip daddr set 13.14.15.16 meta mark set 3 counter accept;
add chain inet osmo-upf mpost3;
add rule inet osmo-upf mpost3 ip saddr set 1.1.1.1 @ih,32,32 set 0x103 counter accept;
add element inet osmo-upf mpre { 1.1.1.1 . 0x4 : jump mpre3 };
add element inet osmo-upf mpost { 3 : jump mpost3 };
add chain inet osmo-upf mpre4;
add rule inet osmo-upf mpre4 ip daddr set 5.6.7.8 meta mark set 4 counter accept;
add chain inet osmo-upf mpost4;
add rule inet osmo-upf mpost4 ip saddr set 1.1.1.1 @ih,32,32 set 0x102 counter accept;
add element inet osmo-upf mpre { 1.1.1.1 . 0x3 : jump mpre4 };
add element inet osmo-upf mpost { 4 : jump mpost4 };
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 0x103 counter accept;\nadd element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x4 : 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 0x102 counter accept;\nadd element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x3 : jump tunmap-pre-4 };\nadd element inet osmo-upf tunmap-post { 4 : jump tunmap-post-4 };\n"
DNFT DEBUG ran nft ruleset, 701 chars: "add chain inet osmo-upf mpre3;\nadd rule inet osmo-upf mpre3 ip daddr set 13.14.15.16 meta mark set 3 counter accept;\nadd chain inet osmo-upf mpost3;\nadd rule inet osmo-upf mpost3 ip saddr set 1.1.1.1 @ih,32,32 set 0x103 counter accept;\nadd element inet osm..."
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--3-> <-4--core
[test override] PFCP tx:
@@ -182,18 +188,21 @@ DSESSION DEBUG up_session(1-2-3-4-0x1){ESTABLISHED}: Received Event UP_SESSION_E
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
DNFT INFO Added NFT ruleset to queue: n:1 strlen:329
DNFT INFO Flushing NFT ruleset queue: reached max nr of rules: n:1 strlen:329 (flush count: 3 avg rules per flush: 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;
delete element inet osmo-upf mpre { 1.1.1.1 . 0x2 };
delete element inet osmo-upf mpost { 1 };
delete chain inet osmo-upf mpre1;
delete chain inet osmo-upf mpost1;
delete element inet osmo-upf mpre { 1.1.1.1 . 0x1 };
delete element inet osmo-upf mpost { 2 };
delete chain inet osmo-upf mpre2;
delete chain inet osmo-upf mpost2;
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"
DNFT DEBUG ran nft ruleset, 329 chars: "delete element inet osmo-upf mpre { 1.1.1.1 . 0x2 };\ndelete element inet osmo-upf mpost { 1 };\ndelete chain inet osmo-upf mpre1;\ndelete chain inet osmo-upf mpost1;\ndelete element inet osmo-upf mpre { 1.1.1.1 . 0x1 };\ndelete element inet osmo-upf mpost { 2 ..."
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
@@ -231,22 +240,25 @@ DSESSION DEBUG up_session(1-2-3-4-0x1){INIT}: Active PDR set: + PDR-1{src:Core T
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
DNFT INFO Added NFT ruleset to queue: n:1 strlen:701
DNFT INFO Flushing NFT ruleset queue: reached max nr of rules: n:1 strlen:701 (flush count: 4 avg rules per flush: 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 };
add chain inet osmo-upf mpre1;
add rule inet osmo-upf mpre1 ip daddr set 13.14.15.16 meta mark set 1 counter accept;
add chain inet osmo-upf mpost1;
add rule inet osmo-upf mpost1 ip saddr set 1.1.1.1 @ih,32,32 set 0x105 counter accept;
add element inet osmo-upf mpre { 1.1.1.1 . 0x2 : jump mpre1 };
add element inet osmo-upf mpost { 1 : jump mpost1 };
add chain inet osmo-upf mpre2;
add rule inet osmo-upf mpre2 ip daddr set 5.6.7.8 meta mark set 2 counter accept;
add chain inet osmo-upf mpost2;
add rule inet osmo-upf mpost2 ip saddr set 1.1.1.1 @ih,32,32 set 0x104 counter accept;
add element inet osmo-upf mpre { 1.1.1.1 . 0x1 : jump mpre2 };
add element inet osmo-upf mpost { 2 : jump mpost2 };
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"
DNFT DEBUG ran nft ruleset, 701 chars: "add chain inet osmo-upf mpre1;\nadd rule inet osmo-upf mpre1 ip daddr set 13.14.15.16 meta mark set 1 counter accept;\nadd chain inet osmo-upf mpost1;\nadd rule inet osmo-upf mpost1 ip saddr set 1.1.1.1 @ih,32,32 set 0x105 counter accept;\nadd element inet osm..."
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:
@@ -296,22 +308,25 @@ DSESSION DEBUG up_session(1-2-3-4-0x3){INIT}: Active PDR set: + PDR-1{src:Core T
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
DNFT INFO Added NFT ruleset to queue: n:1 strlen:701
DNFT INFO Flushing NFT ruleset queue: reached max nr of rules: n:1 strlen:701 (flush count: 5 avg rules per flush: 1)
[test override] nft_run_cmd_from_buffer():
add chain inet osmo-upf tunmap-pre-5;
add rule inet osmo-upf tunmap-pre-5 ip daddr set 13.14.15.16 meta mark set 5 counter accept;
add chain inet osmo-upf tunmap-post-5;
add rule inet osmo-upf tunmap-post-5 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-5 };
add element inet osmo-upf tunmap-post { 5 : jump tunmap-post-5 };
add chain inet osmo-upf tunmap-pre-6;
add rule inet osmo-upf tunmap-pre-6 ip daddr set 5.6.7.8 meta mark set 6 counter accept;
add chain inet osmo-upf tunmap-post-6;
add rule inet osmo-upf tunmap-post-6 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-6 };
add element inet osmo-upf tunmap-post { 6 : jump tunmap-post-6 };
add chain inet osmo-upf mpre5;
add rule inet osmo-upf mpre5 ip daddr set 13.14.15.16 meta mark set 5 counter accept;
add chain inet osmo-upf mpost5;
add rule inet osmo-upf mpost5 ip saddr set 1.1.1.1 @ih,32,32 set 0x107 counter accept;
add element inet osmo-upf mpre { 1.1.1.1 . 0x6 : jump mpre5 };
add element inet osmo-upf mpost { 5 : jump mpost5 };
add chain inet osmo-upf mpre6;
add rule inet osmo-upf mpre6 ip daddr set 5.6.7.8 meta mark set 6 counter accept;
add chain inet osmo-upf mpost6;
add rule inet osmo-upf mpost6 ip saddr set 1.1.1.1 @ih,32,32 set 0x106 counter accept;
add element inet osmo-upf mpre { 1.1.1.1 . 0x5 : jump mpre6 };
add element inet osmo-upf mpost { 6 : jump mpost6 };
DNFT DEBUG run nft ruleset: "add chain inet osmo-upf tunmap-pre-5;\nadd rule inet osmo-upf tunmap-pre-5 ip daddr set 13.14.15.16 meta mark set 5 counter accept;\nadd chain inet osmo-upf tunmap-post-5;\nadd rule inet osmo-upf tunmap-post-5 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-5 };\nadd element inet osmo-upf tunmap-post { 5 : jump tunmap-post-5 };\nadd chain inet osmo-upf tunmap-pre-6;\nadd rule inet osmo-upf tunmap-pre-6 ip daddr set 5.6.7.8 meta mark set 6 counter accept;\nadd chain inet osmo-upf tunmap-post-6;\nadd rule inet osmo-upf tunmap-post-6 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-6 };\nadd element inet osmo-upf tunmap-post { 6 : jump tunmap-post-6 };\n"
DNFT DEBUG ran nft ruleset, 701 chars: "add chain inet osmo-upf mpre5;\nadd rule inet osmo-upf mpre5 ip daddr set 13.14.15.16 meta mark set 5 counter accept;\nadd chain inet osmo-upf mpost5;\nadd rule inet osmo-upf mpost5 ip saddr set 1.1.1.1 @ih,32,32 set 0x107 counter accept;\nadd element inet osm..."
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--5-> <-6--core
[test override] PFCP tx:
@@ -348,18 +363,21 @@ DSESSION DEBUG up_session(1-2-3-4-0x3){ESTABLISHED}: Removing from parent up_pee
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
DNFT INFO Added NFT ruleset to queue: n:1 strlen:329
DNFT INFO Flushing NFT ruleset queue: reached max nr of rules: n:1 strlen:329 (flush count: 6 avg rules per flush: 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 { 5 };
delete chain inet osmo-upf tunmap-pre-5;
delete chain inet osmo-upf tunmap-post-5;
delete element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x5 };
delete element inet osmo-upf tunmap-post { 6 };
delete chain inet osmo-upf tunmap-pre-6;
delete chain inet osmo-upf tunmap-post-6;
delete element inet osmo-upf mpre { 1.1.1.1 . 0x6 };
delete element inet osmo-upf mpost { 5 };
delete chain inet osmo-upf mpre5;
delete chain inet osmo-upf mpost5;
delete element inet osmo-upf mpre { 1.1.1.1 . 0x5 };
delete element inet osmo-upf mpost { 6 };
delete chain inet osmo-upf mpre6;
delete chain inet osmo-upf mpost6;
DNFT DEBUG run nft ruleset: "delete element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x6 };\ndelete element inet osmo-upf tunmap-post { 5 };\ndelete chain inet osmo-upf tunmap-pre-5;\ndelete chain inet osmo-upf tunmap-post-5;\ndelete element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x5 };\ndelete element inet osmo-upf tunmap-post { 6 };\ndelete chain inet osmo-upf tunmap-pre-6;\ndelete chain inet osmo-upf tunmap-post-6;\n"
DNFT DEBUG ran nft ruleset, 329 chars: "delete element inet osmo-upf mpre { 1.1.1.1 . 0x6 };\ndelete element inet osmo-upf mpost { 5 };\ndelete chain inet osmo-upf mpre5;\ndelete chain inet osmo-upf mpost5;\ndelete element inet osmo-upf mpre { 1.1.1.1 . 0x5 };\ndelete element inet osmo-upf mpost { 6 ..."
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--5-> <-6--core
DSESSION DEBUG up_session(1-2-3-4-0x3){ESTABLISHED}: Freeing instance
DSESSION DEBUG up_session(1-2-3-4-0x3){ESTABLISHED}: Deallocated
@@ -368,18 +386,21 @@ DSESSION DEBUG up_session(1-2-3-4-0x1){ESTABLISHED}: Removing from parent up_pee
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
DNFT INFO Added NFT ruleset to queue: n:1 strlen:329
DNFT INFO Flushing NFT ruleset queue: reached max nr of rules: n:1 strlen:329 (flush count: 7 avg rules per flush: 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;
delete element inet osmo-upf mpre { 1.1.1.1 . 0x2 };
delete element inet osmo-upf mpost { 1 };
delete chain inet osmo-upf mpre1;
delete chain inet osmo-upf mpost1;
delete element inet osmo-upf mpre { 1.1.1.1 . 0x1 };
delete element inet osmo-upf mpost { 2 };
delete chain inet osmo-upf mpre2;
delete chain inet osmo-upf mpost2;
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"
DNFT DEBUG ran nft ruleset, 329 chars: "delete element inet osmo-upf mpre { 1.1.1.1 . 0x2 };\ndelete element inet osmo-upf mpost { 1 };\ndelete chain inet osmo-upf mpre1;\ndelete chain inet osmo-upf mpost1;\ndelete element inet osmo-upf mpre { 1.1.1.1 . 0x1 };\ndelete element inet osmo-upf mpost { 2 ..."
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
@@ -388,18 +409,21 @@ DSESSION DEBUG up_session(1-2-3-4-0x2){ESTABLISHED}: Removing from parent up_pee
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
DNFT INFO Added NFT ruleset to queue: n:1 strlen:329
DNFT INFO Flushing NFT ruleset queue: reached max nr of rules: n:1 strlen:329 (flush count: 8 avg rules per flush: 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 { 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 . 0x3 };
delete element inet osmo-upf tunmap-post { 4 };
delete chain inet osmo-upf tunmap-pre-4;
delete chain inet osmo-upf tunmap-post-4;
delete element inet osmo-upf mpre { 1.1.1.1 . 0x4 };
delete element inet osmo-upf mpost { 3 };
delete chain inet osmo-upf mpre3;
delete chain inet osmo-upf mpost3;
delete element inet osmo-upf mpre { 1.1.1.1 . 0x3 };
delete element inet osmo-upf mpost { 4 };
delete chain inet osmo-upf mpre4;
delete chain inet osmo-upf mpost4;
DNFT DEBUG run nft ruleset: "delete element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x4 };\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 . 0x3 };\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"
DNFT DEBUG ran nft ruleset, 329 chars: "delete element inet osmo-upf mpre { 1.1.1.1 . 0x4 };\ndelete element inet osmo-upf mpost { 3 };\ndelete chain inet osmo-upf mpre3;\ndelete chain inet osmo-upf mpost3;\ndelete element inet osmo-upf mpre { 1.1.1.1 . 0x3 };\ndelete element inet osmo-upf mpost { 4 ..."
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--3-> <-4--core
DSESSION DEBUG up_session(1-2-3-4-0x2){ESTABLISHED}: Freeing instance
DSESSION DEBUG up_session(1-2-3-4-0x2){ESTABLISHED}: Deallocated