Skip to content

ns-3 bridges

The bridges run a task's network through ns-3.48 with 5G-LENA v5.1 instead of the GPU engine. They are for validation only and are never needed for training. They need a local ns-3 + 5G-LENA build, which is not part of this package, and binaries built against ns-3 are GPL-bound (see Licensing). Tutorial 05 walks through a run, and ns-3 bridges in depth has the correctness checks, costs and known limits.

Bridge Python entry point C++ program Use
lockstep (TCP, Unix socket or ns3-ai shared memory) bridges.ns3_lockstep.lockstep_net.Ns3Net, bridges.ns3_lockstep.netmodule_ns3.Ns3NetModule bridges/ns3/lockstep/netslot-bridge.cc closed-loop co-simulation of a few environments
process pool bridges.ns3_pool.poolnet.PoolNet bridges/ns3/pool/netslot-bridge.cc one ns-3 process per environment, the CPU co-simulation baseline
offline replay bridges.ns3_offline (rollout, offline_ns3, ReplayNet) the pool program in file mode ns-3 after the fact on a recorded rollout
5G-LENA sweep replay python -m isaac_net.bridges.ns3_offline.lena_replay none replays a 5G-LENA sweep in the NR engine with identical link budgets

Environment variables

Variable Used by Meaning
NS3BRIDGE_ROOT lockstep directory with bin/netslot-bridge (and bin/netslot-bridge-ai for shared memory) and the ns-3.48 build
NS3_TOOLCHAIN_ENV lockstep the conda environment whose lib/ the ns-3 build links against
BRIDGE_ROOT pool, offline directory with the pool's bin/netslot-bridge

The defaults are paths on the lab machine. Build instructions and the wire protocol are in isaac_net/bridges/ns3/lockstep/README.md and isaac_net/bridges/ns3/pool/README.md.

Usage

Ns3Net and PoolNet implement the engine contract on top of ns-3, so they replace make_engine(...) in a loop that drives the engine. Their positions come from an environment object with a pos [E, R, 2] attribute, attached with bind_env(env) or attach_env(env):

from isaac_net import Requests
from isaac_net.bridges.ns3_lockstep.lockstep_net import Ns3Net

net = Ns3Net(E, R, "cpu", (4000.0, 30000.0), mode="procs", transport="tcp").bind_env(env)
net.reset()                                   # full resets only
for t in range(T):
    net.submit(None, Requests(send[t]), snr_db=snr)
    out = net.step(None, snr)                 # the same dict as make_engine's engines
net.close()                                   # stops the ns-3 processes

Ns3NetModule implements the Isaac NetModule API: it takes the isaac NetConfig, and submit then step(t, poses, cur_tag) returns the NetModule dict, with the raw ns-3 statistics in out["ns3"]. The older step(poses, TrafficRequest) -> NetOutput form is kept. In mode "procs" it rebuilds only the reset environment's process, so partial resets work there.

Limits to keep in mind

  • ns-3 cannot rewind part of a simulation. Ns3Net and PoolNet support full resets only, and a partial reset in single-process lockstep mode is logical only.
  • 5G-LENA's results depend on the process heap layout, so bit-exact comparisons between ns-3 runs need an identical command line. Comparisons between ns-3 and the GPU engine are statistical.
  • Offline replay is valid only for the policy that recorded the trace, because another policy's own traffic changes the queues.

Classes

Ns3Net

Ns3Net(E, R, device, sizes, mode='procs', transport='tcp', shadow='env', run=1, ns3_args=None, envs_per_proc=None, spawn=True, endpoints=None, host='127.0.0.1', **core_kw)

Bases: NetBase

ns-3 cannot rewind a subset of its envs here: reset() is full-only (reset(env_ids) raises), and every env
shares one clock, so t is taken from env 0.

bind_env

bind_env(env)

close

close()

Ns3NetModule

Ns3NetModule(cfg, transport='tcp', mode='procs', run=1, ns3_args=None, shadow_sigma_db=6.0, spawn=True, endpoints=None, host='127.0.0.1', envs_per_proc=None, seed=0)

The Isaac NetModule call pattern over the ns-3 lockstep bridge (see the module docstring).

cfg: an isaac NetConfig (num_envs, num_robots, device, msg_sizes, frame_depth, timeout_steps, step_dt).
reset(env_ids) marks envs for a rebuild at the next step; submit(t, TrafficRequest) queues this step's
messages; step(t, poses_end [E,R,3], cur_tag, blocked=...) returns the NetModule step dict with the raw
per-UE ns-3 statistics in out["ns3"]. close() stops the ns-3 processes.

reset

reset(env_ids=None)

step

step(t, poses=None, cur_tag=None, blocked_fn=None, *, blocked=None)

Advance every env by one control step (see the module docstring). Legacy form: step(poses, req,
blocked=None) -> NetOutput.

close

close()

Ns3Lockstep

Ns3Lockstep(E, R, mode='procs', transport='tcp', envs_per_proc=None, run=1, ns3_args=None, binary=None, spawn=True, endpoints=None, log_dir=None, host='127.0.0.1')

Drive E envs x R UEs over one or several ns-3 bridge processes, one 100 ms control step per step() call.

mode "procs" (one process per env), "single" (one process, E cells) or "groups" (envs_per_proc envs per
process); transport "tcp", "unix" or "shm" (ns3-ai, binary netslot-bridge-ai). spawn=False connects to
servers that are already running at endpoints instead of launching them. reset(groups, pos, shadow)
rebuilds the scenario of those process groups; step(pos, frames, shadow) returns the completed frames and
the per-UE ns-3 statistics. close() stops the processes. Ns3Net and Ns3NetModule are built on it.

reset

reset(groups=None, pos=None, shadow=None, runs=None)

Rebuild the scenario in the given process groups (default all).

pos [E,R,3] env-local initial poses (NaN rows = keep the scenario's own drop),
shadow [E,R] dB. runs: RNG run per group (default: a fresh run number per episode).

step

step(pos, frames, shadow=None, interp=False, t=None)

Advance every process by one control step.

pos [E,R,2|3] env-local (NaN = keep); frames: structured array with fields env, ue, fid, bytes
(env = global env index); shadow [E,R] dB or None.
Returns dict: done (structured: env, ue, fid, frac in [0,1) of the step), per-UE stats [E,R],
timing.

close

close()

PoolNet

PoolNet(E, R, device, sizes, extra_args=(), launcher='local', seed_run=1, log_dir=None, send_positions=True)

Bases: NetBase

NetBase drop-in whose uplink is one ns-3 / 5G-LENA worker process per env (see the module docstring).
Every reset() restarts all workers, so partial resets are not supported. attach_env(env) supplies real
robot positions for the fading geometry; close() stops the workers.

attach_env

attach_env(env)

close

close()

ReplayNet

ReplayNet(E, R, device, sizes, outcomes)

Bases: NetBase

NetBase whose frame outcomes come from a recorded rollout, with the fallbacks of the module docstring.
Valid only for the policy that produced the recording: the outcomes do not react to the running policy.

outcomes: {(e, r, t): (cls, delay_steps or inf)}.