jolly has uploaded this change for review.

View Change

Add test case to verify proper DSCP settings

Related: SYS#8071
Change-Id: I6ac965998433b4d8213cce30fc3fcf8fe485a092
---
M .gitignore
M configure.ac
M tests/Makefile.am
A tests/dscp/Makefile.am
A tests/dscp/dscp_test.ok
A tests/dscp/dscp_test.py
A tests/dscp/get_tos_diag.c
A tests/dscp/osmo-stp-dscp.cfg
M tests/testsuite.at
9 files changed, 248 insertions(+), 1 deletion(-)

git pull ssh://gerrit.osmocom.org:29418/libosmo-sigtran refs/changes/09/42809/1
diff --git a/.gitignore b/.gitignore
index 99cb052..8988066 100644
--- a/.gitignore
+++ b/.gitignore
@@ -55,6 +55,7 @@
tests/db/db_test
tests/debug/debug_test
tests/*/*_test
+tests/dscp/get_tos_diag

tests/atconfig
tests/package.m4
diff --git a/configure.ac b/configure.ac
index f1e1888..0bbc233 100644
--- a/configure.ac
+++ b/configure.ac
@@ -209,6 +209,7 @@
tests/ss7/Makefile
tests/tcap/Makefile
tests/vty/Makefile
+ tests/dscp/Makefile
examples/Makefile
stp/Makefile
doc/Makefile
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 7927bbd..5e056d4 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = xua m2ua ss7 vty
+SUBDIRS = xua m2ua ss7 vty dscp

if BUILD_WITH_TCAP_LOADSHARING
SUBDIRS += tcap
diff --git a/tests/dscp/Makefile.am b/tests/dscp/Makefile.am
new file mode 100644
index 0000000..43b1fcd
--- /dev/null
+++ b/tests/dscp/Makefile.am
@@ -0,0 +1,18 @@
+AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include
+AM_CFLAGS=-Wall $(LIBOSMONETIF_CFLAGS) $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS)
+
+AM_LDFLAGS = -no-install
+LDADD = $(top_builddir)/src/.libs/libosmo-sigtran.a \
+ $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMONETIF_LIBS) $(LIBSCTP_LIBS)
+
+if BUILD_WITH_TCAP_LOADSHARING
+LDADD += $(LIBOSMOASN1TCAP_LIBS)
+endif
+
+EXTRA_DIST = dscp_test.ok dscp_test.py
+
+check_PROGRAMS = get_tos_diag
+
+get_tos_diag_SOURCES = get_tos_diag.c
+
+
diff --git a/tests/dscp/dscp_test.ok b/tests/dscp/dscp_test.ok
new file mode 100644
index 0000000..66c7bc4
--- /dev/null
+++ b/tests/dscp/dscp_test.ok
@@ -0,0 +1,9 @@
+starting osmo-stp
+started osmo-stp
+LISTEN 127.0.0.1:2905 0.0.0.0:0 23
+ESTAB 127.0.0.1:2905 127.0.0.2:2906 23
+OTHER 127.0.0.1:2905 127.0.0.2:2906 23
+ESTAB 127.0.0.2:2906 127.0.0.1:2905 42
+OTHER 127.0.0.2:2906 127.0.0.1:2905 42
+stopping osmo-stp
+stopped osmo-stp
diff --git a/tests/dscp/dscp_test.py b/tests/dscp/dscp_test.py
new file mode 100755
index 0000000..0122257
--- /dev/null
+++ b/tests/dscp/dscp_test.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python3
+
+# (C) 2026 by sysmocom s.f.m.c. GmbH
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import subprocess
+import time
+import os
+import sys
+from pathlib import Path
+
+# Pfade definieren
+SCRIPT_DIR = Path(__file__).parent.resolve()
+STP_BINARY = SCRIPT_DIR / ".." / ".." / "stp" / "osmo-stp"
+CONFIG_FILE = SCRIPT_DIR / "osmo-stp-dscp.cfg"
+DIAG_BINARY = SCRIPT_DIR / "get_tos_diag"
+
+
+def main():
+ print(f"starting osmo-stp")
+
+ # 1. osmo-stp im Hintergrund starten
+ try:
+ proc = subprocess.Popen(
+ [STP_BINARY, "-c", CONFIG_FILE],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ text=True
+ )
+ except FileNotFoundError:
+ print("File not found")
+ sys.exit(1)
+
+ # wait to establish socket connection
+ time.sleep(1.0)
+
+ # check process
+ if proc.poll() is not None:
+ print("Process failed")
+ stdout, stderr = proc.communicate()
+ print(f"STDOUT:\n{stdout}\nSTDERR:\n{stderr}", file=sys.stderr)
+ sys.exit(1)
+
+ print("started osmo-stp")
+
+ subprocess.run([DIAG_BINARY], check=True)
+
+ print("stopping osmo-stp")
+ proc.terminate()
+
+ try:
+ proc.wait(timeout=5)
+ print("stopped osmo-stp")
+ except subprocess.TimeoutExpired:
+ print("failed to stop, killing...")
+ proc.kill()
+
+if __name__ == "__main__":
+ main()
diff --git a/tests/dscp/get_tos_diag.c b/tests/dscp/get_tos_diag.c
new file mode 100644
index 0000000..d7bb2d8
--- /dev/null
+++ b/tests/dscp/get_tos_diag.c
@@ -0,0 +1,120 @@
+/*
+ * (C) 2026 by sysmocom s.f.m.c. GmbH
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <asm/types.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <linux/sock_diag.h>
+#include <linux/inet_diag.h>
+#include <arpa/inet.h>
+#include <netinet/tcp.h>
+
+#define BUFFER_SIZE 8192
+
+int main()
+{
+ int nl_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG);
+ if (nl_fd < 0) {
+ perror("Failed to open netlink socket.");
+ return 1;
+ }
+
+ struct {
+ struct nlmsghdr nlh;
+ struct inet_diag_req_v2 req;
+ } req;
+
+ memset(&req, 0, sizeof(req));
+ req.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct inet_diag_req_v2));
+ req.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
+ req.nlh.nlmsg_type = SOCK_DIAG_BY_FAMILY;
+
+ req.req.sdiag_family = AF_INET;
+ req.req.sdiag_protocol = IPPROTO_SCTP;
+ req.req.idiag_states = 0xFFFFFFFF;
+
+ req.req.idiag_ext = (1 << (INET_DIAG_TOS - 1));
+
+ if (send(nl_fd, &req, req.nlh.nlmsg_len, 0) < 0) {
+ perror("Failed to sent netlink request.");
+ close(nl_fd);
+ return 1;
+ }
+
+ char buffer[BUFFER_SIZE];
+
+ while (1) {
+ ssize_t num_bytes = recv(nl_fd, buffer, sizeof(buffer), 0);
+ if (num_bytes < 0) {
+ perror("Failed to receive netlink response.");
+ break;
+ }
+
+ struct nlmsghdr *nlh = (struct nlmsghdr *)buffer;
+ while (NLMSG_OK(nlh, num_bytes)) {
+ if (nlh->nlmsg_type == NLMSG_DONE) {
+ close(nl_fd);
+ return 0;
+ }
+ if (nlh->nlmsg_type == NLMSG_ERROR) {
+ perror("Netlink error received.");
+ close(nl_fd);
+ return 1;
+ }
+
+ struct inet_diag_msg *diag_msg = NLMSG_DATA(nlh);
+
+ char src_ip[INET_ADDRSTRLEN], dst_ip[INET_ADDRSTRLEN];
+ inet_ntop(AF_INET, &diag_msg->id.idiag_src, src_ip, sizeof(src_ip));
+ inet_ntop(AF_INET, &diag_msg->id.idiag_dst, dst_ip, sizeof(dst_ip));
+
+ uint16_t src_port = ntohs(diag_msg->id.idiag_sport);
+ uint16_t dst_port = ntohs(diag_msg->id.idiag_dport);
+
+ char src_addr[32], dst_addr[32];
+ snprintf(src_addr, sizeof(src_addr), "%s:%d", src_ip, src_port);
+ snprintf(dst_addr, sizeof(dst_addr), "%s:%d", dst_ip, dst_port);
+
+ const char *state_str = (diag_msg->idiag_state == TCP_ESTABLISHED) ? "ESTAB" :
+ (diag_msg->idiag_state == TCP_LISTEN) ? "LISTEN" : "OTHER";
+
+ uint8_t tos = 0;
+
+ int rta_len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(struct inet_diag_msg));
+ struct rtattr *attr = (struct rtattr *)(diag_msg + 1);
+
+ while (RTA_OK(attr, rta_len)) {
+ if (attr->rta_type == INET_DIAG_TOS) {
+ tos = *(uint8_t *)RTA_DATA(attr);
+ break;
+ }
+ attr = RTA_NEXT(attr, rta_len);
+ }
+
+ /* state local remote dscp */
+ printf("%s %s %s %d\n", state_str, src_addr, dst_addr, tos>>2);
+ nlh = NLMSG_NEXT(nlh, num_bytes);
+ }
+ }
+
+ close(nl_fd);
+ return 0;
+}
diff --git a/tests/dscp/osmo-stp-dscp.cfg b/tests/dscp/osmo-stp-dscp.cfg
new file mode 100644
index 0000000..74f85ef
--- /dev/null
+++ b/tests/dscp/osmo-stp-dscp.cfg
@@ -0,0 +1,22 @@
+log stderr
+ logging filter all 1
+ logging color 1
+ logging print category 1
+ logging timestamp 0
+ logging level set-all notice
+line vty
+ no login
+!
+cs7 instance 0
+ xua rkm routing-key-allocation dynamic-permitted
+ listen m3ua 2905
+ accept-asp-connections dynamic-permitted
+ local-ip 127.0.0.1
+ ip-dscp 23
+ asp asp-clnt-m3ua 2905 2906 m3ua
+ local-ip 127.0.0.2
+ remote-ip 127.0.0.1
+ ip-dscp 42
+ role asp
+ sctp-role client
+ no shutdown
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 910fc0b..7812c93 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -26,3 +26,9 @@
cat $abs_srcdir/tcap/tcap_transaction_tracking_test.ok > expout
AT_CHECK([$abs_top_builddir/tests/tcap/tcap_transaction_tracking_test], [], [expout], [ignore])
AT_CLEANUP
+
+AT_SETUP([dscp])
+AT_KEYWORDS([dscp])
+cat $abs_srcdir/dscp/dscp_test.ok > expout
+AT_CHECK([python3 -u $abs_top_builddir/tests/dscp/dscp_test.py], [], [expout], [ignore])
+AT_CLEANUP

To view, visit change 42809. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-MessageType: newchange
Gerrit-Project: libosmo-sigtran
Gerrit-Branch: master
Gerrit-Change-Id: I6ac965998433b4d8213cce30fc3fcf8fe485a092
Gerrit-Change-Number: 42809
Gerrit-PatchSet: 1
Gerrit-Owner: jolly <andreas@eversberg.eu>