Skip to content

Release 3.7.5 part 2 - #1065

Merged
duartenfonseca merged 53 commits into
COVESA:masterfrom
andrefesilva:release_3.7.5_part_2
Aug 14, 2026
Merged

Release 3.7.5 part 2#1065
duartenfonseca merged 53 commits into
COVESA:masterfrom
andrefesilva:release_3.7.5_part_2

Conversation

@andrefesilva

Copy link
Copy Markdown
Contributor

No description provided.

thalessouza and others added 30 commits August 14, 2026 11:36
Remove invalid tests from test_boardnet.cpp.
The test_shadow_events.permute_eventgroup_sub_subscribe_before_offer and
test_shadow_events.permute_eventgroup_sub_late_field_offering tests were verifying cases
that should not be accepted on vSomeIP. An application should never
offer an event after their service were already offered.
Increase the waiting time for the start and add a predicate.
The time used in run_condition_.wait_for() was too short. Under valgrind and heavy loaded environments,
the test could take longer to send the notify_one used to wake it up, causing the test to never entering
the start_test method.
e.g.,:
2026-06-03 14:36:34.079966 service-sample [info] Using configuration file: "debounce_filter_test_service.json".
...
2026-06-03 14:36:39.245596 service-sample [info] Starting test

The logs above prove that at least more than 5000 ms passed between the start of the test and the notify_one().

To prevent this, the waiting time was increased and a predicate was added to ensure we don't lose
the notification due to spurious wake up or other possible races.
The logging was also improved to facilitate future analysis.
Struct based approach for the routing info command
Migrate the variable-length ROUTING_INFO command to the struct-based IPC approach.
Unlike the fixed-size trivial commands, each entry carries a nested,
variable-length payload (an optional IPv4 endpoint plus a list of services).
NoteThe former routing_info_command class is marked deprecated but remains
functional -- it will be removed once all dependent code paths are migrated in follow-up PRs.

For reference:

1b1d43d
fb7b611
da84c20
dd4f7a8
63ee6c9
7288f6c
75a1a83
Struct based approach for the register event command
Migrate the variable-length REGISTER_EVENT command to the struct-based IPC approach.
Unlike the fixed-size trivial commands, each registration carries a nested,
variable-length payload, so the migration introduces:
NoteThe former register_events_command class is marked [[deprecated]] but remains
functional -- it will be removed once all dependent code paths are migrated in follow-up PRs.

For reference:

1b1d43d
fb7b611
da84c20
dd4f7a8
63ee6c9
7288f6c
75a1a83
When we receive a message, this should have been "requested".
If there is no corresponding handler installed, this should imply
the application is doing something funky, or is about to be torn down.
Drop the obsolete libvsomeip2 compatibility hack that upgraded a plain event to a selective event
Remove the ET_SELECTIVE_EVENT special-case that erased superseded plain (ET_EVENT)
entries from pending_event_registrations_.
No supported app registers the same event under two types; the branch is dead code.
Create regression test
send_error() erases the TCP send target while its async write completion (send_cbk) is still pending; once the
target is recreated by a notification and the held completion is released, send_cbk runs on an empty queue and
crashes in read_uint16_be.
Change the default configuration to use only a single
io-thread.
And sync them under the consumer mutex.
Meanwhile the endpoints are managed together with the
routing_info. This avoids ping-pong between the rmc and
the emb.
stop_application_from_dispatcher_thread does what the name says - but
this is exactly a scenario where an application can outlive the "user
code", because of the dispatcher thread
This is very problematic if both new/old application should be the
router, which is exactly what breaks the following test when this tight
race happens
Remove export from helpers that do not need it, and add override where
sensible
Replace the two remaining security commands
Get rid of virtuals usage to build up a SOMEIP message
Build SOME/IP messages directly from a message_header_impl via new constructors
on message_impl/message_base_impl, instead of constructing an empty message
and populating it through virtual set_* setters.
Migrate variable-sized commands (CONFIG / ASSIGN_CLIENT) to the struct-based IPC approach.
This follow-up introduces config_command_data and assign_client_command_data, value-type
structs carrying a command_header and a zero-copy, string_view-based payload.

deserialize.hpp gains a zero-copy
key-value view for CONFIG payloads and a struct-fill overload for assign_client_data.
serialize.hpp is extended with constexpr-if branches for config_entry, assign_client_data,
std::string_view, and generic ranges.

NoteThe former config_command and assign_client_command classes are marked [[deprecated]]
but remain functional -- they will be removed once all dependent code paths are migrated
in follow-up PRs.

While at it, thread std::string_view through lazy_load  and request_client_id to defer
heap allocations.
Consolidate round-trip unit tests into ut_commands_roundtrip.cpp.
For reference:

1b1d43d
fb7b611
da84c20
dd4f7a8
63ee6c9
7288f6c
29ab425
77a61c5
f4fbc72
Clear service info only doesnt remove ports.
Previously, there was a failure for services that were offered
on both tcp and udp ports, where the clear of the service info
would clear one of its ports, but not the other, and as such the
stop offer for said service would only have one of the ports
instead of 2, potentially leading to an inconsistent state of
availability in a client.
To fix it, don't remove any of the ports of the service info
before sending the stop offer, and only call it once.
Somewhat obvious, used helpers have no syncronization at all. It
also fixes test_boardnet_helper.udp_connection_refused_send
Replace subscribe_command, unsubscribe_command
and expire_command
Retry unreliable suspend trigger in suspend test cases.
A supposed bug in the routing manager can lead to an OfferService
being sent before the UDP endpoint is ready, leading to the UDP trigger
being sent too early (and thus lost) by suspend_resume_test_connections.
As a workaround, resend the trigger until the expected unavailability
is observed.
This is intended to be a temporary
measure to make the test stable despite the supposed bug.
The workaround should be removed again once the bug is fixed.
Fix another source of flakyness in suspend_resume_test_initial.
Remove the special case of skipping SIGUSR1 in the first iteration.
Without it, the client relies on the SD offer to expire due to
the 2s eth0 blip to mark the service as unavailable, and depending on
timing, that expiration might not happen at all due to network being
restored before TTL of the offer is reached.
Additionally, first iteration never actually expired the subscription
(which is the gate on top of the loop), so its resume was emitted right
before the next iteration's suspend, and depending on signal ordering
(which is unspecified!), this could screw up expectations.
Remove the obsolete class-based command implementations
Migration to follow struct based approach is completed.
The struct-based command serialization is now consolidated in serialize.hpp,
deserialize.hpp and command_types.hpp.
The ut_compatibility_*.cpp unit tests only existed to prove the new structs serialized
byte-for-byte identically to the old classes; with the old classes gone they serve no purpose
and are removed as well. Pure removal — 97 files, no functional change.
Move availability state and subscription/event-caching from application_impl into routing_manager_client.
move available_state_, per-subscription state, and initial-event-received flags to routing_manager_client
on_availability notifications are collected while consumer_mutex_ is held and fired after it is released,
preventing a race where a concurrently registering availability handler could initialize
its shadow against stale state.
subscribe() now checks whether the subscription is already acknowledged:
if so it immediately delivers cached events and fires the ACK locally without re-sending a subscribe message
to the router. Incoming notifications are dropped at the RMC layer if no active subscription is present.
Reconnect upon receiving new client id
Previously, if for some reason a client received a second
assign client id ack message, it would leave the client in
a inconsistent state, where it would update its client id
internally, but not update security policies or its server
endpoint client id.
To minimize synchronization errors that might happen
while updating the client id on the go, trigger a new register
so that the whole registration sequence is done in a clean state.
The Android build fails compiling routing_manager_stub.cpp with clang:
routing_manager_stub.cpp:1054: error: non-constant-expression cannot be narrowed
from type 'vsomeip_v3::length_t' (aka 'unsigned int') to
'std::span<...>::index_type' (aka 'int') in initializer list [-Wc++11-narrowing]
Two adaptations are required:

when the service turns available
when the service is already available

Note:
This change is only for ipc. No behavior change
for boardnet.
Meanwhile:
Simplify the parsing of command_messages.
Most of these are subtle off-by-one overflows, code that would parse
specific fields from the SOME/IP header, and check that the packet had
just enough length. For these overflows, incorrectly
These length checks are folly - such code should instead check that the
packet contains at least a SOME/IP header. It is less error-prune
While at it, minor code simplifications
Add a condition to process REGISTER_EVENT with RT_UNKNOWN
When a client requests an event without specifying reliability RT_UNKNOWN(255), it’s basically saying, “I, the app,
don’t know / don’t care—vsomeip, figure it out yourself based on the offer.” So we should keep the reliability that’s
already set instead of logging an error.
Parallelize network tests.
In order to allow for full parallelization, execute network test cases
inside a sandbox (via bubblewrap) isolating things like PIDs and tmpfs.
Establish a private network namespace for each test run, so even
lower-level communication does not interfere. Test cases invoked via
CTest now are launched through a new script 'run_isolated.sh' that
takes care of setting everything up; no changes are required to the
test cases themselves.
Many of the network test cases require access and communication to a
slave container. The slave container cannot be shared with other test
runs. In order to allow for parallelization of such test cases, it is
possible to have Docker spin up a pool of slaves, via adding a
parameter '--scale slave=N' to the invocation of 'docker compose',
for example:
docker compose --project-directory zuul/network-tests up --scale slave=16
This will spin up 16 slave containers in addition to the master.
CTest provides a way to safely allocate [1] such slaves to specific
test cases for the duration of their run, and schedules parallel test
cases accordingly. To tell CTest about slave(s) being required for
a particular test case, the 'add_custom_test()' function now takes a
an optional argument 'SLAVES N' where N is the number of slaves
required; usually 1, but more or no slaves are supported too.
As a result, concurrency is now constrained by two factors: Overall
concurrency limit which is defined by the number of available CPU
threads, and the number of available, unused slave containers at
any given time for the test cases that need them.
As tests are now executed within a network sandbox, they can no longer
access the slave containers directly (and in fact, on the master side
the slaves get assigned dynamic IPs, which test configs cannot deal
with). Instead, the isolation script creates a virtual LAN inside
the sandbox and bridges the needed slave(s) into it. In order to
avoid collisions with host-side communication, the isolated VXLAN
uses a distinct address range 10.99.0.X, with the master being
assigned 10.99.0.254 and the slave(s) being assigned consecutive
IPs starting from 10.99.0.1. As these IPs are fixed both inside
the sandbox and inside the slave container(s), hardcoding the value
in test configs continues to work.
Some test cases rely on filesystem-based communication between the
host sandbox and the slave container. To make this possible, for each
test case there is now a directory created (inside a tmpfs) that is
both exported into the host-side sandbox under /home/shared, and
on the slave side symlinked to that same path.
The path is put in the test's environment as TEST_SHARED_DIR,
and a utility function get_test_shared_dir() is provided for
use in the C++ parts of tests.
[1] https://cmake.org/cmake/help/latest/manual/ctest.1.html#ctest-resource-allocation
Demote "Service property mismatch" log from error to warning in
routing_manager_impl::request_service.
The routing manager already handles the mismatch gracefully, therefore
WARNING suffices.
This is a behavior preserving change and serves
as preliminary work to enable the local_offering_table
to store multiple service, instance pairs for different
major versions.
It is assumed that the flat-buffer storage for the services,
should be cache friendly, while still allowing wild-card
searches.
fix the e2e tests
Previously, in the e2e, the application was introducing 2 sleeps of 1 second
upon receiving the service availability, and subscribing in the middle of the sleeps.
This is wrong since the service can be subscribed before receiving the availability,
and the sleep before subscribing the service would delay the subscription enough
(when running with valgrind) that the client would send the subscribe very close to
the next cyclic offer. If, due to valgrind delays, the client received the cyclic offer
while having sent the subscribe to the service but had not received the subscribe ack,
it would trigger the resending of the initial events that lead to the failure in this test.
To fix this, subscribe to the service before starting and dont sleep when receiving availability,
joaofesilva and others added 23 commits August 14, 2026 11:36
Log buffer on endpoint receive_cbk errors
Improve logging deficiencies when endpoint receive_cbk had errors.
This will help debug future issues of malformed messages received
Reserve port ranges used by test cases.
Prevent port ranges hardcoded in test cases to be used by the kernel
for ephemeral ports. Otherwise, the kernel may have assigned a port
that a test case expects to be using to something else, such as the
ssh connection to a slave container. This lead to spurious test
failures in the past.
Service announces availability before all endpoints are up
Problem 1 — Server offers a UDP+TCP service before both endpoints are up
A provider configured with both an unreliable (UDP) and a reliable (TCP) endpoint could send an OfferService
that carried only one endpoint, because the SD offer was serialized in the window between the two server
endpoints being created. A consumer then became available from that incomplete (e.g. TCP-only) offer and, when
it sent a message to the not-yet-existing UDP endpoint, the message was dropped.
Now, service_discovery_impl::are_offer_endpoints_ready() withholds the OfferService of an RT_BOTH service until
both endpoints exist.
Problem 2 — Consumer drops a request when the requested reliability isn't up yet
On the consumer, a request looks up the remote client for the requested reliability
(find_or_create_remote_client(reliable)). When a service is available through one reliability only — a genuinely
single-reliability service, or the transient window while a remote ECU offers its endpoints incrementally
(UDP-only offer, then UDP+TCP) — the endpoint for the other reliability does not exist yet, so the lookup returns
null and the request is dropped with the same Routing info for remote service could not be found error.
Now, in routing_manager_impl::send(), if the remote client for the requested reliability is missing, fall back to the
other endpoint when it is valid (the service is available, so one endpoint is guaranteed reachable); only when
neither exists do we keep the original error.
Fix spurious rmi::send() ERROR logs during STR teardown and normalize drop-path log format.
Three send() drop paths in rmi logged ERROR for conditions that are expected during teardown:
Response to deregistered client (local path): downgraded to WARNING — client intentionally
disconnected, message correctly dropped.
Request to remote service during suspension: downgraded to WARNING with (suspended)
tag — routing info was cleared as part of the suspend procedure.
Request to remote service (outside suspension): kept ERROR.
All three now share a consistent format including message type.
Mark the endpoint as no longer established before reporting the disconnect.
Currently, the endpoint's established state (state_) is only reset when restart() runs, but some callers
(e.g., TCP send_cbk / wait_until_sent) invoke on_disconnect before restart() is called. So there's a
window where the connection is already gone but the endpoint still reports is_established() as true.
During that window, the disconnect path calls service_endpoint_disconnected(), which then calls
on_stop_offer_service() while the SD thread concurrently runs rmi::add_routing_info(). It then read
is_established() == true, and re-offer the service via on_offer_service(). Since the two transitions
are unsynchronized, the re-offer can land after the stop-offer, leaving the remote service spuriously
available even though the connection has dropped.
To fix the issue, this PR adds a common path on the client_endpoint_impl called notify_disconnect
and a new offer_service_if_established method for the routing_manager_impl, with both locking
the same mutex to prevent this specific race from happening.
Drop E_MALFORMED_MESSAGE when usei receives bad length.
Drop E_MALFORMED_MESSAGE in the magic cookie logic. It's neither
necessary nor specified anywhere
Since we only transmit complete messages within internal
communication, having to wait for more then 5s for a
remainder of a message can be used as a very strong hint,
that the sender might have send corrupted data.
Add handler exception logs
Previously, when there was an exception in an application handler,
the log printed would just be the blocking call.
With this change, there is a dedicated log for exceptions,
that should help the debugging.
The eventgroupinfo is a 90% boardnet class.
The rmc should not use this class at all.
As part of this PR the provider is already removed.
It ought to be a uint32_t so the rest of the codebase does not have to
do any casting
The test sends quite a few messages, so under load it could timeout
A memory corruption was detected in SOME/IP-TP where fully overlapping segments would trigger
an unsigned length underflow and lead to a crash.
The received packet should correctly reassemble overlapping and duplicated
segments by overwriting using the content of the first segment received.
This PR fixes the incorrect segment ordering (could make a fully overlapped segment to be ordered
first, though its start offset is higher) and ignore the received segment.
Unused since.. 2019, since 9befbcd
Fix crash of TCP socket closed mid send
There was a crash where a subscriber's local-TCP connection was torn
down while sending a message. This PR fixes that crash.
The ASIO socket wrappers held their Boost socket by value,
and async completion handlers
only captured weak_from_this — nothing kept the underlying
socket alive for the duration of a send.
With more than one io-thread there is a specific case where the daemon sends a large
notification over local TCP while at the same time the sockets are being destroyed due
to the clients being closed causing a std::terminate().
The socket/acceptor wrappers (asio_tcp_socket, asio_udp_socket, asio_uds_socket,
asio_uds_acceptor) now hold their underlying Boost socket/acceptor via std::shared_ptr, and
every async operation captures a copy of that pointer into its completion handler.
A unit test was failing because with sockets now outliving a reset, the test's pending
async_receive_from handler reads unicast_socket_ under sync_ after the test resets it.
Added a lock for the sync_ mutex.
Fix load_eventgroup silently dropping all but the first event of an
eventgroup's events array due to a reused std::stringstream left in
EOF state.
Regression from commit b1e7bab (COVESA#840),
which removed the previously local std::stringstream from the events
loop.
Fixed by resetting the shared converter (its_converter.str(""); its_converter.clear();) at the top of the events k-loop in
implementation/configuration/src/configuration_impl.cpp.
Added TEST(configuration_test, eventgroup_multiple_events), which
declares an eventgroup with three events (only defined via the
eventgroup) and asserts get_event_reliability() returns
RT_UNRELIABLE for all three — failing under the bug (RT_UNKNOWN) and
passing with the fix.
Drop orphaned SOME/IP responses/errors addressed to a consumer that no longer requests the remote service,
preventing client-id-reuse cross-talk.
A consumer requests a remote service and sends a request; the reply returns asynchronously. If it meanwhile
deregisters, releases the service, or its connection drops and its client id is recycled to another app, the late reply
reaches the host routing manager addressed to a client id that no longer requests the service and is forwarded
blindly — so an unrelated app receives a response it never asked for (id-reuse cross-talk). This PR drops such replies
unless the target is still a requester.
Scope: only remote services via the host send(); local proxy-to-proxy bypasses it, where the receiving client drops it
if no handler matches the service/instance/method, and with CommonAPI it drops by session id.
Add Sanitizers/Valgrinds log on build
This information was removed by ef26b9d
Decouple consumer vs. provider error handler
A routing_manager_client can be, toward the same peer, both a provider (accepted socket, for a
service it offers) and a consumer (outbound socket, for a service it consumes) — two distinct local
sockets keyed only by client_t. The connection-error handler did not carry the role, so an error on
either socket tore down BOTH roles' state: a consumer-socket failure dropped remote subscribers of
our offered services, and a provider-socket failure marked peer-offered services unavailable and
closed our outbound consumer endpoint.
vsomeip-lib build was failing due to the usage of to_address.
The provider side of routing_manager_client tracked offered
services in two parallel containers:
provided_services_ (a services_t map of serviceinfo) and
pending_offers_ (a std::setprotocol::serviceprotocol::service).
The two containers held overlapping state that had to be kept in
sync across offer_service, stop_offer_service, and reconnect handling.
This PR merges them into a single local_service_table offered_services_,
reducing the complexity of the bookkeeping.
Allow the same service instance to be offered under multiple major
versions by different local applications, and let local clients
consume the specific version they request.
Previously the router stored at most one offer per service instance,
so a second application offering the same instance under a different
major version would be rejected. This change makes the routing state
version-aware:

The local offering table is now keyed by (service, instance, major),
so offers for distinct majors of the same instance coexist.
The internal service map is extended to service → instance → major →
serviceinfo.
Availability, requests and offers are resolved per major version, so
a client only sees the version it requested become available.

The existing recovery mechanisms are preserved and made version-aware:
the pending-offers and pending-requests bookkeeping (used to ping a
still-alive server when a client re-requests a service, or when another
application tries to offer an already-offered service) now tracks the
major version alongside the service instance.
Scope / limitations

Local offering and consuming only; no boardnet (remote) support for
multiple major versions yet.
No support for offering or consuming different versions within the
same application.
Several find_service call sites still resolve with ANY_MAJOR
(marked with TODOs). These sit on the remote/boardnet paths and will
be resolved as part of the boardnet enablement.
Refactor: Struct based IPC for SERVICE commands
Increase TTL offer test big sd msg
fix climate_test
Fix double connect
improve message reception error logs
Synchronize pending_offers and provided_services
Add sender info to error logs
Batch Executions Enhancement
Fix flaky test_boardnet_with_fake_sockets
Refactor: Struct based to single field commands
Consolidate memcheck suppressions
standardize test scripts
Migrate multiple_services command
Optimize restart routing test
remove offer commands
Remove routing_manager_base
Use host-provided version of Boost for network tests
Fix port checks in external_local_* and routing tests
Fix timing issue in suspend_resume_test_service
Fix local routing test with multiple dispatcher threads
Make debounce_filter test slightly more jitter-tolerant
Convert blocking rmc::stop to async continuation approach
Fix potential race in test_connection_restoration
Fix offer stop offer
Turn external_routing_ready_ into a property
Fix potential hang in intial_event tests
add tracking logs
Upgrade compatibility to Boost 1.91
rmc: fix on_message check
Refactor: Struct based to aggregate simple commands
Log file descriptors
Modernize service_instance_t
idc23 cpp compatibility
Fix header_factory_test for multi-dispatch
Fix race condition in client_id_test_service
Add Android NDK r25b portability gate
Fake sockets - Record SOME/IP and SD messages on gate
Add network-tests image pull fallback and seed job
Fix a race in test_boardnet
replace send command
Turn last_session into a property and add mutex
replace the subscribe_answer commands
rmc: drop available_services_history_
Remove several magic sleeps from test cases
Fix race condition in restart_routing_test
Prevent double start of netlink_connector
ucei: reuse receive buffer
Fix race in malicious_data_tests
Enforce single dispatch for big_payload tests
Fix offered_services_info_test
SonarQube Baseline Frequency
use timer utility in rmc
rmi: remove some dead code
Cleanup pending event registration
Fix additional boardnet tests
Introduce test timeout scaling
Try to make debounce_filter_test more robust under load
Remove deprecated tests
Harden debounce_filter_test against timing issues
Refactor: Struct base approach on routing info cmd
Refactor: Struct based approach for register event command
log a warning when no message handler is installed
Drop obsolete hack event promotion plain -> selective
Create regression test for
Change default number of io threads to 1
move consumer eps into rmc
Ignore SQ rules due to clang-r450784d
tests: fix rare application_tests failure
message: minor export cleanup
Replace update security commands
Get rid of virtuals usage to build up a SOMEIP message
Refactor: Struct based to some variable-sized commands
clear service info doesnt remove ports
tests: fix race in udp_connection_refused_recv
replace subscribe command
Retry unreliable suspend trigger in suspend test cases
Fix more flakyness in suspend_resume_test_initial
Drops all VSOMEIP commands former implementation
move event caching to rmc
Reconnect upon receiving new client id
Fix Android build issues
Forward only requested service version
misc: fix a few overflows
IDCEVO event::set_reliability error
Parallelize network tests
Cache Boost for Android in Artifactory
Demote+Rephrase service property mismatch log
refactor the local_offering_table
fix e2e tests
Log buffer on endpoint receive_cbk errors
Nodeset Refactor
Reserve port ranges used in test cases
Service announces availability before all endpoints are up
Logging: improves routing error logging
Set established as false early on disconnect
endpoints: drop unneeded errors
Drop connection on suspicious message
Add handler exception logs
Remove the eventgroupinfo from rmc as provider
simpler get_message_size
tests: fix usei_fixture.corrupted_data timeout
Ignore fully overlaping segments
misc: dead code removal
Change sockets to shared_ptrs
Check eventgroup with multiple events
drop remote response for recycled/released client id
Add Sanitizers/Valgrinds log on build
Decouple consumer vs. provider error handler
fix daemon build
Run the full NDK build in the android r25b job
Merge pending_offers_ + provided_services_ in rmc
enable multiple major version offerings
@duartenfonseca
duartenfonseca merged commit 7875a1c into COVESA:master Aug 14, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants