Repository navigation
E3Controller: bump libe3 submodule to latest tag 0.2.0 - #7
Merged
Merged
Conversation
aferaudo
added a commit
that referenced
this pull request
Oct 13, 2026
* simplified building * updated asn attributions * testing native memcpy - this should be replaced * removed boolean dependency * fixing logging * added codelet verifier * various fixing * added config file * added support to configuration file * various fixing + config switch shm writer * clock monotonic jbpf * various cmake fixing * various fixing * jbpf patches * fixed libe3 cmake and filtering methods * build fixings * Record the slot path's stages with latrec instead of a per-slot CSV (#6) The per-slot stage CSV opened an ofstream, wrote a row and flushed it, once per slot, inside the sample handler. A synchronous formatted write plus a flush on the slot path costs far more than the intervals it was recording, so every number it produced included the cost of producing it. Measured: ~1840 ns per slot against ~111 ns for the five records that replace it, or roughly 17x. It also documented a mechanism that does not exist: README and two source comments described downstream send stages as joinable through a libe3 `--pub-stages-log` option. There is no such option in libe3 on any branch, so the send side was simply unmeasured. Stamp the same boundaries into latrec instead - one clock read and four stores into an mmap-backed ring, no syscall, allocation, formatting, lock or I/O on the slot path. The mapping onto the shared stage catalog lives in one header, l1_kpm_trace.h, which the handler and the bench both use, so what CI measures is the code that runs on the radio: A1 RECORD_BEGIN -> PROCESS_BEGIN the data recording A2 PROCESS_BEGIN -> ENCODE_E3SM_BEGIN getting it to the SM A3 ENCODE_E3SM_BEGIN -> ENCODE_E3SM_DONE E3SM encode ENCODE_E3SM_DONE -> WAIT_ENTER the emit tail A1 and A2 are recorded here, and the gNB needs no instrumentation for it. Both of A1's boundaries are already on the wire when the slot arrives: gnb_ts_ns is stamped on the last symbol with the grid complete and nothing copied, and codelet_ts_ns just before the codelet submits. So the controller back-dates those two stamps rather than the RAN keeping a ring of its own. That is sound because the whole chain reads CLOCK_MONOTONIC now - the hook, jbpf_time_get_ns() and the dispatcher poll - which is latrec's own clock, so there is no domain conversion. What still has to hold is the ring's own invariant: a single-writer log whose t_ns ascends, whose one permitted descent libe3's reader treats as the wrap point and silently rotates at. Program order gives a wide margin (the jbpf hook is a synchronous inline call, and A1 is tens of microseconds against a >=500 us slot spacing), but a pipeline stall or several sectors interleaving on one ring would break it. So the floor is enforced per thread and the count of enforced stamps is reported, in the drop CSV and the shutdown summary - a non-zero count means A1 is understated for that many slots. Four sub-hops stay recoverable from aux payloads, which is what keeps jbpf dispatch separable from the data movement, and preserves the distinction the codelet's entry/exit timestamp split was added for. Correct the two timestamp comments. codelet_ts_ns was documented as a "codelet entry timestamp" whose interval with gnb_ts_ns was "jbpf invocation + verifier path overhead". It is stamped last, not at entry; the interval is A1, the data recording itself, dominated by the convert and the row write; and there is no runtime verifier cost at all, since the gNB loads through ubpf whose JIT emits no bounds checks and verification is an offline build-time gate. gnb_ts_ns said CLOCK_REALTIME in three places and no longer is. Replace the CSV's option with logging.latrec_dir, which is placement only: whether anything is recorded is decided when libe3 is built, by -DLIBE3_ENABLE_LATREC (./build.sh --latrec). Keep the throttled drop-accounting CSV - it is aggregate and <=1/s, so it is not the thing that perturbed. The legacy eCPRI SM keeps its own stage CSV under its own key; it is a different data path and has the same problem, to be fixed when that path is next touched. Move the libe3 pin to 22f3918 (0.1.2), a fast-forward. Its message-id work surfaces the assigned id to a dApp calling send_control/send_report but not on the Service Model emit path, so origin_seq remains the only cross-component join. Drop the BOOLEAN skeleton staging from build.sh. It existed to have libe3 compile asn_DEF_BOOLEAN for Spectrum-ConfigControl; that type is no longer compiled and nothing references the symbol, so the staging had nothing left to supply while still aborting the build on any host without asn1c's reference skeletons. Add CI, which this repository had none of. It builds both ways, asserts that an untraced binary links no latrec symbols and carries no ring registry, runs the recording-cost bench, and converts a capture with libe3's own tool to check the ring role maps to the intended component, the source leg is complete, the emit-tail hop column materialises, and nothing wrapped. * E3Controller: bump libe3 submodule to latest tag 0.2.0 (#7) Co-authored-by: ocudu <ocudu@localhost> * Resend the helper config after every codelet load Restarting only the dApp stopped all data: the controller kept getting slots but dropped every one, without any warning. Why: on the last unsubscribe the controller unloads the codelet, and the next subscription loads a new one with empty maps. The shm config and the slot selector were sent only once per process, so the new codelet never got them, and the gNB helper refused every slot. The warning for that is printed once, and the first session had already used it. Fix: send the config again after every load (same for the PRB filter of the eCPRI pipeline), and re-arm the one-time warnings on every start. Tested on an OpenShift pod: after a dApp restart the data comes back, with one slot dropped per load. Assisted-by: Claude Opus 5.5 <noreply@anthropic.com> * Update the L1-KPM SM to the latest grammar The L1-KPM grammar now matches OAI's (e3sm_l1_kpm.asn). It adds L1KPM-RanFunctionData and an optional validSymbolMask in the indication. - ranFunctionData is L1KPM-RanFunctionData over APER, and the same fields as a JSON object over JSON, with OAI's values (L1-KPM, version 1). The JSON keeps the ASN.1 field order, so it is byte for byte what OAI sends. - Build checks keep the name and description within the ASN.1 sizes. - validSymbolMask is not sent yet. Its presence bit still changes every APER indication, so ASN.1 dApps need the new grammar. - The generated ASN.1 sources are declared as build outputs, so a new type no longer breaks an existing build folder. - README updated. Tested on an OpenShift pod: the APER decodes back to the same values, the JSON matches OAI's, and an existing build folder rebuilds with the new type. Assisted-by: Claude Opus 5.5 <noreply@anthropic.com> * Build against the gNB's jbpf from the ocudu checkout (#9) The controller is the jbpf IPC primary and the gNB the secondary, so both must be built from the same jbpf. Instead of carrying a second jbpf as a submodule and keeping its pin and patches in step with ocudu's by hand, build against ocudu's external/jbpf (OCUDU_DIR, default ../ocudu-e3). - Drop the jbpf submodule, apply_jbpf_patches.sh and jbpf_patches/; ocudu owns the tree and its patches, and build.sh runs ocudu's idempotent apply_jbpf_patches.sh over it. - CMake: add_subdirectory(${JBPF_DIR}) with an explicit binary dir, ocudu's jbpf options (JBPF_STATIC, JBPF_EXPERIMENTAL_FEATURES), and configure-time warnings when jbpf is not at ocudu's pin or lacks the monotonic patch. - Codelet Makefiles and the verifier take jbpf from the same place. - build.sh: OCUDU_DIR, and LIBE3_PREFIX for installing libe3 without sudo. - CI: fetch jbpf from the public wineslab/ocudu-e3 mirror. Assisted-by: Claude Opus 5.5 <noreply@anthropic.com> * Describe writer: gnb as the default in the configs Both configs already set shm.writer: gnb, but the comment still called the controller mode "today's path" and listed it first. The shipped slot codelet only publishes descriptors, so in controller mode every slot fails with "Slot blob too small". List gnb first as the default, and say that controller mode needs a copy-based codelet that this repository does not ship. Assisted-by: Claude Opus 5.5 <noreply@anthropic.com> * Split the README into docs/ The README had grown to 800 lines. Keep the introduction, a table of contents, Attribution and How To Cite in it, and move the rest into docs/: build, usage, architecture, service models, stage records and known limitations. The Codelets section goes into codelets/README.md, which already covered most of it. While moving the text: - Build: describe how build.sh finds ocudu (OCUDU_DIR) and installs libe3 (LIBE3_PREFIX), and add build.sh examples and the order for building the whole system. - Usage: document shm.writer: gnb only; the shipped codelet does not support the controller writer. - Architecture: redraw the pipeline for the descriptor path (the gNB writes the row, the controller sends only its index) and mark the ecpri_iq stream and the Spectrum SM obsolete, until the SM is updated. Both pipelines release their own jbpf buffers. - codelets/README.md: the verifier is its own target, not part of build.sh. - Point the source comments that cited the README at the new files. Assisted-by: Claude Opus 5.5 <noreply@anthropic.com> * removed comments * fixed how to cite --------- Co-authored-by: Ravis Shirkhani <shirkhani.r@northeastern.edu> Co-authored-by: Andrea Lacava <thecave003@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.