IFRAN: Interoperable Framework for Reproducible Automation of Networks
The ifran orchestrator is a Python library that deploys and manages a complete 5G network on real or virtual infrastructure, driven by declarative models. With the ifran orchestrator you can deploy a new 5G network but also modify it on-the-fly, for example to change a UPF, add a gNB, register new subscribers without interruptions.
You describe the 5G network you want and the machines you want to run it on. The library then:
- Provisions the machines (VMs, bare-metal servers, radio units, phones) if needed.
- Builds a Kubernetes cluster on them.
- Deploys the 5G core, RAN, RIC and UEs.
- Lets you fetch logs, run commands on nodes, pods and UEs, add or remove components on the fly, and tear everything down.
It automates the whole stack, including the IP wiring between functions (for example, the gNB's AMF address). Internally it runs Ansible (through ansible-runner) over SSH, and the Kubernetes and Helm operations are executed from the cluster's master node.
The figure below shows an example of complex hybrid deployment made possible by the ifran orchestrator.
flowchart TD
Core <--> node-ran
Core <--> gnb
cuup -.- cucp
cuup -.- du1
cucp -.- du1
cuup -.- du2
cucp -.- du2
subgraph node-core["node-Core (VM)"]
subgraph Core ["Core (Open5GS)"]
amf["AMF"]
ausf["AUSF"]
bsf["BSF"]
nssf["NSSF"]
nrf["NRF"]
pcf["PCF"]
smf["SMF"]
upf["UPF"]
udm["UDM"]
udr["UDR"]
end
end
subgraph node-ran["node-ran (VM)"]
cucp["CU-CP (OAI)"]
cuup["CU-UP (OAI)"]
end
subgraph sopnode-f1["sopnode-f1 (bare metal)"]
du1["DU1 (OAI)"]
end
subgraph sopnode-f2["sopnode-f2 (bare metal)"]
du2["DU2 (OCUDU)"]
end
subgraph node-ues["node-ues (VM)"]
gnb[gnb]
subgraph ues ["UEs (UERANSIM)"]
gnb -.- sim_ue1["sim_ue1"]
gnb -.- etc["..."]
gnb -.- sim_ue10["sim_ue_10"]
end
end
subgraph r2lab["R2LAB (Anechoic Chamber)"]
du1 <---> jaguar["AW2S jaguar (RU)"]
du2 <---> n320["USRP n320 (RU)"]
qhat01["Quectel RM 500Q-GL 01 (UE)"]
qhat02["Quectel RM 500Q-GL 02 (UE)"]
qhat03["Quectel RM 500Q-GL 03 (UE)"]
end
Where can it run?
The ifran orchestrator is not tied to a specific testbed. There are two ways to use it:
-
On SLICES-RI infrastructure. The built-in provisioners (e.g.,
bi,pos,r2lab) reserve and set up VMs, bare-metal nodes, radio units and phones for you, so a complete network, including real radio equipment, can be deployed from a single description. -
On any other infrastructure. Your own servers, a lab cluster, VMs from a public or private cloud, or a local virtualization setup all work, as long as the machines:
- run Linux,
- are reachable over SSH, and
- can run Kubernetes (the 5G functions are deployed on a Kubernetes cluster).
In that case, declare the machines with
provisioner: null, mark themis_provisioned: trueand give theirssh_info. The orchestrator then skips provisioning and goes straight to building the Kubernetes cluster and deploying the network. If you already have a Kubernetes cluster, you can also use it directly, as long as its nodes carry the expected role labels.
Both approaches can be mixed in the same deployment, for example a core on your own servers and a RAN with radio units provisioned through SLICES-RI.
Fundamental concepts
1. Metamodel
The metamodel is the abstract, implementation-agnostic description of the 5G network, based on 3GPP concepts: core, gNBs, UEs (SUPI, S-NSSAI, DNN), RUs, RIC and so on. It comes with full defaults, so you only write what deviates from them. It says what the network is, not how it is deployed, so you can reuse it across environments. The orchestrator transparently translates the metamodel into implementation configurations.
2. Deployment model
The deployment model is the concrete half. It says how and where the network runs:
- which implementation each function uses (Open5GS, OAI, OCUDU, UERANSIM...);
- which machines will be used, which roles they play (
core,ran,ue,ric) and how to provision them; - the deployment state: IP addresses, SSH information, Kubernetes cluster details and whether each resource is provisioned.
3. Managers
Each lifecycle stage is handled by a manager class. All of them inherit from BaseManagement.
| Manager | Main role |
|---|---|
ProvisioningManagement |
Provision, unprovision or reserve nodes, RUs and UEs; run commands on nodes; copy files to and from nodes |
K8SManagement |
Create or destroy a Kubernetes cluster on the nodes and label them according to their roles |
CoreManagement |
Deploy, update or remove core network functions; register or unregister subscribers; run commands in core functions |
RANManagement |
Deploy, update or remove RAN functions (e.g., gNB, CU, CU-CP, CU-UP, DU); run commands in RAN functions |
RICManagement |
Deploy, update, remove and manage the RIC |
UEManagement |
Deploy, connect and disconnect UEs; run commands on UEs |
MiscellaneousManagement |
Run custom Ansible playbooks on the nodes, typically to tune machines |
4. Kubernetes
Core, RAN, RIC, and potnetially UE functions run on a Kubernetes cluster and are installed with Helm. Kubernetes decides where each function is scheduled using node labels of the form node-type.5g.blueprint/<role>=true. For example, core functions only run on nodes labeled core, and the same holds for RAN, RIC, UE functions.
- Virtual UEs and RUs are deployed inside the cluster.
- Real RUs are managed by the orchestrator and connected to the cluster over IP.
- Real UEs (phones, modules) connect over their radio link to nearby RUs.
K8SManagement can create the cluster for you. You can also use an existing cluster, as long as it meets the requirements and carries the expected labels.
Design principles
-
Declarative and functional. Models are deep-copied between managers and input models are never mutated. A manager keeps the model it was built with, so create a new manager after each step.
-
Chaining.
NextManager(preceding=previous_manager)inherits the updated models. You can also start frommetamodelanddeployment_modelobjects, or from files. -
Reconciliation. When a manager is created, it completes the deployment model with an entry for every component in the metamodel. When needed it derives values from the parameters that are provided.
-
Persistence. After each stage, you can save the state to human-readable YAML files to resume or share a deployment.
-
Async API. All actions are
asyncso that work can run in parallel. -
No limitations: Beside type checking, the orchestrator does not provide any validation to allow experimenters to test any potential setup.
-
Ready for AI: Managers can be chained to construct arbitrary workflows. A typical deployment chains the managers in order, each one passing its models to the next.
Supported components
The orchestrator comes with a large collection of supported implementations and support for infrastructures. Users can even define their own images or helm charts in order to be highly customizable.
| Layer | Implementations |
|---|---|
| Core | OAI, Open5GS, Free5GC |
| RAN | OAI, OCUDU, UERANSIM, with support for CU, CU-CP, CU-UP, DU and monolithic gNB (RAN split) |
| RU | Physical radio units (USRP SDRs, AW2S, Benetel, LiteOn...) |
| RIC | OAI FlexRIC, O-RAN SC near-RT RIC |
| UEs | UERANSIM, OAI nr-ue, srsUE (containerized), Quectel 5G modules, COTS phones |
Machines can come from several sources, selected by the type of a provisioner:
| Provisioner type | Use it for |
|---|---|
null |
Machines you already have and can reach over SSH |
bi |
SLICES Basic Infrastructure virtual machines |
pos, legacy_pos |
Bare-metal nodes on POS testbeds |
unified_radio, r2lab |
Radio units and phones (for example in R2LAB) |
Minimal example
This example deploys a simple 5G network on virtual machines: one core, one gNB and two virtual UEs.
flowchart TD
Core --> gnb
%% Core --> gnb2
subgraph node-core[node-Core]
subgraph Core ["Core (Open5GS)"]
amf["AMF"]
ausf["AUSF"]
bsf["BSF"]
nssf["NSSF"]
nrf["NRF"]
pcf["PCF"]
smf["SMF"]
upf["UPF"]
udm["UDM"]
udr["UDR"]
end
end
subgraph node-ram[node-RAN]
subgraph RAN ["RAN (UERANSIM)"]
gnb[gnb]
%% gnb2["gnb2 (OAI)"]
end
end
subgraph node-ues[node-UEs]
subgraph ues ["UEs (UERANSIM)"]
gnb --> sim_ue1["sim_ue1"]
gnb --> sim_ue2["sim_ue2"]
%% gnb2 --rfsim--> sim_ue3["sim_ue3 (oai)"]
end
end
from ifran import (
MetaModel
DeploymentModel
CoreManagement,
K8SManagement,
ProvisioningManagement,
RANManagement,
UEManagement,
)
# WHAT: the abstract network (the core uses the defaults)
metamodel = MetaModel.from_yaml(
"""
ran:
components:
gnb:
type: gnb
ues:
sim_ue1:
config:
supi: '001010000000100'
subscriptions:
- snssai: internet
dnn: internet
gnbs:
- gnb
sim_ue2:
config:
supi: '001010000000101'
subscriptions:
- snssai: internet
dnn: internet
gnbs:
- gnb
"""
)
# HOW and WHERE: implementations, machines and provisioner
deployment_model = DeploymentModel.from_yaml(
"""
ran:
components:
gnb:
type: gnb
implementation: ueransim
ues:
sim_ue1:
implementation: ueransim
type: containerized
sim_ue2:
implementation: ueransim
type: containerized
nodes:
node-core:
provisioner: my-provisioner
roles:
- core
- ric
node-ran:
provisioner: my-provisioner
roles:
- ran
node-ues:
provisioner: my-provisioner
roles:
- ue
provisioners:
my-provisioner:
type: bi
params:
infra: <your_infrastructure>
project: <your_project>
experiment: <your_experiment>
create_experiment: true
experiment_duration: 2h
node_duration: 2h
"""
)
# Provision the 3 VMs in SLICES BI
prov = ProvisioningManagement(metamodel=metamodel, deployment_model=deployment_model)
await prov.provision(quiet=False)
# Deploy a Kubernetes cluster on these VMs
k8s = K8SManagement(preceding=prov)
await k8s.deploy(quiet=True)
# Deploy the 5G core functions
core = CoreManagement(preceding=k8s)
await core.deploy(quiet=True)
# Deploy the 5G RAN functions
ran = RANManagement(preceding=core)
await ran.deploy(quiet=True)
# Deploy the UEs
ues = UEManagement(preceding=ran)
await ues.deploy(quiet=True)
# Run a command on the UEs
command = ["ping", "-I", "uesimtun0", "-c", "10", "-D", "8.8.8.8"]
pings = await ues.run_command(command=command, components=["sim_ue1", "sim_ue2"], quiet=True)
print(pings)
# Save the state for reproducibility
ues.metamodel.to_yaml_file("state/metamodel.yaml")
ues.deployment_model.to_yaml_file("state/deployment_model.yaml")
If you already have machines, replace the provisioner with provisioner: null on each node, set is_provisioned: true and give its ssh_info.
Tutorials
We provide a vast collection of learn-by-doing tutorials.
Setup
Information to setup the experimenter's environment.
Infrastructure
How to manage the infrastructure where experiments are deployed.
5G network deployments and configuration
Main concepts of 5G networking.
Radio Units (RU) and Software Defined Radios (SDR)
Using real Radio Units and User Equipment.
Examples
Find a large collection of examples in the examples directory.
Contributing
Contributions are welcome. Please refer to our Contributing Guidelines for details.
License
Distributed under the BSD 3-Clause Clear license. See LICENSE for details.
Metadata
Release files for ifran 0.0.6
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| ifran-0.0.6.tar.gz | 224.4 kB | With provenance | Details for ifran-0.0.6.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| ifran-0.0.6-py3-none-any.whl | Python 3 | none | any | Details for ifran-0.0.6-py3-none-any.whl |
Total release size: 1.0 MB
Release files / ifran-0.0.6.tar.gz
| Download URL | ifran-0.0.6.tar.gz |
|---|---|
| Size | 224.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
db5c3d16776c31bfe452e64152e63e5bd8b3472faa4908c2ff083f33f3b30593
|
|
BLAKE2b-256 checksum How to use checksums |
a83ce45e0ebc668a9eb6b04df7b29824bb0c6592b2966e91cf96e927e2a19c60
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 12, 2026.
Transparency logRelease files / ifran-0.0.6-py3-none-any.whl
| Download URL | ifran-0.0.6-py3-none-any.whl |
|---|---|
| Size | 823.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9ec95d3ea15437f8a200d3c84912cde9852a5e2433c8677422baaad9d3e87af5
|
|
BLAKE2b-256 checksum How to use checksums |
215aa3c21153f1736ed9417caf74cc0edb61c008d8669997a33e7be69f6be591
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 12, 2026.
Transparency logSecurity for ifran 0.0.6
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for ifran-0.0.6.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 12, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.