Run Scripts
June 12, 2026 ยท View on GitHub
This directory contains the scripts used to create and reuse the FikoRE NFQUEUE lab.
The lab and the emulator config are separate concerns:
- the lab manages Linux namespaces,
vethpairs, routes, andNFQUEUErules; - the
.inifile remains the source of truth for what FikoRE actually instantiates; runusesCONFIG_FILEas-is and does not generate or patch a runtime copy.
Scripts
- run_fikore_nfqueue_lab.sh: creates, reuses, inspects, and tears down the lab topology, then launches FikoRE on top of it.
- run_docker.sh: builds or launches the helper container for Docker backends.
- run_offline.sh: runs an offline simulation from a positional config file and then generates plots from the latest logs. By default it keeps only the general offline plots; pass
-ato also generate DualQ/L4S/NFQUEUE-specific plots. - run_emulated.sh: runs the NFQUEUE lab workflow with a positional emulation config file.
- run_dashboard.sh: activates the repository Python environment and starts the live dashboard.
- python_env.sh: shared Python environment helper used by the other run scripts.
- fikorens: direct wrapper that opens a namespace shell without requiring
source. - fikorens-open: direct wrapper that opens a namespace shell and returns when it exits.
- fikorens-exec: direct wrapper for one-shot commands inside a namespace.
- fikore_ns.sh: optional sourced helper exposing
fikorens,fikorens_open, andfikorens_exec.
Mental Model
up: explicitly recreate the lab topology and save its state.run: launch FikoRE on the current lab. If no lab exists yet, it creates one first. If saved state exists but the topology is broken, it fails and tells you to runup.status,shell,exec,capture-*,ue-add,ue-del, anddown: reuse the saved lab state. They do not needBACKENDagain once the lab is up.
This avoids the old destructive behavior where run recreated namespaces every time.
For real-traffic emulation, use run_emulated.sh or the lab script directly. For offline simulated traffic, use run_offline.sh.
Topology
Emulated Plane
UE <-> DN traffic always crosses the EMU node, which is where FikoRE runs and where the NFQUEUE rules are applied.
fkue1 ----\
fkue2 ----- EMU ---- fkdn
... /
Default addressing:
- UE1
<->EMU:10.201.1.2/30 <-> 10.201.1.1/30 - UE2
<->EMU:10.201.2.2/30 <-> 10.201.2.1/30 - DN
<->EMU:10.255.0.2/24 <-> 10.255.0.1/24
Default queue mapping:
- UE1: UL
100, DL101 - UE2: UL
110, DL111
General formula:
UL = QUEUE_BASE + (UE - 1) * QUEUE_STEPDL = UL + 1
With the defaults (UE_COUNT=2, QUEUE_BASE=100, QUEUE_STEP=10), UE3 would use 120/121 only if UE_COUNT>=3 or if you add it later with ue-add 3.
Management Plane
This plane only exists in docker-none.
host <----> FikoRE container
172.30.0.1 172.30.0.2
It is only a management link. If your .ini emits dashboard UDP traffic from inside the container, that .ini must already point to a reachable host address such as 172.30.0.1:8096.
Requirements
- Run run_fikore_nfqueue_lab.sh through
sudo. - Have
bin/fikorealready built. - For Docker backends, have an image built and a container started with run_docker.sh.
- For Docker backends, keep
CONFIG_FILEinside the repository so the container can read that same file through the bind mount.
Recommended Example Config
The best ready-to-use emulated example is config/emulated_rural_n78_single_with_background.ini.
Why this file is the best default example:
- it matches the lab queue plan directly with
UE1 -> 100/101; - it keeps
l4s_dual_queue: true, so it exercises the L4S / DualQ path; - it adds simulated background users to create load around the captured UE;
- it already enables UDP dashboard output on
127.0.0.1:8096.
Important:
run_fikore_nfqueue_lab.shdoes not rewrite monitoring keys anymore.- For
hostanddocker-host, a dashboard on127.0.0.1:8096is usually fine if the.inialready says that. - For
docker-none, the.inishould explicitly target the host-side management IP, typically172.30.0.1:8096. - Adding namespaces with
ue-adddoes not modify the.ini; FikoRE only uses UEs actually defined in the config file.
Quick Workflow
All commands below assume your current directory is the repository root.
1. Create the Lab
For the recommended example config:
sudo BACKEND=host UE_COUNT=2 run_scripts/run_fikore_nfqueue_lab.sh up
sudo run_scripts/run_fikore_nfqueue_lab.sh status
This creates two namespace UEs:
ue1: intended for the L4S pathue2: intended for the legacy path
If you need a different lab size, change UE_COUNT only when running up. Later run reuses the existing topology.
2. Open Namespace Shells
Direct wrappers work without source:
run_scripts/fikorens-open dn
run_scripts/fikorens-open ue1
run_scripts/fikorens-open ue2
For one-shot commands:
run_scripts/fikorens-exec dn iperf3 -s -p 5202
run_scripts/fikorens-exec ue1 iperf3 -c 10.255.0.2 -p 5202 -t 30
Each interactive namespace shell adds a prompt prefix such as (ue1) or (dn) without replacing the whole prompt.
If you still prefer sourced helpers:
source run_scripts/fikore_ns.sh
fikorens_open ue1
fikorens_exec dn iperf3 -s -p 5202
When sourced, fikorens ue1 keeps its original "replace the current shell" behavior.
3. Start the Dashboard
Typical host-side dashboard command:
run_scripts/run_dashboard.sh --host 0.0.0.0 --port 8096
Make sure the .ini already points to the correct address for your backend.
4. Launch FikoRE
run_scripts/run_emulated.sh config/emulated_rural_n78_single_with_background.ini
Equivalent direct lab invocation:
sudo CONFIG_FILE="$PWD/config/emulated_rural_n78_single_with_background.ini" \
run_scripts/run_fikore_nfqueue_lab.sh run
Behavior:
- if no lab exists yet,
runcreates it first using current defaults or suppliedBACKEND/UE_COUNT; - if a valid lab already exists,
runreuses it and does not recreate namespaces; - if saved state exists but the topology is broken,
runfails and asks you to runup.
5. Run Traffic Tests
Assumed addresses:
- DN IP:
10.255.0.2 - UE1 IP:
10.201.1.2 - UE2 IP:
10.201.2.2
TCP iperf3
In dn:
iperf3 -s -p 5202
In ue1:
iperf3 -c 10.255.0.2 -p 5202 -t 60
Downlink:
iperf3 -c 10.255.0.2 -p 5202 -t 60 -R
UDP iperf3
In dn:
iperf3 -s -p 5202
In ue1:
iperf3 -c 10.255.0.2 -u -b 20M -l 1200 -p 5202 -t 60
Downlink:
iperf3 -c 10.255.0.2 -u -b 20M -l 1200 -p 5202 -t 60 -R
UDP Prague
In dn:
udp_prague_receiver -a 0.0.0.0 -p 8080
In ue1:
udp_prague_sender -c -a 10.255.0.2 -p 8080 -b 20000
SCReAM
In dn:
scream_bw_test_rx 10.201.1.2 30122
In ue1:
scream_bw_test_tx -ect 1 -time 60 10.255.0.2 30122
6. Generate Offline Visualizations
After the run:
run_scripts/run_offline.sh plots
The analyzers read the newest log directory under logs/ and write figures under results/<latest-log>/.
7. Optional PCAP Capture
Start:
sudo CAPTURE_ID=example CAPTURE_UDP_PORT=5202 run_scripts/run_fikore_nfqueue_lab.sh capture-start
Stop and summarize:
sudo CAPTURE_ID=example run_scripts/run_fikore_nfqueue_lab.sh capture-stop
sudo CAPTURE_ID=example run_scripts/run_fikore_nfqueue_lab.sh capture-summary
Artifacts are written under run_scripts/.captures/example/.
Main Actions
Create or recreate topology:
sudo BACKEND=host UE_COUNT=2 run_scripts/run_fikore_nfqueue_lab.sh up
sudo BACKEND=docker-host UE_COUNT=2 run_scripts/run_fikore_nfqueue_lab.sh up
sudo BACKEND=docker-none UE_COUNT=2 run_scripts/run_fikore_nfqueue_lab.sh up
Reuse current topology:
sudo CONFIG_FILE="$PWD/config/emulated_rural_n78_single_with_background.ini" run_scripts/run_fikore_nfqueue_lab.sh run
sudo run_scripts/run_fikore_nfqueue_lab.sh status
sudo run_scripts/run_fikore_nfqueue_lab.sh shell ue1
sudo run_scripts/run_fikore_nfqueue_lab.sh exec dn -- iperf3 -s -p 5202
sudo run_scripts/run_fikore_nfqueue_lab.sh capture-start
sudo run_scripts/run_fikore_nfqueue_lab.sh capture-stop
sudo run_scripts/run_fikore_nfqueue_lab.sh capture-summary
sudo run_scripts/run_fikore_nfqueue_lab.sh down
Lab-only UE lifecycle:
sudo run_scripts/run_fikore_nfqueue_lab.sh ue-add 3
sudo run_scripts/run_fikore_nfqueue_lab.sh ue-del 3
These commands only change lab topology:
- create or remove
fkueN; - create or remove its
vethpair and routing; - add or remove the corresponding UL/DL
NFQUEUErules; - update saved lab state.
They do not modify the .ini. If the config does not define a matching real UE and queue pair, FikoRE will ignore that extra namespace.
Useful Variables
BACKEND=host|docker-host|docker-noneCONFIG_FILE=/path/to/config.iniUE_COUNT=2QUEUE_BASE=100QUEUE_STEP=10CONTAINER_NAME=fikore-emuCONTAINER_WORKDIR=/usr/src/5g-network-emulatorCAPTURE_ID=defaultCAPTURE_UDP_PORT=9999CAPTURE_DN_NAMESPACE=1CAPTURE_DIR=/path/to/run_scripts/.capturesTARGET_UID=<uid>TARGET_GID=<gid>TARGET_USER=<user>TARGET_HOME=/home/<user>
Notes
emuis only a valid namespace target indocker-none.shellandexecuserootonly to cross into the namespace, then drop back to the original user from thesudosession.- If you invoke the script directly as
rootwithoutsudo, setTARGET_UID,TARGET_GID,TARGET_USER, andTARGET_HOMEexplicitly so commands can run as a normal user once inside the namespace.