Skip to content

Commit f49b7f3

Browse files
authored
Integrates datarouter (#178)
* Integrates datarouter - Deploys datarouetr in linux x86_64 and qnx_x86_64 image - Multicast route added to qnx guest in network_setup_dhcp.sh required for capturing DLTs. - dlt_config added for x86_64 and qnx x86_64 targets that includes the vlan_address updated for dlt_receive to capture untagged ethernet frames on tap0 interface * Adds datarouter test_remote_logging integration test - Adds test_remote_logging integration test that verifies remote logging of datarouter and network config. of the linux x86_64 and qnx qemu image by capturing DLT logs on the host.
1 parent 5a72c15 commit f49b7f3

13 files changed

Lines changed: 279 additions & 4 deletions

File tree

.bazelrc

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ build --tool_java_language_version=17
1313
build --java_runtime_version=remotejdk_17
1414
build --tool_java_runtime_version=remotejdk_17
1515

16-
build:_common --@score_baselibs//score/mw/log/flags:KRemote_Logging=False
1716
build:_common --@score_baselibs//score/json:base_library=nlohmann
1817
build:_common --@score_baselibs//score/memory/shared/flags:use_typedshmd=False
1918
build:_common --@score_communication//score/mw/com/flags:tracing_library=stub
@@ -22,6 +21,14 @@ build:_common --host_platform=@score_bazel_platforms//:x86_64-linux-gcc_12.2.0-p
2221
build:_common --extra_toolchains=@score_toolchains_rust//toolchains/ferrocene:ferrocene_x86_64_unknown_linux_gnu
2322
build:_common --extra_toolchains=@score_gcc_x86_64_toolchain//:x86_64-linux-gcc_12.2.0-posix
2423

24+
# Flags needed by datarouter
25+
build:_common --@score_logging//score/datarouter/build_configuration_flags:persistent_logging=False
26+
build:_common --@score_logging//score/datarouter/build_configuration_flags:persistent_config_feature_enabled=False
27+
build:_common --@score_logging//score/datarouter/build_configuration_flags:enable_nonverbose_dlt=False
28+
build:_common --@score_logging//score/datarouter/build_configuration_flags:enable_dynamic_configuration=False
29+
build:_common --@score_logging//score/datarouter/build_configuration_flags:file_transfer=False
30+
build:_common --@score_logging//score/datarouter/build_configuration_flags:use_local_vlan=True
31+
2532
build:qnx-x86_64 --config=_common
2633
build:qnx-x86_64 --noexperimental_merged_skyframe_analysis_execution
2734
build:qnx-x86_64 --action_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1

feature_integration_tests/configs/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
# *******************************************************************************
1313
exports_files(
1414
[
15+
"dlt_config_qnx_x86_64.json",
16+
"dlt_config_x86_64.json",
1517
"qemu_bridge_config.json",
1618
],
1719
)
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# *******************************************************************************
2+
# Copyright (c) 2026 Contributors to the Eclipse Foundation
3+
#
4+
# See the NOTICE file(s) distributed with this work for additional
5+
# information regarding copyright ownership.
6+
#
7+
# This program and the accompanying materials are made available under the
8+
# terms of the Apache License Version 2.0 which is available at
9+
# https://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# SPDX-License-Identifier: Apache-2.0
12+
# *******************************************************************************
13+
14+
exports_files([
15+
"etc/logging.json",
16+
"etc/log-channels.json",
17+
])
18+
19+
filegroup(
20+
name = "etc_configs",
21+
srcs = [
22+
"etc/log-channels.json",
23+
"etc/logging.json",
24+
],
25+
visibility = ["//visibility:public"],
26+
)
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
{
2+
"channels": {
3+
"3491": {
4+
"address": "0.0.0.0",
5+
"channelThreshold": "kError",
6+
"dstAddress": "239.255.42.99",
7+
"dstPort": 3490,
8+
"ecu": "SCPP",
9+
"port": 3491
10+
},
11+
"3492": {
12+
"address": "0.0.0.0",
13+
"channelThreshold": "kInfo",
14+
"dstAddress": "239.255.42.99",
15+
"dstPort": 3490,
16+
"ecu": "SCPP",
17+
"port": 3492
18+
},
19+
"3493": {
20+
"address": "0.0.0.0",
21+
"channelThreshold": "kVerbose",
22+
"dstAddress": "239.255.42.99",
23+
"dstPort": 3490,
24+
"ecu": "SCPP",
25+
"port": 3493
26+
}
27+
},
28+
"channelAssignments": {
29+
"DR": {
30+
"": [
31+
"3492"
32+
],
33+
"CTX1": [
34+
"3492",
35+
"3493"
36+
],
37+
"STAT": [
38+
"3492"
39+
]
40+
},
41+
"-NI-": {
42+
"": [
43+
"3491"
44+
]
45+
}
46+
},
47+
"defaultChannel": "3493",
48+
"defaultThresold": "kVerbose",
49+
"messageThresholds": {
50+
"": {
51+
"": "kInfo"
52+
},
53+
"DR": {
54+
"": "kVerbose",
55+
"CTX1": "kVerbose",
56+
"STAT": "kDebug"
57+
},
58+
"-NI-": {
59+
"": "kVerbose"
60+
}
61+
}
62+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"appId": "DR",
3+
"appDesc": "Data Router",
4+
"logLevel": "kInfo",
5+
"logMode": "kRemote",
6+
"ringBufferSize": 786432,
7+
"numberOfSlots": 4,
8+
"slotSizeBytes": 4096,
9+
"datarouterUid": 1051
10+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"host_ip": "169.254.21.88",
3+
"target_ip": "169.254.21.88",
4+
"multicast_ips": [
5+
"239.255.42.99"
6+
]
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"host_ip": "172.17.0.1",
3+
"target_ip": "172.17.0.1",
4+
"multicast_ips": [
5+
"239.255.42.99"
6+
]
7+
}

feature_integration_tests/itf/BUILD

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@
1111
# SPDX-License-Identifier: Apache-2.0
1212
# *******************************************************************************
1313
load("@score_itf//:defs.bzl", "py_itf_test")
14-
load("@score_itf//score/itf/plugins:plugins.bzl", "docker", "qemu")
14+
load("@score_itf//score/itf/plugins:plugins.bzl", "dlt", "docker", "qemu")
1515

1616
filegroup(
1717
name = "all_tests",
1818
srcs = [
19+
"test_remote_logging.py",
1920
"test_showcases.py",
2021
"test_ssh.py",
2122
],
@@ -27,13 +28,16 @@ py_itf_test(
2728
":all_tests",
2829
],
2930
args = [
31+
"--dlt-config=$(location //feature_integration_tests/configs:dlt_config_x86_64.json)",
3032
"--docker-image-bootstrap=$(location //images/linux_x86_64:image_tarball)",
3133
"--docker-image=score_showcases:latest",
3234
],
3335
data = [
36+
"//feature_integration_tests/configs:dlt_config_x86_64.json",
3437
"//images/linux_x86_64:image_tarball",
3538
],
3639
plugins = [
40+
dlt,
3741
docker,
3842
],
3943
tags = [
@@ -47,14 +51,17 @@ py_itf_test(
4751
":all_tests",
4852
],
4953
args = [
54+
"--dlt-config=$(location //feature_integration_tests/configs:dlt_config_qnx_x86_64.json)",
5055
"--qemu-config=$(location //feature_integration_tests/configs:qemu_bridge_config.json)",
5156
"--qemu-image=$(location //images/qnx_x86_64:image)",
5257
],
5358
data = [
59+
"//feature_integration_tests/configs:dlt_config_qnx_x86_64.json",
5460
"//feature_integration_tests/configs:qemu_bridge_config.json",
5561
"//images/qnx_x86_64:image",
5662
],
5763
plugins = [
64+
dlt,
5865
qemu,
5966
],
6067
tags = [
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# *******************************************************************************
2+
# Copyright (c) 2026 Contributors to the Eclipse Foundation
3+
#
4+
# See the NOTICE file(s) distributed with this work for additional
5+
# information regarding copyright ownership.
6+
#
7+
# This program and the accompanying materials are made available under the
8+
# terms of the Apache License Version 2.0 which is available at
9+
# https://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# SPDX-License-Identifier: Apache-2.0
12+
# *******************************************************************************
13+
14+
import logging
15+
import os
16+
import time
17+
18+
import pytest
19+
20+
from score.itf.plugins.dlt.dlt_receive import Protocol
21+
from score.itf.plugins.dlt.dlt_window import DltWindow
22+
23+
logger = logging.getLogger(__name__)
24+
25+
26+
# Datarouter messages with Context ID "STAT" sent every ~5s hence 10s to reliably capture and verify
27+
CAPTURE_DURATION_SECONDS = 10
28+
29+
# DLT message identifiers for datarouter statistics
30+
APP_ID = "DR"
31+
CTX_ID = "STAT"
32+
33+
_QNX_DATAROUTER_CHECK_CMD = "/proc/boot/pidin | /proc/boot/grep datarouter"
34+
_LINUX_DATAROUTER_CHECK_CMD = "ps -ef | grep datarouter | grep -v grep"
35+
36+
# pathspace ability provides the datarouter access to the `procnto` pathname prefix space
37+
# required for mw/com message passing with mw::log frontend
38+
_QNX_DATAROUTER_START_CMD = (
39+
"cd /usr/bin/datarouter && nohup on -A nonroot,allow,pathspace -u 1051:1091 "
40+
"./datarouter --no_adaptive_runtime > /dev/null 2>&1 &"
41+
)
42+
_LINUX_DATAROUTER_START_CMD = "cd /usr/bin/datarouter && nohup ./datarouter --no_adaptive_runtime > /dev/null 2>&1 &"
43+
# Multicast route directs all multicast traffic (224.0.0.0/4) out of the containers
44+
# network interface required for DLT messages to reach the host via the Docker bridge.
45+
_LINUX_CHECK_MULTICAST_ROUTE_CMD = "ip route add 224.0.0.0/4 dev eth0 2>/dev/null || true"
46+
_DATAROUTER_STARTUP_TIMEOUT_SEC = 2
47+
48+
49+
def _is_qnx(target):
50+
_, out = target.execute("uname -s")
51+
return b"QNX" in out
52+
53+
54+
@pytest.fixture
55+
def datarouter_running(target):
56+
is_qnx = _is_qnx(target)
57+
58+
if is_qnx:
59+
check_cmd = _QNX_DATAROUTER_CHECK_CMD
60+
start_cmd = _QNX_DATAROUTER_START_CMD
61+
else:
62+
check_cmd = _LINUX_DATAROUTER_CHECK_CMD
63+
start_cmd = _LINUX_DATAROUTER_START_CMD
64+
target.execute(_LINUX_CHECK_MULTICAST_ROUTE_CMD)
65+
66+
exit_code, out = target.execute(check_cmd)
67+
output = out.decode(errors="replace")
68+
69+
if "datarouter" not in output:
70+
exit_code, _ = target.execute("test -x /usr/bin/datarouter")
71+
if exit_code != 0:
72+
pytest.fail("Datarouter binary not found at /usr/bin/datarouter on target")
73+
74+
logger.info("Datarouter not running. Starting Datarouter..")
75+
exit_code, out = target.execute(start_cmd)
76+
logger.debug("Start command exit_code=%s", exit_code)
77+
time.sleep(_DATAROUTER_STARTUP_TIMEOUT_SEC)
78+
79+
_, out = target.execute(check_cmd)
80+
if "datarouter" not in out.decode(errors="replace"):
81+
pytest.fail("Failed to start datarouter on target")
82+
logger.info("Datarouter started successfully..")
83+
else:
84+
logger.info("Datarouter already running!")
85+
yield
86+
87+
88+
def test_remote_logging(datarouter_running, dlt_config):
89+
"""Verifies remote logging of Dataraouter
90+
91+
Starts Datarouter on the target if not already running, then
92+
the dlt_receive captures DLT messages on the test host
93+
on the multicast group for a fixed duration and checks for
94+
expected 'STAT' log messages in the captured DTL logs.
95+
"""
96+
with DltWindow(
97+
protocol=Protocol.UDP,
98+
host_ip=dlt_config.host_ip,
99+
multicast_ips=dlt_config.multicast_ips,
100+
print_to_stdout=True,
101+
binary_path=dlt_config.dlt_receive_path,
102+
) as window:
103+
time.sleep(CAPTURE_DURATION_SECONDS)
104+
105+
record = window.record(filters=[(APP_ID, CTX_ID)])
106+
messages = record.find(query=dict(apid=APP_ID, ctid=CTX_ID))
107+
message_count = len(messages)
108+
109+
logger.debug("Found %d messages with app_id: %s, context_id: %s", message_count, APP_ID, CTX_ID)
110+
111+
assert message_count > 1, (
112+
f"Expected atleast one DLT message with app_id: {APP_ID} and context_id: {CTX_ID}, but got {message_count}"
113+
)

images/linux_x86_64/BUILD

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,30 @@ sh_binary(
2828
},
2929
)
3030

31+
pkg_tar(
32+
name = "datarouter_bin_tar",
33+
srcs = ["@score_logging//score/datarouter"],
34+
mode = "0755",
35+
package_dir = "/usr/bin/datarouter",
36+
)
37+
38+
pkg_tar(
39+
name = "datarouter_etc_tar",
40+
srcs = [
41+
"//feature_integration_tests/configs/datarouter:etc/log-channels.json",
42+
"//feature_integration_tests/configs/datarouter:etc/logging.json",
43+
],
44+
mode = "0644",
45+
package_dir = "/usr/bin/datarouter/etc",
46+
)
47+
3148
oci_image(
3249
name = "image",
3350
base = "@ubuntu_22_04",
3451
tars = [
3552
"//showcases:showcases_pkg_tar",
53+
":datarouter_bin_tar",
54+
":datarouter_etc_tar",
3655
],
3756
)
3857

0 commit comments

Comments
 (0)