18 Commits

Author SHA1 Message Date
Neels Janosch Hofmeyr
72c4a50d46 perf fu
Change-Id: I5f2acfe14d3dbffa96aab00870b094a9486f414e
2024-07-31 06:32:29 +02:00
Neels Janosch Hofmeyr
e13cb5dd75 perf fu
Change-Id: Ib9b85bc63a1ac0d668fd75cd504076c7282c764c
2024-07-31 06:32:29 +02:00
Neels Janosch Hofmeyr
9823f45c96 tunend.vty
Change-Id: I5cfe47abfd3c9a13f6191922f31b39e5c562a1a8
2024-07-31 06:32:29 +02:00
Neels Janosch Hofmeyr
518757d962 perf fu
Change-Id: Ie59b53b88a77a2e6535887ca7ae697cca7d01d27
2024-07-31 06:32:29 +02:00
Neels Janosch Hofmeyr
0b49cc8aa6 perf
Change-Id: I85379b2a5987bc0e4d4bf55ae4ed3407bdd1adac
2024-07-31 06:32:29 +02:00
Neels Janosch Hofmeyr
07d66468ea perf
Change-Id: I041a6dc9096d7a740eaf1c1c67ef6b0eb156b831
2024-07-31 06:32:29 +02:00
Neels Janosch Hofmeyr
ff2b29e303 perf
Change-Id: If03c1de7cff15874d229449254ebe4726d65dc92
2024-07-31 06:32:29 +02:00
Neels Janosch Hofmeyr
feca23d45f contrib/perf/bpftrace.txt: separate id lookups from nft
Change-Id: Ic821b3a2375f91d5ad1becde8239481e11be5f5b
2024-07-31 06:32:29 +02:00
Neels Janosch Hofmeyr
47f2da0cf4 bpftrace probing
Change-Id: I2717b736e23552bffe1492604cbd073f22977c84
2024-07-31 06:32:29 +02:00
Neels Janosch Hofmeyr
0fd645dbfc gtp_probe
Change-Id: I051f5e56c73593090c783e522b1fbdd17ed6b059
2024-07-31 06:32:29 +02:00
Neels Janosch Hofmeyr
7dc16bc375 move pfcp_tool.h to include/osmocom/pfcptool/
Change-Id: If3e7cc4df3defd08df9e75965715a1be0388ed01
2024-07-31 06:32:29 +02:00
Neels Janosch Hofmeyr
95e9e2ee2d nft: batch nftables commands
Change-Id: Ib0a8e86b29bab1559d94fc55a89daa00ec670318
2024-07-31 06:31:52 +02:00
Neels Janosch Hofmeyr
f9e430258b 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-07-31 06:31:48 +02:00
Neels Janosch Hofmeyr
d201ec157b n-sessions
Change-Id: I74a21cc31296ab89a2acda1da8ae9693c1992e66
2024-07-31 06:31:48 +02:00
Neels Janosch Hofmeyr
05e8472ed9 n-sessions: add poll arg to pfcp_tool_mainloop()
Allow calling in non-blocking mode, prepare for N sessions.

Change-Id: I20bb2803b28681face18ee665d8a1aad06d58091
2024-07-31 06:31:03 +02:00
Neels Janosch Hofmeyr
b69b742e21 n-sessions: generalize function args
Change some VTY DEFUN into generally callable functions. Prepare for N
sessions commands.

Change-Id: I112206049e704b7adad7072b1f7953f7ee4f18ca
2024-07-31 06:31:03 +02:00
Neels Janosch Hofmeyr
6c77f4d184 n-sessions: add generators for TEID and UE IP
Change-Id: Iec164a222782d382aefe8d0342f398ebba1eac05
2024-07-31 06:30:55 +02:00
Neels Janosch Hofmeyr
8cbe5cd3ee use fixed PDR id for access and core
Makes it easier to find the right one later.

Change-Id: Ic343494001c70a84f3402ce5749d08e729551b26
2024-07-31 06:30:44 +02:00
25 changed files with 1487 additions and 86 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

54
contrib/perf/gen_bpftrace.py Executable file
View File

@@ -0,0 +1,54 @@
#!/usr/bin/env python3
import sys
args = sys.argv[1:]
output = []
lib = None
probes = set()
for arg in args:
if arg.startswith('/'):
lib = arg
continue
func = arg
#identifier = '%s-%s' % (lib, func)
identifier = func
identifier = ''.join([c if c.isalpha() else '_' for c in identifier])
identifier.replace('__', '_')
probes.add((lib, func, identifier))
for lib, func, identifier in probes:
output.append(
f'''uprobe:{lib}:{func} {{
@{identifier}__count ++;
@{identifier}__start = nsecs;
}}
uretprobe:{lib}:{func} {{
${identifier}__duration_ns = (nsecs - @{identifier}__start);
@{identifier}__total_ns += ${identifier}__duration_ns;
@{identifier}__total_ms = @{identifier}__total_ns / 1000000;
${identifier}__duration_us = ${identifier}__duration_ns / 1000;
@{identifier}__us = hist(${identifier}__duration_us);
}}''')
output.append(
'''interval:s:3 {
printf("==========================================================");
time("%Y-%m-%d %H:%M:%S\\n");''')
for lib, func, identifier in probes:
output.append(f' print(@{identifier}__count);');
output.append(f' print(@{identifier}__total_ms);');
output.append(f' print(@{identifier}__us);');
output.append('}')
print('\n'.join(output))

View File

@@ -0,0 +1,49 @@
==========================================================2024-05-05 19:16:44
@nft_evaluate__us:
[1K, 2K) 111 |@@@@ |
[2K, 4K) 333 |@@@@@@@@@@@@ |
[4K, 8K) 589 |@@@@@@@@@@@@@@@@@@@@@@ |
[8K, 16K) 1382 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[16K, 32K) 585 |@@@@@@@@@@@@@@@@@@@@@@ |
@nft_evaluate__count: 3000
@nft_cache_update__us:
[512, 1K) 21 | |
[1K, 2K) 138 |@@@@@ |
[2K, 4K) 324 |@@@@@@@@@@@@ |
[4K, 8K) 597 |@@@@@@@@@@@@@@@@@@@@@@ |
[8K, 16K) 1395 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[16K, 32K) 525 |@@@@@@@@@@@@@@@@@@@ |
@nft_cache_update__count: 3000
@nft_cache_is_complete__us:
[2, 4) 974 |@@@@@@@@@@@@@@@@@@@@@@@@@ |
[4, 8) 1983 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[8, 16) 26 | |
[16, 32) 17 | |
@nft_cache_is_complete__count: 3000
@nft_cache_is_updated__us:
[2, 4) 1684 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[4, 8) 1285 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
[8, 16) 18 | |
[16, 32) 10 | |
@nft_cache_is_updated__count: 2997
@nft_cache_release__us:
[32, 64) 15 | |
[64, 128) 38 |@ |
[128, 256) 88 |@@@@ |
[256, 512) 171 |@@@@@@@@ |
[512, 1K) 192 |@@@@@@@@@ |
[1K, 2K) 498 |@@@@@@@@@@@@@@@@@@@@@@@@ |
[2K, 4K) 1065 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[4K, 8K) 852 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ |
[8K, 16K) 81 |@@@ |
@nft_cache_release__count: 3000
==========================================================2024-05-05 19:16:47

View File

@@ -0,0 +1,53 @@
==========================================================2024-05-05 19:10:38
@nft_evaluate__us:
[512, 1K) 21 | |
[1K, 2K) 264 |@@@@ |
[2K, 4K) 634 |@@@@@@@@@@@ |
[4K, 8K) 1397 |@@@@@@@@@@@@@@@@@@@@@@@@@ |
[8K, 16K) 2844 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[16K, 32K) 837 |@@@@@@@@@@@@@@@ |
[32K, 64K) 3 | |
@nft_evaluate__count: 6000
@nft_cache_filter_init__us:
[128, 256) 5985 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[256, 512) 9 | |
[512, 1K) 6 | |
@nft_cache_filter_init__count: 6000
@nft_cache_evaluate__us:
[2, 4) 536 |@@@@@ |
[4, 8) 5237 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[8, 16) 150 |@ |
[16, 32) 77 | |
@nft_cache_evaluate__count: 6000
@nft_cache_update__us:
[512, 1K) 107 |@ |
[1K, 2K) 289 |@@@@@ |
[2K, 4K) 651 |@@@@@@@@@@@ |
[4K, 8K) 1408 |@@@@@@@@@@@@@@@@@@@@@@@@@ |
[8K, 16K) 2828 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[16K, 32K) 714 |@@@@@@@@@@@@@ |
[32K, 64K) 3 | |
@nft_cache_update__count: 6000
@nft_cache_filter_fini__us:
[32, 64) 5841 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[64, 128) 135 |@ |
[128, 256) 0 | |
[256, 512) 0 | |
[512, 1K) 0 | |
[1K, 2K) 0 | |
[2K, 4K) 21 | |
[4K, 8K) 3 | |
@nft_cache_filter_fini__count: 6000
@nft_cmd_expand__us:
[1] 720 |@ |
[2, 4) 33583 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|
[4, 8) 1551 |@@ |
[8, 16) 83 | |
[16, 32) 63 | |
@nft_cmd_expand__count: 36000

139
contrib/perf/now.bt Normal file
View File

@@ -0,0 +1,139 @@
uprobe:/usr/local/lib/libnftables.*:flowtable_free {
@flowtable_free__count ++;
@flowtable_free__start = nsecs;
}
uretprobe:/usr/local/lib/libnftables.*:flowtable_free {
$flowtable_free__duration_ns = (nsecs - @flowtable_free__start);
@flowtable_free__total_ns += $flowtable_free__duration_ns;
@flowtable_free__total_ms = @flowtable_free__total_ns / 1000000;
$flowtable_free__duration_us = $flowtable_free__duration_ns / 1000;
@flowtable_free__us = hist($flowtable_free__duration_us);
}
uprobe:/usr/local/lib/libnftables.*:free_const {
@free_const__count ++;
@free_const__start = nsecs;
}
uretprobe:/usr/local/lib/libnftables.*:free_const {
$free_const__duration_ns = (nsecs - @free_const__start);
@free_const__total_ns += $free_const__duration_ns;
@free_const__total_ms = @free_const__total_ns / 1000000;
$free_const__duration_us = $free_const__duration_ns / 1000;
@free_const__us = hist($free_const__duration_us);
}
uprobe:/usr/local/lib/libnftables.*:chain_free {
@chain_free__count ++;
@chain_free__start = nsecs;
}
uretprobe:/usr/local/lib/libnftables.*:chain_free {
$chain_free__duration_ns = (nsecs - @chain_free__start);
@chain_free__total_ns += $chain_free__duration_ns;
@chain_free__total_ms = @chain_free__total_ns / 1000000;
$chain_free__duration_us = $chain_free__duration_ns / 1000;
@chain_free__us = hist($chain_free__duration_us);
}
uprobe:/usr/local/lib/libnftables.*:cache_free {
@cache_free__count ++;
@cache_free__start = nsecs;
}
uretprobe:/usr/local/lib/libnftables.*:cache_free {
$cache_free__duration_ns = (nsecs - @cache_free__start);
@cache_free__total_ns += $cache_free__duration_ns;
@cache_free__total_ms = @cache_free__total_ns / 1000000;
$cache_free__duration_us = $cache_free__duration_ns / 1000;
@cache_free__us = hist($cache_free__duration_us);
}
uprobe:/usr/local/lib/libnftables.*:scope_release {
@scope_release__count ++;
@scope_release__start = nsecs;
}
uretprobe:/usr/local/lib/libnftables.*:scope_release {
$scope_release__duration_ns = (nsecs - @scope_release__start);
@scope_release__total_ns += $scope_release__duration_ns;
@scope_release__total_ms = @scope_release__total_ns / 1000000;
$scope_release__duration_us = $scope_release__duration_ns / 1000;
@scope_release__us = hist($scope_release__duration_us);
}
uprobe:/usr/local/lib/libnftables.*:set_free {
@set_free__count ++;
@set_free__start = nsecs;
}
uretprobe:/usr/local/lib/libnftables.*:set_free {
$set_free__duration_ns = (nsecs - @set_free__start);
@set_free__total_ns += $set_free__duration_ns;
@set_free__total_ms = @set_free__total_ns / 1000000;
$set_free__duration_us = $set_free__duration_ns / 1000;
@set_free__us = hist($set_free__duration_us);
}
uprobe:/usr/local/lib/libnftables.*:handle_free {
@handle_free__count ++;
@handle_free__start = nsecs;
}
uretprobe:/usr/local/lib/libnftables.*:handle_free {
$handle_free__duration_ns = (nsecs - @handle_free__start);
@handle_free__total_ns += $handle_free__duration_ns;
@handle_free__total_ms = @handle_free__total_ns / 1000000;
$handle_free__duration_us = $handle_free__duration_ns / 1000;
@handle_free__us = hist($handle_free__duration_us);
}
uprobe:/usr/local/lib/libnftables.*:obj_free {
@obj_free__count ++;
@obj_free__start = nsecs;
}
uretprobe:/usr/local/lib/libnftables.*:obj_free {
$obj_free__duration_ns = (nsecs - @obj_free__start);
@obj_free__total_ns += $obj_free__duration_ns;
@obj_free__total_ms = @obj_free__total_ns / 1000000;
$obj_free__duration_us = $obj_free__duration_ns / 1000;
@obj_free__us = hist($obj_free__duration_us);
}
uprobe:/usr/lib/x86_64-linux-gnu/libc.*:free {
@free__count ++;
@free__start = nsecs;
}
uretprobe:/usr/lib/x86_64-linux-gnu/libc.*:free {
$free__duration_ns = (nsecs - @free__start);
@free__total_ns += $free__duration_ns;
@free__total_ms = @free__total_ns / 1000000;
$free__duration_us = $free__duration_ns / 1000;
@free__us = hist($free__duration_us);
}
interval:s:3 {
printf("==========================================================");
time("%Y-%m-%d %H:%M:%S\n");
print(@flowtable_free__count);
print(@flowtable_free__total_ms);
print(@flowtable_free__us);
print(@free_const__count);
print(@free_const__total_ms);
print(@free_const__us);
print(@chain_free__count);
print(@chain_free__total_ms);
print(@chain_free__us);
print(@cache_free__count);
print(@cache_free__total_ms);
print(@cache_free__us);
print(@scope_release__count);
print(@scope_release__total_ms);
print(@scope_release__us);
print(@set_free__count);
print(@set_free__total_ms);
print(@set_free__us);
print(@handle_free__count);
print(@handle_free__total_ms);
print(@handle_free__us);
print(@obj_free__count);
print(@obj_free__total_ms);
print(@obj_free__us);
print(@free__count);
print(@free__total_ms);
print(@free__us);
}

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

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

@@ -0,0 +1,27 @@
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 error
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

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

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

@@ -0,0 +1,7 @@
pfcp-peer 127.0.0.1
tx assoc-setup-req
sleep 1
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.*: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.*: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.*: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.*:osmo_pfcp_fd_write_cb {
@pfcp_write_cb_start_at = nsecs;
@pfcp_write_cb_us_val = (uint64)0;
}
uretprobe:/usr/local/lib/libosmo-pfcp.*: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.*:osmo_pfcp_endpoint_tx_data_no_logging {
@pfcp_tx_start_at = nsecs;
@pfcp_tx_us_val = (uint64)0;
}
uretprobe:/usr/local/lib/libosmo-pfcp.*: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.*: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);
}

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

@@ -0,0 +1,46 @@
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.*: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.*: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/libnftables.*:nft_parse_bison_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.*:nft_parse_bison_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);
}
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);
}

19
contrib/perf/upftrace.sh Executable file
View File

@@ -0,0 +1,19 @@
#!/bin/sh
./gen_bpftrace.py \
"/usr/local/lib/libnftables.*" \
\
free_const \
chain_free \
set_free \
flowtable_free \
flowtable_free \
obj_free \
handle_free \
scope_release \
cache_free \
"/usr/lib/x86_64-linux-gnu/libc.*" free \
\
> now.bt
cat now.bt
sudo bpftrace now.bt

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,28 @@
#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(struct gtp_probe_state *s, struct pfcp_tool_gtp_tun *inject_gtp,
struct osmo_sockaddr_str *ue_ip,
struct gtp_probe_target *expect_ip);

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;
@@ -57,6 +58,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 +102,11 @@ struct g_pfcp_tool {
struct osmo_pfcp_endpoint *ep;
struct llist_head peers;
uint32_t next_teid_state;
uint32_t next_ue_addr_state;
struct gtp_probe_state gtp_probe;
};
extern struct g_pfcp_tool *g_pfcp_tool;
@@ -108,7 +115,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 +124,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

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

View File

@@ -0,0 +1,233 @@
/*
* (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>
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){};
}
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];
struct udphdr *h = (void *)rxbuf;
if (!(what & OSMO_FD_READ))
return 0;
rc = recvfrom(ofd->fd, rxbuf, sizeof(rxbuf), 0, (struct sockaddr *)&remote, &remote_len);
if (rc <= 0)
return -EIO;
osmo_sockaddr_str_from_sockaddr(&remote_str, &remote.u.sas);
size_t len = ntohl(h->len);
uint8_t *data = rxbuf + sizeof(*h);
size_t data_len = len - sizeof(*h);
if (ofd->priv_nr)
osmo_escape_cstr_buf(strbuf, sizeof(strbuf), (char *)data, data_len);
else
osmo_hexdump_buf(strbuf, sizeof(strbuf), data, data_len, NULL, false);
LOGP(DLGLOBAL, LOGL_NOTICE,
"Probe RX: " OSMO_SOCKADDR_STR_FMT " -> " OSMO_SOCKADDR_STR_FMT " '%s'\n",
OSMO_SOCKADDR_STR_FMT_ARGS(&remote_str),
OSMO_SOCKADDR_STR_FMT_ARGS(&s->ip_target.cfg),
strbuf);
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(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;
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 = 1234, // TODO
.frag_off = htons(0x4000),
.ttl = 64,
.protocol = IPPROTO_UDP,
.check = 0, // TODO
},
.udp = {
.source = htons(payload_src.port),
.dest = htons(payload_dst->port),
.check = 0, // TODO
},
.data = "hello!",
};
size_t data_len = strlen(pdu.data) + 1;
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);
LOGP(DLGLOBAL, LOGL_NOTICE, "GTP-probe: sending payload GTP{%zu IP{%zu UDP{%zu {%zu %s} } } }\n",
gtp_len, ip_len, udp_len, data_len, osmo_quote_cstr_c(OTC_SELECT, pdu.data, data_len));
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;
}
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 "\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));
// 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));
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,8 @@ void g_pfcp_tool_alloc(void *ctx)
};
INIT_LLIST_HEAD(&g_pfcp_tool->peers);
g_pfcp_tool->next_ue_addr_state = 0xc0a90001;
}
struct pfcp_tool_peer *pfcp_tool_peer_find(const struct osmo_sockaddr *remote_addr)
@@ -144,6 +146,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)
@@ -176,6 +204,10 @@ int peer_tx(struct pfcp_tool_peer *peer, struct osmo_pfcp_msg *m)
else
copy_msg(&peer->last_req, m);
rc = osmo_pfcp_endpoint_tx(g_pfcp_tool->ep, m);
if (rc) {
LOGP(DLPFCP, LOGL_ERROR, "Failed to transmit PFCP: %s\n", strerror(-rc));
return CMD_WARNING;
}
return rc;
}
@@ -183,3 +215,14 @@ 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->next_teid_state++;
}
int pfcp_tool_next_ue_addr(struct osmo_sockaddr_str *dst)
{
uint32_t addr = g_pfcp_tool->next_ue_addr_state++;
return osmo_sockaddr_str_from_32h(dst, addr, 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,
@@ -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,44 @@ 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->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;
@@ -412,26 +515,26 @@ 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);
LOGP(DLGLOBAL, LOGL_ERROR, "PFCP endpoint not configured\n");
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 +552,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 +568,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 +583,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 +600,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,
@@ -531,16 +639,13 @@ 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);
if (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;
@@ -556,14 +661,14 @@ 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);
LOGP(DLGLOBAL, LOGL_ERROR, "PFCP endpoint not configured\n");
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 +730,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 +744,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 +759,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,
@@ -691,10 +800,8 @@ 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);
if (rc)
return CMD_WARNING;
}
return CMD_SUCCESS;
}
@@ -705,24 +812,20 @@ 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;
@@ -730,14 +833,14 @@ DEFUN(session_tx_mod_req, session_tx_mod_req_cmd,
struct osmo_pfcp_ie_f_seid cp_f_seid;
if (!g_pfcp_tool->ep) {
vty_out(vty, "Endpoint not configured%s", VTY_NEWLINE);
LOGP(DLGLOBAL, LOGL_ERROR, "PFCP endpoint not configured\n");
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 +848,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 +873,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 +918,294 @@ DEFUN(session_tx_del_req, session_tx_del_req_cmd,
return CMD_SUCCESS;
}
/* N SESSIONS */
static int 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 (!responses_pending) {
vty_out(vty, "no responses pending, not waiting.%s", VTY_NEWLINE);
return CMD_SUCCESS;
}
vty_out(vty, "waiting for %d responses...%s", responses_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)
break;
if (responses_pending == 0)
break;
}
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)
{
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)
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;
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;
struct pfcp_tool_gtp_tun_ep *dst;
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 */
dst = &te->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();
/* 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)
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)
{
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)
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;
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)
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)
break;
/* handle any pending select work */
while (!osmo_select_shutdown_done()) {
rc = pfcp_tool_mainloop(1);
/* quit requested */
if (rc < 0)
return;
/* no fd needed service */
if (rc == 0)
break;
}
/* Every N created sessions, wait for pending responses */
if (!(i & 0x3f) && responses_pending) {
vty_out(vty, "waiting for %d responses...%s", responses_pending, VTY_NEWLINE);
vty_flush(vty);
while (!osmo_select_shutdown_done()) {
if (pfcp_tool_mainloop(0) == -1)
break;
if (responses_pending == 0)
break;
}
}
}
}
static void n_sessions_delete(struct pfcp_tool_peer *peer, int n, enum up_gtp_action_kind kind)
{
}
DEFUN(n_sessions, n_sessions_cmd,
"n (<0-2147483647>|all) session (create|delete) (tunend|tunmap)",
"Batch run\n"
"Perform the action N times, or on all available entries\n"
"In a batch run, create and later delete a number of sessions at once.\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 install_ve_and_config(struct cmd_element *cmd)
{
install_element_ve(cmd);
@@ -818,23 +1225,32 @@ 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_sessions_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 = 1, .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>
@@ -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);
@@ -263,11 +387,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 };
@@ -280,11 +399,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 };
@@ -344,18 +458,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)
@@ -373,10 +497,10 @@ 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);
}

View File

@@ -8,7 +8,7 @@ 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():
@@ -19,7 +19,7 @@ add map inet osmo-upf tunmap-post { typeof meta mark : verdict; };
add rule inet osmo-upf pre udp dport 2152 ip daddr . @ih,32,32 vmap @tunmap-pre;
add rule inet osmo-upf post meta mark vmap @tunmap-post;
DNFT DEBUG run nft ruleset: "add chain inet osmo-upf pre { type filter hook prerouting priority -300; policy accept; };\nadd chain inet osmo-upf post { type filter hook postrouting priority 400; policy accept; };\nadd map inet osmo-upf tunmap-pre { typeof ip daddr . @ih,32,32 : verdict; };\nadd map inet osmo-upf tunmap-post { typeof meta mark : verdict; };\nadd rule inet osmo-upf pre udp dport 2152 ip daddr . @ih,32,32 vmap @tunmap-pre;\nadd rule inet osmo-upf post meta mark vmap @tunmap-post;\n"
DNFT DEBUG ran nft ruleset, 465 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 tunmap-pre { typeof ip daddr . @ih,32,32 : verdict;..."
PFCP Associate peer
DPEER DEBUG up_peer{NOT_ASSOCIATED}: Allocated
@@ -58,6 +58,8 @@ 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:847
DNFT INFO Flushing NFT ruleset queue: reached max nr of rules: n:1 strlen:847 (flush count: 1 avg rules per flush: 1)
[test override] nft_run_cmd_from_buffer():
add chain inet osmo-upf tunmap-pre-1;
@@ -73,7 +75,8 @@ add rule inet osmo-upf tunmap-post-2 ip saddr set 1.1.1.1 udp sport set 2152 @ih
add element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x1 : jump tunmap-pre-2 };
add element inet osmo-upf tunmap-post { 2 : jump tunmap-post-2 };
DNFT DEBUG run nft ruleset: "add chain inet osmo-upf tunmap-pre-1;\nadd rule inet osmo-upf tunmap-pre-1 ip daddr set 13.14.15.16 meta mark set 1 counter accept;\nadd chain inet osmo-upf tunmap-post-1;\nadd rule inet osmo-upf tunmap-post-1 ip saddr set 1.1.1.1 udp sport set 2152 @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 udp sport set 2152 @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, 847 chars: "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 udp sport set 2152 @ih,32,32..."
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,6 +126,8 @@ 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:847
DNFT INFO Flushing NFT ruleset queue: reached max nr of rules: n:1 strlen:847 (flush count: 2 avg rules per flush: 1)
[test override] nft_run_cmd_from_buffer():
add chain inet osmo-upf tunmap-pre-3;
@@ -138,7 +143,8 @@ add rule inet osmo-upf tunmap-post-4 ip saddr set 1.1.1.1 udp sport set 2152 @ih
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 };
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 udp sport set 2152 @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 udp sport set 2152 @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, 847 chars: "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 udp sport set 2152 @ih,32,32..."
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,6 +188,8 @@ 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:381
DNFT INFO Flushing NFT ruleset queue: reached max nr of rules: n:1 strlen:381 (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 };
@@ -193,7 +201,8 @@ delete element inet osmo-upf tunmap-post { 2 };
delete chain inet osmo-upf tunmap-pre-2;
delete chain inet osmo-upf tunmap-post-2;
DNFT DEBUG run nft ruleset: "delete element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x2 };\ndelete element inet osmo-upf tunmap-post { 1 };\ndelete chain inet osmo-upf tunmap-pre-1;\ndelete chain inet osmo-upf tunmap-post-1;\ndelete element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x1 };\ndelete element inet osmo-upf tunmap-post { 2 };\ndelete chain inet osmo-upf tunmap-pre-2;\ndelete chain inet osmo-upf tunmap-post-2;\n"
DNFT DEBUG ran nft ruleset, 381 chars: "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 ..."
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,6 +240,8 @@ 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:847
DNFT INFO Flushing NFT ruleset queue: reached max nr of rules: n:1 strlen:847 (flush count: 4 avg rules per flush: 1)
[test override] nft_run_cmd_from_buffer():
add chain inet osmo-upf tunmap-pre-1;
@@ -246,7 +257,8 @@ add rule inet osmo-upf tunmap-post-2 ip saddr set 1.1.1.1 udp sport set 2152 @ih
add element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x1 : jump tunmap-pre-2 };
add element inet osmo-upf tunmap-post { 2 : jump tunmap-post-2 };
DNFT DEBUG run nft ruleset: "add chain inet osmo-upf tunmap-pre-1;\nadd rule inet osmo-upf tunmap-pre-1 ip daddr set 13.14.15.16 meta mark set 1 counter accept;\nadd chain inet osmo-upf tunmap-post-1;\nadd rule inet osmo-upf tunmap-post-1 ip saddr set 1.1.1.1 udp sport set 2152 @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 udp sport set 2152 @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, 847 chars: "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 udp sport set 2152 @ih,32,32..."
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,6 +308,8 @@ 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:847
DNFT INFO Flushing NFT ruleset queue: reached max nr of rules: n:1 strlen:847 (flush count: 5 avg rules per flush: 1)
[test override] nft_run_cmd_from_buffer():
add chain inet osmo-upf tunmap-pre-5;
@@ -311,7 +325,8 @@ add rule inet osmo-upf tunmap-post-6 ip saddr set 1.1.1.1 udp sport set 2152 @ih
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 };
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 udp sport set 2152 @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 udp sport set 2152 @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, 847 chars: "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 udp sport set 2152 @ih,32,32..."
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,6 +363,8 @@ 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:381
DNFT INFO Flushing NFT ruleset queue: reached max nr of rules: n:1 strlen:381 (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 };
@@ -359,7 +376,8 @@ delete element inet osmo-upf tunmap-post { 6 };
delete chain inet osmo-upf tunmap-pre-6;
delete chain inet osmo-upf tunmap-post-6;
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, 381 chars: "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 ..."
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,6 +386,8 @@ 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:381
DNFT INFO Flushing NFT ruleset queue: reached max nr of rules: n:1 strlen:381 (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 };
@@ -379,7 +399,8 @@ delete element inet osmo-upf tunmap-post { 2 };
delete chain inet osmo-upf tunmap-pre-2;
delete chain inet osmo-upf tunmap-post-2;
DNFT DEBUG run nft ruleset: "delete element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x2 };\ndelete element inet osmo-upf tunmap-post { 1 };\ndelete chain inet osmo-upf tunmap-pre-1;\ndelete chain inet osmo-upf tunmap-post-1;\ndelete element inet osmo-upf tunmap-pre { 1.1.1.1 . 0x1 };\ndelete element inet osmo-upf tunmap-post { 2 };\ndelete chain inet osmo-upf tunmap-pre-2;\ndelete chain inet osmo-upf tunmap-post-2;\n"
DNFT DEBUG ran nft ruleset, 381 chars: "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 ..."
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,6 +409,8 @@ 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:381
DNFT INFO Flushing NFT ruleset queue: reached max nr of rules: n:1 strlen:381 (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 };
@@ -399,7 +422,8 @@ delete element inet osmo-upf tunmap-post { 4 };
delete chain inet osmo-upf tunmap-pre-4;
delete chain inet osmo-upf tunmap-post-4;
DNFT DEBUG run nft ruleset: "delete element inet osmo-upf tunmap-pre { 1.1.1.1 . 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, 381 chars: "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 ..."
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