obu-firmware builds against vanetza-idf from microbu-esp32c5/external, but that tree was gitignored, so a clone of this repository could not build the firmware it ships. It is now committed here as ordinary files in its own folder, microbu-esp32c5/: the colleague's commit cf4b99f plus the V2X2MAP bridge's signature verification (--trust) used on the bench. Nothing is fetched from or pushed to the colleague's repository; this repository and its remotes carry everything. The folder's own .gitignore keeps build output, downloaded components and private key material out, as it did there; the committed file set is identical to that repository's tracked files. The ESP32-C5 is still flashed from obu-firmware/, which only takes vanetza-idf from microbu-esp32c5/, so the two stay separate folders. FLASHING.md says how to take a newer version of the colleague's tree (copy it over the folder, rebuild, test, commit).
383 lines
21 KiB
Markdown
383 lines
21 KiB
Markdown
# vanetza-idf
|
|
|
|
A configurable C++17 [Vanetza](https://github.com/riebl/vanetza) library for ESP-IDF,
|
|
with portable access, network/transport, facilities codec and test boundaries.
|
|
The component does not own a FreeRTOS task or start a radio. Applications supply
|
|
time, position, security and access implementations.
|
|
|
|
**Status: experimental port, not an ETSI-conformant complete station.** The
|
|
Release 2 interface bindings and CAM/DENM/VAM codecs are implemented. The
|
|
upstream router provides SHB and GeoBroadcast; complete Release 2 GN, CA/DEN/VRU
|
|
Basic Service behavior, a production security entity and a validated C5 radio
|
|
remain work items. [Conformance status](conformance.md) records these precisely.
|
|
Selecting a codec does not implement the associated Basic Service.
|
|
|
|
## Integrate in an ESP-IDF project
|
|
|
|
Install ESP-IDF separately, then clone this repository recursively inside your
|
|
project's `components` directory. Keep the directory name `vanetza-idf`:
|
|
|
|
```sh
|
|
git clone --recurse-submodules https://github.com/niklasdathe/vanetza-idf.git components/vanetza-idf
|
|
```
|
|
|
|
`master` carries the port including the security entity, identifier change,
|
|
cross-layer SAP bindings and TS 102 941 core (merged from
|
|
`feature/etsi-cross-layer-security` on 2026-09-14 after an ESP32-C5 station
|
|
signed VAMs, CAMs and DENMs under a laboratory chain that an independent
|
|
verifier and a second ESP32-C5 accepted, and after the official AtsSecurity
|
|
campaigns ran against that device; see [validation.md](validation.md)).
|
|
Signing under production credentials of a real PKI has not been demonstrated
|
|
yet. Pin a reviewed commit for reproducible builds. An existing clone needs
|
|
`git submodule update --init --recursive`.
|
|
|
|
Alternatively, keep the clone elsewhere and add its absolute path to
|
|
`EXTRA_COMPONENT_DIRS` **before** including ESP-IDF's `project.cmake`:
|
|
|
|
```cmake
|
|
cmake_minimum_required(VERSION 3.22)
|
|
list(APPEND EXTRA_COMPONENT_DIRS "/path/to/vanetza-idf")
|
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
|
project(my_its_application)
|
|
```
|
|
|
|
The consumer component declares its dependency normally:
|
|
|
|
```cmake
|
|
idf_component_register(SRCS "main.cpp" REQUIRES vanetza-idf)
|
|
target_compile_features(${COMPONENT_LIB} PRIVATE cxx_std_17)
|
|
```
|
|
|
|
Set these in the application's `sdkconfig.defaults`, then select the profile in
|
|
`idf.py menuconfig` → **Component config → Vanetza-IDF**:
|
|
|
|
```ini
|
|
CONFIG_COMPILER_CXX_EXCEPTIONS=y
|
|
CONFIG_COMPILER_CXX_RTTI=y
|
|
CONFIG_ESP_MAIN_TASK_STACK_SIZE=32768
|
|
CONFIG_VANETZA_IDF_PROFILE_NETWORK=y
|
|
```
|
|
|
|
The component manifest resolves `espressif/esp-boost` 0.4.1. Git submodules pin
|
|
the additional Boost headers that package omits. No source-generation tool,
|
|
TTCN compiler, workstation path or host test framework is required to build
|
|
the device library. ESP-IDF >=5.3 is the declared dependency floor; only builds
|
|
listed in [validation](validation.md) have actually been checked.
|
|
|
|
## Choose the entry point
|
|
|
|
| Profile | Feed in | Built functionality | Main API |
|
|
|---|---|---|---|
|
|
| `ACCESS` | GNPDU plus radio parameters | IN-SAP binding and access utilities | `AccessStack::request(AlDataRequest)` |
|
|
| `NETWORK` | Facilities bytes plus BTP/GN parameters | BTP, upstream GN router and its dependencies | `Stack::request(BtpRequest)` |
|
|
| `FACILITIES` | Release 2 CAM, DENM or VAM PDUs | Network profile and independently selected codecs | `facilities::send`, typed `Cam`/`Denm`/`Vam` |
|
|
|
|
`CONFIG_VANETZA_IDF_CAM`, `..._DENM` and `..._VAM` control individual codecs.
|
|
The source manifest includes only the ASN.1 types transitively needed by enabled
|
|
services. `CONFIG_VANETZA_IDF_HIL` adds transport-independent tester framing;
|
|
it defaults off. `CONFIG_VANETZA_IDF_SECURITY` (default on with the network
|
|
profile) builds the signing security entity, the PSA crypto backend and the
|
|
identifier change; `CONFIG_VANETZA_IDF_SECURITY_VERIFY` (default on) adds the
|
|
verification of received secured packets; `CONFIG_VANETZA_IDF_PKI`
|
|
(default off) adds the TS 102 941 request/response core. Optional features are
|
|
removed at compile time, rather than being permanently allocated and merely
|
|
ignored at runtime.
|
|
|
|
The core has no target-specific headers. It is intended for any ESP32 supported
|
|
by the selected ESP-IDF/toolchain with sufficient memory. A C5 radio backend is
|
|
a separate, target-specific adapter; another ESP32 can use an external radio or
|
|
a test lower port. Building on an ESP32 does not establish ITS-G5 PHY support.
|
|
|
|
## Supply an access adapter
|
|
|
|
Implement `vanetza_idf::Access::request(AlDataRequest)`. This method owns its
|
|
argument. Preserve source/destination MAC, priority, power, MCS, bandwidth,
|
|
channel, transceiver/mode and datastream ID. Reject an unsupported control
|
|
explicitly; silently changing it makes interface testing meaningless.
|
|
|
|
`AlDataRequest::data` starts at the **GeoNetworking Basic Header**. The adapter
|
|
adds/removes LLC/SNAP, MAC and PHY encapsulation, and enforces the selected
|
|
access/DCC behavior. A request result means acceptance/rejection by the local
|
|
adapter, not proof of radio transmission. Missing CBR/RSSI observations are
|
|
represented as absent measurements, never invented zeros.
|
|
|
|
```cpp
|
|
#include <vanetza_idf/access.hpp>
|
|
|
|
class Radio : public vanetza_idf::Access {
|
|
public:
|
|
vanetza_idf::Result request(vanetza_idf::AlDataRequest request) override {
|
|
// Validate hardware controls and transfer ownership to your driver queue.
|
|
return vanetza_idf::Result::unsupported; // replace with a real driver
|
|
}
|
|
};
|
|
```
|
|
|
|
This binding follows EN 303 797 Annex B.2. It is a local C++ representation of
|
|
the illustrated service primitives, **not** an ETSI-defined binary ABI. In
|
|
particular, neither a C++ object layout nor raw structs should be sent over BLE,
|
|
SPI or USB. Define an explicit versioned serialization for an inter-device link.
|
|
|
|
## Security entity and identity management
|
|
|
|
`vanetza_idf/security.hpp` provides a signing security entity for the SN-SAP
|
|
(TS 102 723-8) that the GeoNetworking router calls for every outgoing packet
|
|
when `itsGnSecurity` is set. The application provisions it; nothing is built
|
|
in:
|
|
|
|
```cpp
|
|
using namespace vanetza_idf::security;
|
|
vanetza_idf::BackendMbedTls backend; // PSA Crypto (host: vanetza::security::BackendOpenSsl)
|
|
TrustConfiguration trust; // root CA and the AA(s) of the tickets, COER
|
|
trust.add_root(root_coer); trust.add_authority(aa_coer);
|
|
CertificatePool pool {backend}; // authorization tickets with their private keys
|
|
pool.add(at_coer, at_private_key); // TS 103 097 clause 7.2.1 profile checked, key probed
|
|
SecurityEntity entity {runtime, position_provider, backend, pool, trust};
|
|
Stack stack {config, runtime, access, &entity};
|
|
```
|
|
|
|
The entity applies the TS 103 097 V2.2.1 signing profiles by ITS-AID and the
|
|
SN-ENCAP `context_information`: CAM (clause 7.1.1: digest, certificate once
|
|
per second or when a new CAM signer was reported), DENM (clause 7.1.2:
|
|
certificate, generationLocation), generic/GN-MGMT (clause 7.1.3), VAM
|
|
(TS 103 300-3 clause 6.5: individual 1 s, cluster 500 ms through
|
|
`context::vam_cluster`). Without a valid ticket for the requested ITS-AID and
|
|
permissions, or without an anchored chain, the request is refused and counted
|
|
(`SecurityEntity::statistics()`); nothing is transmitted unsigned.
|
|
|
|
SN-DECAP verifies received `EtsiTs103097Data-Signed` packets (IEEE Std 1609.2
|
|
clause 5.2 as TS 103 097 clause 5.2 requires): the TS 103 097 clause 7.1
|
|
structure for the ITS-AID, the signer (inline certificate or a digest learned
|
|
earlier), the ticket's validity, permissions and region, every certificate
|
|
signature up to a provisioned root, the permission and region consistency of
|
|
the chain (IEEE Std 1609.2 clause 5.1.2: chain length windows, eeType, SSP
|
|
ranges of every ancestor; clause 6.4.17: every region inside its issuer's,
|
|
identified regions by identifier), the message signature, then the
|
|
generationTime window and replay detection of `VerificationPolicy`
|
|
(`set_verification_policy`). A CAM from an unknown station or with an unknown
|
|
AA triggers the P2P certificate distribution of clause 7.1.1 through the header
|
|
policy, and an AA received in `requestedCertificate` is learned once it chains
|
|
to a root. The GN router drops what does not verify (`itsGnSnDecapResultHandling`
|
|
STRICT) and passes report, ITS-AID and SSP of what does up to BTP. Without
|
|
`CONFIG_VANETZA_IDF_SECURITY_VERIFY` the report is `Configuration_Problem` and
|
|
nothing secured is passed up (docs/idf/conformance.md GAP-SEC-001). Identified
|
|
regions (country codes) are accepted for the position check, and a circular/rectangular/
|
|
polygonal region under an identified one is accepted in the chain, while
|
|
`VerificationPolicy::permissive_identified_region` is true (no border database
|
|
on the device); set it to false to reject both. Encryption is not implemented.
|
|
Revocation is: with `VIDF_PKI`, `pki::parse_rca_ctl`/`parse_crl` read a root's
|
|
CTL and CRL as fetched from its distribution centre (TS 102 941 clause 6.3;
|
|
the HTTP GET is the application's) and `pki::apply` turns them into trusted
|
|
issuers and revocations (`TrustConfiguration::revoke`) the chain validator
|
|
honours (`REVOKED_CERTIFICATE`). Budget on the ESP32-C5: about 34 ms per verified message, 29 ms of
|
|
which is the ECDSA peripheral (validation.md).
|
|
|
|
`IdentityManager` implements the identifier change of TS 102 723-8 clause 6.3:
|
|
subscribers (the GN core when `itsGnLocalAddrConfMethod` is ANONYMOUS, the
|
|
facilities layer through `sf_sap.hpp`, any other layer through `sn_sap.hpp`)
|
|
receive PREPARE, answer through the responder, then COMMIT with the HashedId8 of
|
|
the next ticket or ABORT; ID-LOCK holds the identifier for 0..255 s. A
|
|
subscriber may run in the same task, in another task or process, or on another
|
|
device; the responder object may be answered later from anywhere. The library
|
|
defines no transport for that and no policy for *when* to change: the
|
|
application triggers, the manager sequences.
|
|
|
|
The private keys of the tickets stay with the application: the pool holds
|
|
them, the backend imports them as volatile PSA keys, and no key ever leaves the
|
|
device through this library. The test trust domain of the component tests
|
|
(`tests/test_trust_domain.*`, `vidf_test_pool`) is generated per run and is not
|
|
a PKI. To issue a chain under a root of your own for lab use (root, AA,
|
|
tickets in the pool layout, EU CCMS CPOC root profile) there is the host tool
|
|
`vidf_issue`, and `tools/capture_pcap.py` records what a host or device
|
|
station signs as an 802.11 pcap for an independent verifier; both are
|
|
described in [test-campaigns.md](test-campaigns.md).
|
|
|
|
**Provisioning and storage: what is the library's and what is yours.**
|
|
`vanetza_idf/credentials.hpp` fixes the octets between a provisioning path
|
|
and the security entity: a `Credentials` value (root certificates,
|
|
subordinate CA certificates, tickets with their private scalars, all COER or
|
|
raw), its bundle encoding (`VCR1` records) and `apply()` into a
|
|
`TrustConfiguration` and `CertificatePool` through the same checks the
|
|
entity applies to anything it signs with. `CredentialStore` is the storage
|
|
interface; the library ships `FileCredentialStore` (a bundle in one file,
|
|
hosts or a mounted VFS) and, with `CONFIG_VANETZA_IDF_NVS_CREDENTIALS`
|
|
(default on), `NvsCredentialStore` on the `nvs_flash` component: one blob
|
|
under a namespace/key of your choosing. That much is generic to any ESP32
|
|
station and therefore in the component. What stays with the application:
|
|
initialising NVS and deciding whether it is encrypted (ESP-IDF NVS
|
|
encryption; the bundle carries keys in the clear), the transport the bundle
|
|
arrives over (a serial diagnostic channel, a wireless link, a TS 102 941
|
|
client, a file) and the policy of when to load, replace or erase credentials.
|
|
The test application shows the pattern: diagnostic command 9 hands a bundle to
|
|
the SUT for its next reset (`serial_sut.py --bundle`), and the component tests
|
|
exercise the NVS store on the device. Nothing in the library reads a bundle
|
|
on its own initiative.
|
|
|
|
## Cross-layer SAPs
|
|
|
|
The management and security SAPs of the ITS station are bound as plain C++
|
|
types and `*_request_submit` functions, one header per SAP, each declaration
|
|
commented with its standard, edition and clause:
|
|
|
|
| Header | SAP | Serves |
|
|
|---|---|---|
|
|
| `sn_sap.hpp` | SN-SAP, TS 102 723-8 V2.0.0 (V1.1.1 Tables 10 to 27) | SN-ENCAP/-DECAP into the security entity; SN-IDCHANGE-*/SN-ID-LOCK into the identity manager |
|
|
| `sf_sap.hpp` | SF-SAP, TS 102 723-9 V1.1.1 | The same identity manager for the facilities layer (clause 4.1.5); SF-SIGN/-VERIFY/-ENCAP/-DECAP as types only |
|
|
| `mn_sap.hpp` | MN-SAP, TS 102 723-4; TS 103 836-4-1 Annex K; TS 103 175 clause 8.3 | `CORE_MMT_response_apply` (time, position, address, TC mapping) into the stack; DCC N-Params through the application's provider |
|
|
| `mf_sap.hpp` | MF-SAP, TS 102 723-5 V2.0.0; TS 103 175 clause 8.4 | DCC F-Params into the application's facilities layer |
|
|
| `mi_sap.hpp` | MI-SAP, TS 102 723-3; TS 103 175 clause 8.2 | DCC I-Params through the application's access adapter |
|
|
|
|
The peer of each binding (management entity, facilities layer, access adapter,
|
|
identifier-change subscriber) may live in the same task, another task or
|
|
process, or another device. The library defines no transport, serialization or
|
|
RPC for these primitives, invents no DCC measurement (an absent provider
|
|
answers ErrStatus 250, an undefined command ErrStatus 5 per TS 102 723-3 clause
|
|
5.2.3) and keeps every optional peer compile-time selectable. The default build
|
|
is one un-split station.
|
|
|
|
## Own the stack from one event loop
|
|
|
|
```cpp
|
|
#include <vanetza_idf/stack.hpp>
|
|
|
|
vanetza::ManualRuntime time;
|
|
vanetza_idf::StackConfig config;
|
|
// Configure GN identity, radio controls and the MIB before construction.
|
|
// Supply a security::SecurityEntity when itsGnSecurity is true (the default).
|
|
vanetza_idf::Stack stack(config, time, radio, security_entity);
|
|
|
|
stack.on_receive([](vanetza_idf::BtpIndication indication) {
|
|
// Dispatch the owned facilities payload by destination_port and BTP type.
|
|
});
|
|
stack.on_access_result([](vanetza_idf::Result result) {
|
|
// Record actual lower-adapter acceptance/failure, including later forwarding.
|
|
});
|
|
```
|
|
|
|
Keep `time`, `radio` and the security entity alive until after stack destruction.
|
|
Advance time, inject position, call request/indicate and destroy the stack from
|
|
the **same application task**. ISRs and other tasks enqueue events to that task.
|
|
Do not re-enter the stack from callbacks. No global singleton is required;
|
|
independent stacks can coexist.
|
|
|
|
Supply a coherent position with `update_position(PositionFix)` and an ITS epoch
|
|
clock via `advance(Clock::time_point)`. Upstream `Clock` counts microseconds from
|
|
2004-01-01; `esp_timer_get_time()` alone is uptime, not ITS time. The application
|
|
must maintain the absolute-time mapping and uncertainty. Regressing time is
|
|
rejected. Reinitialize an instance when an epoch reset is required.
|
|
|
|
For BTP, port values are in host byte order; the library serializes them in
|
|
network byte order. BTP-A requires a source port and excludes destination port
|
|
info; BTP-B excludes a source port. Optional GN parameters inherit the configured
|
|
MIB. Unsupported GN transports return `Result::unsupported`, never silently
|
|
become a different transport. `accepted` means submitted for protocol processing;
|
|
it is not a promise of RF delivery.
|
|
|
|
## Build and test the standalone examples
|
|
|
|
```sh
|
|
cd examples/esp_idf
|
|
idf.py set-target esp32c5
|
|
idf.py build
|
|
```
|
|
|
|
Use `esp32`, `esp32s3`, or another SDK target for the same portable example.
|
|
`sdkconfig.access` and `sdkconfig.network` are alternative profile overrides.
|
|
Supply overrides using `SDKCONFIG_DEFAULTS` with a **fresh sdkconfig/build
|
|
directory**; changing defaults does not rewrite an existing sdkconfig. The
|
|
example deliberately uses a rejecting access adapter and emits no RF traffic.
|
|
|
|
`examples/esp_idf_test` runs the same component regression code on a device.
|
|
Select the correct target and port before `idf.py flash monitor`. Retain
|
|
`VIDF_TEST_RESULT=0`, firmware hash, target, SDK version and configuration.
|
|
These are component tests, not TTCN verdicts or radio-conformance evidence.
|
|
|
|
On a host with CMake, a C++17 compiler and Boost development headers:
|
|
|
|
```sh
|
|
cmake -S ports/esp_idf -B build-host -DVIDF_TESTS=ON
|
|
cmake --build build-host
|
|
ctest --test-dir build-host --output-on-failure
|
|
```
|
|
|
|
Host configuration uses `VIDF_NETWORK`, `VIDF_CAM`, `VIDF_DENM`, `VIDF_VAM` and
|
|
`VIDF_HIL` with the same meaning as the device features. Build with all four
|
|
network/facilities features off to test the access-only configuration.
|
|
|
|
## Connect a separately installed ETSI TTCN-3 framework
|
|
|
|
**The user installs and configures TTCN-3, its runtime, the ETSI ATS, codecs,
|
|
platform adapter and SUT adapter separately.** This repository neither installs
|
|
nor vendors that framework. Start from the official
|
|
[ETSI ITS Test Suite](https://forge.etsi.org/rep/ITS/TS.ITS) and its suite-specific
|
|
instructions. Choose and record immutable revisions and the associated published
|
|
ATS, TSS/TP, PICS and PIXIT editions.
|
|
|
|
The test architecture is:
|
|
|
|
```text
|
|
ETSI TTCN-3 ATS + codecs + platform/SUT adapter (host)
|
|
| upper tester: suite-specific commands and real result/event indications
|
|
| optional USB/UART/Ethernet transport, supplied by the test application
|
|
v
|
|
test application on ESP32 -> service/BTP/position/security hooks -> stack
|
|
|
|
|
lower tester <-> Access adapter
|
|
or independent ITS-G5 test radio
|
|
```
|
|
|
|
| Test point | Connect to | Intended use |
|
|
|---|---|---|
|
|
| Facilities upper tester | Actual CA/DEN/VRU service trigger, update, termination, position and pseudonym operations | Test generation rules, timers and service state; it must invoke the service under test, not prebuild the expected PDU |
|
|
| BTP upper tester | `Stack::request(BtpRequest)`; result/events from the actual operation and `on_receive` | Test BTP-A/B headers, payload delivery and port handling |
|
|
| GN upper tester | Router request/configuration through the test application | Test supported GN transports, forwarding and lifetimes; unsupported transports remain explicitly unimplemented |
|
|
| Position/time control | `Stack::update_position` and `Stack::advance` | Deterministic host/component tests; physical campaigns use measured real time and ATS-defined timing tolerances |
|
|
| Security | Injected `SecurityEntity`, real credentials and trust configuration; `vidf_sut --security-pool` for the host | Test signing and authorization (`etsi_security_gn.cfg`, `etsi_security_facilities.cfg`) and reception (`etsi_security_receive.cfg`: the test system signs in TTCN-3, the adapter reports what the SUT passes up); an absent signer cannot produce success |
|
|
| Software lower tester | `Access::request` (outgoing GNPDU), `Stack::indicate` (incoming GNPDU and metadata) | HIL for BTP/GN on the MCU while bypassing RF; codec conversion must preserve the ATS lower-port semantics |
|
|
| Physical lower tester | Independent ITS-G5 capture/injection radio | Test MAC/PHY, channel behavior, radiated packets and integrated ITS-G5 behavior |
|
|
|
|
`hil::Decoder`/`hil::encode` offer an optional bounded envelope:
|
|
`VID1 | channel:u8 | sequence:u32be | length:u16be | payload | CRC32:u32be`.
|
|
Channel 1 carries upper tester bytes, channel 2 lower tester data, and channel 3
|
|
diagnostics. This framing is a **library transport choice**, not an ETSI wire
|
|
protocol. The host SUT adapter or bridge adds/removes it. Match the suite's own
|
|
UT codec revision and command layout; no universal UT opcode table is assumed.
|
|
|
|
The `hil::UpperTester` callback accepts raw suite-specific UT payload and may
|
|
return a real encoded result. A missing handler or unsupported command must not
|
|
produce a success response. Sequence numbers correlate request/results;
|
|
asynchronous events need a separately defined convention in your SUT adapter.
|
|
The transport itself does not determine PASS, FAIL, INCONC or ERROR.
|
|
|
|
The official BTP and GN test ports may contain separate lower-layer encodings
|
|
and metadata; raw GNPDU bytes are not automatically their complete wire format.
|
|
Implement that conversion in the host SUT adapter and verify it independently.
|
|
Example ETSI adapter sources to inspect are `UpperTester` codecs under
|
|
`ccsrc/Protocols` and the selected ATS `lib_system` test ports.
|
|
|
|
For Release 2, do not simply relabel an older ATS. Check each TP's referenced
|
|
clause, ASN.1/CDD version, PICS option, template and UT encoding. Keep any
|
|
adaptation in an auditable overlay in the **external test project**, retain the
|
|
original case identity and record added/changed coverage. Keep official,
|
|
adapted and component-test verdicts distinct. Record absent test coverage.
|
|
|
|
For each campaign retain: firmware/source hashes, sdkconfig, SDK/compiler and
|
|
target, ATS/runtime/adapter revisions, PICS/PIXIT, case list, verdicts, complete
|
|
logs, packet captures, clock calibration and the actual upper/lower boundaries.
|
|
A SUT's mirrored outgoing bytes establish software behavior, not independent RF
|
|
transmission. Do not change production protocol behavior merely to satisfy UT.
|
|
|
|
## Design and standards references
|
|
|
|
- [Standards and interface traceability](standards.md)
|
|
- [Conformance and implementation gaps](conformance.md)
|
|
- [Build and test evidence](validation.md)
|
|
- [Source manifest](../../ports/esp_idf/source-manifest.json)
|
|
- [Upstream and dependency licenses](../../LICENSE.md)
|
|
|
|
The fork retains upstream history and notices. Only selected sources enter the
|
|
IDF component. Upstream host tools, cellular/IPv6 application paths, RPC, PQC,
|
|
PKI clients, infrastructure and collective-perception services are outside the
|
|
embedded profile. The repository keeps upstream sources to support merging;
|
|
source presence does not mean the component compiles or links those modules.
|