Aether is the Linux Foundation's open-source private-5G platform; SD-Core is its 5G core, from the omec-project. Unlike Open5GS, SD-Core is Kubernetes-native — it runs as Helm charts on RKE2, with a DPDK/BESS user plane — which makes it the right choice when the core is the object of study rather than a dependency of a radio experiment.
This page is the map: what SD-Core is made of, which tutorials use it, and — most importantly — the operational rules that are not in the upstream documentation and that cost real days to find.
SD-Core splits cleanly into a control plane of Go microservices (derived from free5GC) and a user plane built on BESS, a software dataplane that moves GTP-U packets. The control plane talks to the user plane over PFCP (N4); the gNB sees an ordinary N2/NGAP endpoint on the AMF and an N3/GTP-U endpoint on the UPF.
Everything runs in one Kubernetes namespace (aether-5gc) on a single RKE2 node in the COSMOS deployment.
| Component | Role | Kubernetes object |
|---|---|---|
| AMF | Access & Mobility — terminates N2/NGAP, registration, NAS | deployment/amf |
| SMF | Session Management — PDU sessions, PFCP (N4) to the UPF | deployment/smf |
| UPF | User Plane — a 5-container pod: bessd (the BESS dataplane), pfcp-agent, routectl, web, arping |
statefulset/upf → pod upf-0 |
| NRF | NF Repository — service discovery over HTTPS (port 29510) | deployment/nrf |
| AUSF / UDM / UDR | Authentication and subscriber data | deployment/ausf, udm, udr |
| PCF / NSSF | Policy and slice selection | deployment/pcf, nssf |
| WebUI | subscriber/slice configuration front end | deployment/webui |
| simapp | pushes device groups, slices and the served PLMN/TAC into the core at start-up | deployment/simapp |
| MongoDB | subscriber and NF state (enableDBStore) |
statefulset/mongodb |
| Kafka | the telemetry/event bus (metricfunc) |
statefulset/kafka |
bessd is a real packet dataplane, not a kernel module: it has its own worker threads pinned to cores, its own ports, and its own statistics. Two consequences:
kubectl. A Running 5/5 upf-0 can still be refusing every PFCP association. Inspect it directly:kubectl -n aether-5gc exec upf-0 -c bessd -- bessctl show worker
kubectl -n aether-5gc exec upf-0 -c bessd -- bessctl show port
A healthy dataplane shows a RUNNING worker and the access/core ports Link UP with non-zero counters.pfcp-agent can lose its binding to bessd while bessd itself is perfectly healthy. It then answers every PFCP Association Setup with Error during Process: datapath down. That message names the agent's binding, not BESS.Measured on COSMOS, 2026-09-20. One SMF pod restart breaks the PDU path two ways at once, and both failures are close to silent:
datapath down — indefinitely, while the SMF re-sends a request every 10 s. Downstream the SMF reports PfcpSessCreateFailure with RemoteSEID 0, and the UE gets PDU Session Establishment Reject, 5GSM cause 0x1f (31).enableNrfCaching: true the AMF can serve an unusable cached SMF entry: it logs transport 5GSM Message to SMF, then does nothing for ~1.8 s and releases the UE context. A packet capture shows zero packets leaving the AMF toward the SMF.| symptom | what to restart |
|---|---|
AMF logs transport 5GSM Message to SMF then goes silent, no error |
AMF — kubectl -n aether-5gc rollout restart deployment/amf |
UPF logs datapath down; SMF logs PfcpSessCreateFailure |
upf-0 — kubectl -n aether-5gc delete pod upf-0 |
| anything at all | never the SMF |
The gate that actually predicts whether a PDU session can be created is the association line in the UPF log:
kubectl -n aether-5gc logs upf-0 -c pfcp-agent --since=3m | grep -i association
# healthy: association setup done between nodes local: <upf> remote: <smf-pod-ip>
tac: 7 and fail here in a way that is easy to misread as a radio fault. Match the AMF's Supported Tai List.CHECKSUM_PARTIAL and is forwarded into GTP without the checksum being completed; the UE discards every segment. Put the iperf server on the gNB host instead.cipheringOrder: [NEA0], so NAS is integrity-protected but not encrypted — an N2 capture decodes with no key material, which makes registration debugging far easier than it usually is.aether-sdcore image pins its bake host in several places (config, NIC name, etcd membership, on-disk CNI IPAM, a Service externalIP). Loading it on a different server does not simply work.10.42.0.0/16 and 10.43.0.0/16, which sit inside COSMOS NJ's 10.0.0.0/10. Nothing collides today and nothing is routed off-node, but a future testbed allocation in that range would be silently black-holed on any pod-hosting node. The agreed reservation for virtualised workloads is 10.128.0.0/14.| Tutorial | RAN stack | Radio | Status |
|---|---|---|---|
| Two-server 5G SA — OCUDU gNB + SD-Core over a 10 GbE data plane | OCUDU (srsRAN) | USRP B210 or network N310/X310 | ✅ working end to end |
The same core has also been driven from an OCUDU O-RAN 7.2 O-DU against commercial O-RUs (LiteOn FlexFi and Benetel RAN650) — see OCUDU 5G SA over O-RAN 7.2 for the radio side of that work.
Best figures recorded against SD-Core, with the CPU platform, because throughput on these rigs tracks the core count available for isolation. Platform letters follow the OCUDU page: B = 2× Intel Xeon Gold 6126 (24C/48T).
| RAN configuration | UE | Platform | DL, Mbit/s | UL, Mbit/s | Date |
|---|---|---|---|---|---|
| OCUDU over the air, USRP B210 | Quectel RM520N-GL | B | 23.6–24.6 | 10.3–11.7 | 2026-09-18 |
| OCUDU O-RAN 7.2, LiteOn FlexFi (100 MHz n78) | Quectel RM520N-GL | B | 141–149 | 37.6–58.7 | 2026-09-20 |
| OCUDU O-RAN 7.2, Benetel RAN650 (100 MHz n78) | Quectel RM520N-GL | B | 3.4 | 10.4 | 2026-09-21 — registration, PDU and ping are clean; throughput is limited by a degraded radio (only one usable TX branch on this unit), not by the core |
Ping is 0 % loss on all three, ~29–36 ms to both the gNB host and the public internet.
aether-5g.oci://ghcr.io/omec-project/sd-core.Author(s): COSMOS team · Last verified: 2026-09-21 · Tested image/release: aether-sdcore · SD-Core 4.0.0 · Tags: aether, sd-core, omec, 5gc, core, 5g, sa, overview