bLEO
May 19, 2026 · View on GitHub
bLEO: An eBPF-based emulator for large-scale LEO satellite networks
Description
bLEO is a Linux-based tool designed to emulate large-scale LEO (Low Earth Orbit) satellite networks. It is implemented using shell scripting (bleo.sh) and makes use of the following general-purpose Linux tools:
- Docker containers
- eBPF modules
- Linux bridging
- Network namespaces
- Python (for event generation)
- gcc and clang (LLVM) compilers
The core idea is to run one container per network element (satellites, ground stations, and terminals) and connect them through virtual Ethernet interfaces (veth) and network namespaces. bLEO models time-varying connectivity between satellites and ground stations, driven by satellite movement and Earth rotation. Instead of using tc-netem, link delay is controlled via an eBPF module, enabling near-instantaneous updates directly in the kernel datapath. In LEO constellations, link characteristics such as delay and connectivity change frequently, requiring efficient mechanisms to update network conditions at high rates.
A typical execution workflow is:
- Configure the scenario in
bleo.conf - Generate dynamic events using
eventGenerator.py - Deploy the network using
bleo.sh - Run the dynamic event script (
events_dynamic.shgenerated byeventGenerator.py) to simulate satellite movement
Components
- Configuration file (
bleo.conf): defines the LEO scenario parameters. - Event Generator (
eventGenerator.py): generates time-dependent topology events (topology_init.shandevents_dynamic.sh). - Configuration Manager (
bleo.sh): deploys and manages the network. Dockerfile: builds an Ubuntu-based image for bLEO components.updatemapapplication (filesupdatemap.c,updatemap): updates interface delays via eBPF maps.setprop.oeBPF module (filessetprop.c,bpf_elf.h,setprop.o): enforces delay in the kernel datapath.tracerapplication (filestracer.c,tracer): monitors traffic across interfaces.showifidutility: retrieves interface identifiers.Makefile: builds utilities and eBPF components.
Preparation
Runtime requirements
The following components are required to run bLEO:
- Docker >= 20.10.17
- Python >= 3.6
libbpfruntime library (version 1.x, providinglibbpf.so)
If users need to rebuild the native utilities (updatemap, tracer) or the eBPF object (setprop.o) from source, the corresponding libbpf development package and compilation toolchain (e.g., clang, llvm, gcc, make) are also required.
Although not strictly required, the bpftool command-line utility can be useful for inspecting the eBPF maps used by bLEO (e.g., interface delays and traffic counters).
Build requirements (optional)
The following tools are only required if you need to rebuild the native utilities (updatemap, tracer) or the eBPF object (setprop.o) from source:
makegccclang/llvmtoolchainlibbpfdevelopment package (version 1.x), e.g.:libbpf-devon Ubuntu/Debianlibbpf-develon RHEL/Fedora
Installation
1. Clone the repository
Clone the bLEO repository into your home directory:
git clone https://github.com/leonetlab-upct/bleo.git ~/bleo
cd ~/bleo
2. Install Python dependencies
Install the required Python dependencies:
python3 -m pip install sgp4 skyfield numpy
3. Build the Docker image
bLEO requires a Docker image containing the necessary networking tools (e.g., FRR, D-ITG, iperf). A Dockerfile is provided for this purpose.
To build the image, run:
sudo docker build -t frr_ditg:v1 . --no-cache
Make sure that the image name matches the value specified in the bleo.conf file:
docker_img="frr_ditg:v1"
Alternatively, you can use a different image by modifying the docker_img parameter in bleo.conf.
This step is required before running bLEO. Otherwise, the deployment script (bleo.sh) will fail because the Docker image will not be available.
4. (Optional) Build utilities and eBPF module
Precompiled binaries are provided for x86_64 systems. If you are using a different architecture or want to rebuild the tools, run:
make
This will compile:
updatemaptracersetprop.o
5. (Optional) Install binaries system-wide
If you prefer to install the tools system-wide, you can copy them to /usr/local/bin:
sudo cp updatemap tracer setprop.o /usr/local/bin/
Otherwise, you can keep them in ~/bleo and reference them directly in bleo.conf.
Quick Start
Run a minimal bLEO scenario using the default configuration:
# Clone and enter the repository
git clone https://github.com/leonetlab-upct/bleo.git ~/bleo
cd ~/bleo
# Install binaries system-wide
sudo cp updatemap tracer setprop.o /usr/local/bin/
# Build Docker image
sudo docker build -t frr_ditg:v1 . --no-cache
# Install Python dependencies
python3 -m pip install sgp4 skyfield numpy
# Generate topology events
python3 eventGenerator.py
# Deploy the network
sudo ./bleo.sh --config bleo.conf
# Start dynamic emulation
sudo ./events_dynamic.sh
The default configuration (bleo.conf) allows running a basic scenario out of the box. To customize the scenario, you can modify the configuration file as described below.
Configuration file
The following paths assume that bLEO is located in ~/bleo. Below is a brief explanation of each of the configuration variables:
docker_img="frr_ditg:v1"
This is the name of the Docker image used to emulate each LEO satellite, ground station, and terminal (it is assumed that Docker is properly installed and running on the system). A Dockerfile is provided for building an image based on Ubuntu with the utilities frr (OSPF), ditg (Distributed Internet Traffic Generator) and iperf already installed. To build this Docker image, run: sudo docker build -t frr_ditg:v1 . --no-cache
updatemap=/usr/local/bin/updatemap
This specifies the location of the updatemap application, which is used by bleo.sh to update the delays of the LEO network interfaces. A version compiled for x86_64 is provided; for other platforms, simply run make. If bLEO is located in ~/bleo, you can simply set updatemap=~/bleo/updatemap
setprop=/usr/local/bin/setprop.o
This is the location of the setprop.o eBPF module, which is used by the updatemap application to set up the network link delays. The script bleo.sh is responsible for loading it on each network interface. A version compiled for x86_64 is provided; for other platforms, simply run make. If bLEO is located in ~/bleo, you can simply set setprop=~/bleo/setprop.o
tracer=/usr/local/bin/tracer
This is the location of the tracer application. This application allows tracing the path across LEO satellites used by a connection. A version compiled for x86_64 is provided; for other platforms, simply run make. If bLEO is located in ~/bleo, you can simply set tracer=~/bleo/tracer
numgs=2, gs_coords="50.110924,8.682127;46.635700,14.311817"
The number of ground stations (GS) and their coordinates separated by semicolons.
numterm=2, termc="term1-gs1;term2-gs2"
The number of terminals and the connections between terminals and ground stations, separated by semicolons.
maxp=12, maxs=8
The number of orbital planes (maxp) and the number of satellites per plane (maxs).
delay_west=1, delay_east=1, delay_north=1, delay_south=1, delay_gssat=1
Initial delay for each of the five interfaces of a LEO satellite.
ip="yes"
Set this variable to yes if you want to build an IP network. The way IP addresses are configured is described later.
ospf="yes"
Set this variable to yes if you want to build an OSPF network. It is expected that the Docker image used in the emulation must contain the software frr.
hello_interval="10"
If OSPF is enabled, this is the interval (in seconds) between Hello messages.
mapsize=2048
The eBPF map size. It should be large enough to store the delay of all interfaces (five per satellite and one per ground station).
altitude=550, inclination=70
Altitude and inclination of the orbit.
duration=3600
Duration of the emulation in seconds.
antenna_inclination_angle=25
The angle of the antenna in each ground station. It determines the time window during which a ground station can establish and maintain a connection to a satellite.
Event Generator
The second step is to generate the shell scripts responsible for handling all network dynamics (link connections/disconnections, delay updates, etc.) throughout the entire emulation time. This is done using the Python application eventGenerator.py. Simply run:
python3 eventGenerator.py
This will generate the scripts topology_init.sh and events_dynamic.sh.
Configuration Manager
The next step is to build the LEO network. To do so, run as root:
sudo ./bleo.sh --config path_to_bleo.conf
Then wait until the network is fully deployed. For large scenarios (e.g., 12 orbital planes and 24 satellites per plane), deployment may take up to 10 minutes.
Movement Manager
At this point, the network should be up and running, but the network remains static (i.e., neither the satellites nor the Earth move). To start the emulation, run the script:
sudo ./events_dynamic.sh
From then on, the connections and delays of all elements will vary according to the movement of the satellites along their orbital planes, as well as the rotation of the Earth.
When the emulation has finished, shut it down by running:
sudo ./bleo.sh -d
Miscellanea
Each network element is assigned a unique ID. Satellite IDs range from 1 to maxp × maxs, while ground station IDs start from maxp × maxs + 1. The maximum allowed ID value is 2047 (11 bits). For example, if maxp=12, maxs=24, and numgs=2, satellite IDs range from 1 to 288, while ground station IDs are 289 and 290.
Each network element is associated with a Docker container name. Satellite containers follow the format pXXsYY, where XX indicates the orbital plane and YY the satellite index within that plane. Ground station containers follow the format gsN, where N is the ground station number starting from 1, although their internal IDs start from maxp × maxs + 1. Terminal nodes follow the format termN, where N is the terminal number starting from 1, with internal IDs assigned after the ground stations. For example, if maxp=12 and maxs=24, p00s00 corresponds to the satellite with ID=1, while p11s23 corresponds to ID=288. In that case, the first ground station has internal ID=289 but its Docker container is named gs1. If numterm=2, the terminal nodes would be named term1 and term2, with internal IDs assigned after the ground stations.
Terminal nodes are connected to specific ground stations through dedicated point-to-point virtual Ethernet links, as defined by the termc configuration parameter (e.g., term1-gs1;term2-gs2). This allows end hosts to inject or receive traffic through selected ground stations while remaining outside the emulated satellite constellation. All containers can be listed using docker container ls.
A LEO satellite has five network interfaces. Their names are formed by appending north, south (intra-plane), east, west (inter-plane), or LinkToGS to the name of the Docker container. For example, the five interfaces of satellite p02s15 are p02s15north, p02s15south, p02s15east, p02s15west and p02s15LinkToGS. For ground stations, the interface name is ifgs followed by the ground station ID.
For IP addressing, bLEO uses a private class A scheme (10.X.Y.Z). The addressing rule is based on the north and east interfaces. The IP address of the interface connecting the IDsrc (north/east) to IDdst (south/west) is determined as follows: byte X is set to the first 8 bits of the IDsrc. Byte Y is set to the first 8 bits of the IDdst. Finally, the last byte is set using the last three bits of the IDsrc, together with the last three bits of IDdst, and bits 01 for the north/east interface or 11 for south/west interface (the other end). For example, the IP address of the interface p02s15north (ID=64, assuming again maxp=12 and maxs=24) is 10.64.65.1 and the IP address of the interface p03s21west (ID=94) is 10.70.94.2, following the rules derived from interface p02s21east (ID=70).
Additionally, each element has a loopback interface (apart from 127.0.0.1) with a private IP address in the 172.16.0.0/16 range. The last two bytes are determined following the same rules described above but considering only the ID of the element. For example, the IP address of the loopback interface of satellite p02s13 (ID=62) is 172.16.62.0, while that of p10s18 (ID=259) is 172.16.3.32.
The tracer application is intended to show how many packets have been sent for each link interface. This utility can be used to infer the path followed by the IP datagrams in a LEO network.
sudo tracer --show 1000: shows all interfaces that have sent more than 1000 datagrams.sudo tracer --show 0: shows the number of datagrams sent through each interface.sudo tracer --clear: resets the database to 0 datagrams sent for every interface.
The showifid script is a utility that shows the kernel identifier of every network link used by bLEO. It is needed by the tracer utility and can also be helpful if you want to configure link delay manually using the updatemap utility directly, or alternatively bpftool (the eBPF library operates on link identifiers rather than link names).
License
This project is licensed under the MIT License.
bLEO is intended as a research-oriented tool to facilitate reproducible experimentation in large-scale LEO satellite networks.