Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions BRANCH_HISTORY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Branch history — `spectranet-demo`

**2026-06-10: this branch was repointed.** It now tracks the **aerial-compatible
JSON dialect** lineage (`main` @ `bc2fd15` + `fa187a0`) and replaced the original
2026-04/05 **runtime dual-encoding** lineage (old tip `aa46f6b`). This file
records what the old lineage contained so nothing is lost with the rewrite.

## What this branch is now

- libe3 `main` plus one commit, `fa187a0`: the JSON encoder/decoder speaks the
NVIDIA Aerial camelCase wire dialect — flat envelope with a `"type"` key
(PascalCase and `"data"`-wrapped forms rejected), payloads accepted as inline
JSON / `{"__hex__": "…"}` / plain hex / UTF-8, structured `ranFunctionData`
passed inline, plus additive optional fields (`SetupResponse.message`,
`SubscriptionResponse` granted-list/periodicity/message echoes,
`IndicationMessage.subscription_id`).
- Exactly one encoder per build: the spectranet deployment uses
`-DLIBE3_ENABLE_JSON=ON -DLIBE3_ENABLE_ASN1=OFF`.
- Pairs with the `spectranet-demo` branches of `spear-openairinterface5g`
(gNB built with `-DE3_ENCODING_FORMAT=JSON`) and of the dApp repo.

## The replaced lineage (runtime dual-encoding, old tip `aa46f6b`)

The old branch served ASN.1 (spear-dApp) and JSON (aerial dApps)
**simultaneously** over two channel sets inside one agent. It was superseded by
the build-time single-encoding model above. Its commits up to `8afc87f` remain
reachable through the branch `aerial-oai-integration`; the last six commits
existed only on the old `spectranet-demo` and are summarized here so they can
be re-implemented if ever needed:

| Commit | What it did | Still relevant? |
|---|---|---|
| `aa46f6b` | Reliable gNB→dApp xApp-control relay: per-message ack + retransmit on the agent side | The current stack relays xApp controls fire-and-forget; the dApp side has its own ack/retransmit for dApp→gNB. Re-implement if xApp→dApp delivery must be guaranteed under load. |
| `088b03d` | Link `libe3_sanitizers` PUBLIC so consumers inherit the flags | Build hygiene; re-do if sanitizer builds return. |
| `454874d` | Rate-limit + clarify malformed-setup warnings in the setup loop | Cosmetic; logs can flood if a wrong-encoding dApp hammers setup. |
| `5449543` | **Send an empty reply on setup-decode failure so the ZMQ REP socket never wedges** | The known sharp edge of `main`: a malformed/wrong-encoding setupRequest leaves the REP socket stuck (reply expected before next recv). Re-implement this if mixed-encoding dApps ever share a deployment. |
| `b458ba4` | Reduce SubscriptionManager reader pressure under emit load | Possibly superseded by `main`'s multi-dApp fan-out rework; re-evaluate before porting. |
| `774a043` | Per-dApp encoding query API for SMs | Dual-encoding only; obsolete under the single-encoding model. |

Also notable inside `aerial-oai-integration` (still reachable there):
`e3fa80c` — ASN.1 setupResponse encode fails when an SM registers with empty
`ranFunctionData`; substituted a 1-byte placeholder. Needed only on **ASN1**
builds; current mitigation is to enable only SMs that provide
`ranFunctionData`. `5dbacba` — accept plain hex-string `actionData`
(now part of the `fa187a0` payload handling). `383ae08` — SubscriptionDetails
use-after-free fix (superseded by the `json-format` branch's SubscriptionDetails
rework, `ea62ba9`).

## Related branches

- `json-format`: an independent camelCase/flat-envelope implementation plus a
SubscriptionDetails C API. Largely overlaps `fa187a0`; its gaps for Aerial
compatibility are `ranFunctionData` always hex-encoded, no
`IndicationMessage.subscription_id`, no subscriptionResponse echoes, and a
strict `json::parse` on indication payloads. Natural upstream target: merge
it to `main`, then layer the `fa187a0` deltas on top.
29 changes: 24 additions & 5 deletions include/libe3/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ struct SetupResponse {
std::optional<uint32_t> dapp_identifier; ///< Assigned dApp identifier (optional)
std::string ran_identifier; ///< RAN identifier (mandatory)
std::vector<RanFunctionDef> ran_function_list; ///< List of available RAN functions (optional)
std::optional<std::string> message; ///< Diagnostic message (typically on negative response)
};

/**
Expand All @@ -228,20 +229,38 @@ struct SubscriptionDelete {

/**
* @brief E3AP Subscription Response structure
*
* Mirrors the fields cuBB's E3 Agent emits: the granted telemetry/control
* IDs, the agent-committed periodicity (may cap what the dApp requested),
* and a diagnostic message on negatives. The aerial dApps read
* telemetryGrantedList and periodicity, when present, to confirm/update
* their subscription state; all of these are optional on the wire, so
* producers that don't populate them stay compatible.
*/
struct SubscriptionResponse {
uint32_t request_id{0}; ///< ID of the corresponding SubscriptionRequest
uint32_t dapp_identifier{0}; ///< dApp identifier
ResponseCode response_code{ResponseCode::NEGATIVE}; ///< Response code (positive/negative)
std::optional<uint32_t> subscription_id; ///< Subscription ID (optional)
uint32_t request_id{0}; ///< ID of the corresponding SubscriptionRequest
uint32_t dapp_identifier{0}; ///< dApp identifier
ResponseCode response_code{ResponseCode::NEGATIVE}; ///< Response code (positive/negative)
std::optional<uint32_t> subscription_id; ///< Subscription ID (optional)
std::optional<uint32_t> ran_function_identifier; ///< RAN function the subscription targets
std::vector<uint32_t> telemetry_granted_list; ///< Telemetry IDs the agent committed to
std::vector<uint32_t> control_granted_list; ///< Control IDs the agent committed to
std::optional<uint32_t> periodicity_us; ///< Agent-committed periodicity (microseconds)
std::optional<std::string> message; ///< Diagnostic message (typically on negative)
};

/**
* @brief E3AP Indication Message structure
*
* `subscription_id` lets receivers correlate indications back to the
* subscription they originated from; cuBB sets it on every outbound
* indication. Optional for backward compat with producers that don't
* populate it.
*/
struct IndicationMessage {
uint32_t dapp_identifier{0};
uint32_t ran_function_identifier{0}; ///< RAN function identifier
uint32_t ran_function_identifier{0}; ///< RAN function identifier
std::optional<uint32_t> subscription_id; ///< Subscription this indication belongs to
std::vector<uint8_t> protocol_data;
};

Expand Down
Loading