aboutsummaryrefslogtreecommitdiffstats
path: root/tools/testing/selftests/networking
diff options
context:
space:
mode:
authorJian Yang <jianyang@google.com>2020-03-25 13:32:07 -0700
committerDavid S. Miller <davem@davemloft.net>2020-03-29 21:48:30 -0700
commit5ef5c90e3cb3ae1ce7bebddaeb8e8f44309950f7 (patch)
treed025c25e717a13808070791ccf8110c645c4b4a6 /tools/testing/selftests/networking
parentARM: dts: apalis-imx6qdl: use rgmii-id instead of rgmii (diff)
downloadlinux-dev-5ef5c90e3cb3ae1ce7bebddaeb8e8f44309950f7.tar.xz
linux-dev-5ef5c90e3cb3ae1ce7bebddaeb8e8f44309950f7.zip
selftests: move timestamping selftests to net folder
For historical reasons, there are several timestamping selftest targets in selftests/networking/timestamping. Move them to the standard directory for networking tests: selftests/net. Signed-off-by: Jian Yang <jianyang@google.com> Acked-by: Willem de Bruijn <willemb@google.com> Acked-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'tools/testing/selftests/networking')
-rw-r--r--tools/testing/selftests/networking/timestamping/.gitignore4
-rw-r--r--tools/testing/selftests/networking/timestamping/Makefile11
-rw-r--r--tools/testing/selftests/networking/timestamping/config2
-rw-r--r--tools/testing/selftests/networking/timestamping/hwtstamp_config.c135
-rw-r--r--tools/testing/selftests/networking/timestamping/rxtimestamp.c390
-rw-r--r--tools/testing/selftests/networking/timestamping/timestamping.c509
-rw-r--r--tools/testing/selftests/networking/timestamping/txtimestamp.c916
-rwxr-xr-xtools/testing/selftests/networking/timestamping/txtimestamp.sh82
8 files changed, 0 insertions, 2049 deletions
diff --git a/tools/testing/selftests/networking/timestamping/.gitignore b/tools/testing/selftests/networking/timestamping/.gitignore
deleted file mode 100644
index d9355035e746..000000000000
--- a/tools/testing/selftests/networking/timestamping/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-timestamping
-rxtimestamp
-txtimestamp
-hwtstamp_config
diff --git a/tools/testing/selftests/networking/timestamping/Makefile b/tools/testing/selftests/networking/timestamping/Makefile
deleted file mode 100644
index 1de8bd8ccf5d..000000000000
--- a/tools/testing/selftests/networking/timestamping/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-CFLAGS += -I../../../../../usr/include
-
-TEST_GEN_FILES := hwtstamp_config rxtimestamp timestamping txtimestamp
-TEST_PROGS := txtimestamp.sh
-
-all: $(TEST_PROGS)
-
-top_srcdir = ../../../../..
-KSFT_KHDR_INSTALL := 1
-include ../../lib.mk
diff --git a/tools/testing/selftests/networking/timestamping/config b/tools/testing/selftests/networking/timestamping/config
deleted file mode 100644
index a13e3169b0a4..000000000000
--- a/tools/testing/selftests/networking/timestamping/config
+++ /dev/null
@@ -1,2 +0,0 @@
-CONFIG_IFB=y
-CONFIG_NET_SCH_NETEM=y
diff --git a/tools/testing/selftests/networking/timestamping/hwtstamp_config.c b/tools/testing/selftests/networking/timestamping/hwtstamp_config.c
deleted file mode 100644
index e1fdee841021..000000000000
--- a/tools/testing/selftests/networking/timestamping/hwtstamp_config.c
+++ /dev/null
@@ -1,135 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Test program for SIOC{G,S}HWTSTAMP
- * Copyright 2013 Solarflare Communications
- * Author: Ben Hutchings
- */
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-
-#include <linux/if.h>
-#include <linux/net_tstamp.h>
-#include <linux/sockios.h>
-
-static int
-lookup_value(const char **names, int size, const char *name)
-{
- int value;
-
- for (value = 0; value < size; value++)
- if (names[value] && strcasecmp(names[value], name) == 0)
- return value;
-
- return -1;
-}
-
-static const char *
-lookup_name(const char **names, int size, int value)
-{
- return (value >= 0 && value < size) ? names[value] : NULL;
-}
-
-static void list_names(FILE *f, const char **names, int size)
-{
- int value;
-
- for (value = 0; value < size; value++)
- if (names[value])
- fprintf(f, " %s\n", names[value]);
-}
-
-static const char *tx_types[] = {
-#define TX_TYPE(name) [HWTSTAMP_TX_ ## name] = #name
- TX_TYPE(OFF),
- TX_TYPE(ON),
- TX_TYPE(ONESTEP_SYNC)
-#undef TX_TYPE
-};
-#define N_TX_TYPES ((int)(sizeof(tx_types) / sizeof(tx_types[0])))
-
-static const char *rx_filters[] = {
-#define RX_FILTER(name) [HWTSTAMP_FILTER_ ## name] = #name
- RX_FILTER(NONE),
- RX_FILTER(ALL),
- RX_FILTER(SOME),
- RX_FILTER(PTP_V1_L4_EVENT),
- RX_FILTER(PTP_V1_L4_SYNC),
- RX_FILTER(PTP_V1_L4_DELAY_REQ),
- RX_FILTER(PTP_V2_L4_EVENT),
- RX_FILTER(PTP_V2_L4_SYNC),
- RX_FILTER(PTP_V2_L4_DELAY_REQ),
- RX_FILTER(PTP_V2_L2_EVENT),
- RX_FILTER(PTP_V2_L2_SYNC),
- RX_FILTER(PTP_V2_L2_DELAY_REQ),
- RX_FILTER(PTP_V2_EVENT),
- RX_FILTER(PTP_V2_SYNC),
- RX_FILTER(PTP_V2_DELAY_REQ),
-#undef RX_FILTER
-};
-#define N_RX_FILTERS ((int)(sizeof(rx_filters) / sizeof(rx_filters[0])))
-
-static void usage(void)
-{
- fputs("Usage: hwtstamp_config if_name [tx_type rx_filter]\n"
- "tx_type is any of (case-insensitive):\n",
- stderr);
- list_names(stderr, tx_types, N_TX_TYPES);
- fputs("rx_filter is any of (case-insensitive):\n", stderr);
- list_names(stderr, rx_filters, N_RX_FILTERS);
-}
-
-int main(int argc, char **argv)
-{
- struct ifreq ifr;
- struct hwtstamp_config config;
- const char *name;
- int sock;
-
- if ((argc != 2 && argc != 4) || (strlen(argv[1]) >= IFNAMSIZ)) {
- usage();
- return 2;
- }
-
- if (argc == 4) {
- config.flags = 0;
- config.tx_type = lookup_value(tx_types, N_TX_TYPES, argv[2]);
- config.rx_filter = lookup_value(rx_filters, N_RX_FILTERS, argv[3]);
- if (config.tx_type < 0 || config.rx_filter < 0) {
- usage();
- return 2;
- }
- }
-
- sock = socket(AF_INET, SOCK_DGRAM, 0);
- if (sock < 0) {
- perror("socket");
- return 1;
- }
-
- strcpy(ifr.ifr_name, argv[1]);
- ifr.ifr_data = (caddr_t)&config;
-
- if (ioctl(sock, (argc == 2) ? SIOCGHWTSTAMP : SIOCSHWTSTAMP, &ifr)) {
- perror("ioctl");
- return 1;
- }
-
- printf("flags = %#x\n", config.flags);
- name = lookup_name(tx_types, N_TX_TYPES, config.tx_type);
- if (name)
- printf("tx_type = %s\n", name);
- else
- printf("tx_type = %d\n", config.tx_type);
- name = lookup_name(rx_filters, N_RX_FILTERS, config.rx_filter);
- if (name)
- printf("rx_filter = %s\n", name);
- else
- printf("rx_filter = %d\n", config.rx_filter);
-
- return 0;
-}
diff --git a/tools/testing/selftests/networking/timestamping/rxtimestamp.c b/tools/testing/selftests/networking/timestamping/rxtimestamp.c
deleted file mode 100644
index 6dee9e636a95..000000000000
--- a/tools/testing/selftests/networking/timestamping/rxtimestamp.c
+++ /dev/null
@@ -1,390 +0,0 @@
-#include <errno.h>
-#include <error.h>
-#include <getopt.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <sys/select.h>
-#include <sys/ioctl.h>
-#include <arpa/inet.h>
-#include <net/if.h>
-
-#include <asm/types.h>
-#include <linux/net_tstamp.h>
-#include <linux/errqueue.h>
-
-#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
-
-struct options {
- int so_timestamp;
- int so_timestampns;
- int so_timestamping;
-};
-
-struct tstamps {
- bool tstamp;
- bool tstampns;
- bool swtstamp;
- bool hwtstamp;
-};
-
-struct socket_type {
- char *friendly_name;
- int type;
- int protocol;
- bool enabled;
-};
-
-struct test_case {
- struct options sockopt;
- struct tstamps expected;
- bool enabled;
-};
-
-struct sof_flag {
- int mask;
- char *name;
-};
-
-static struct sof_flag sof_flags[] = {
-#define SOF_FLAG(f) { f, #f }
- SOF_FLAG(SOF_TIMESTAMPING_SOFTWARE),
- SOF_FLAG(SOF_TIMESTAMPING_RX_SOFTWARE),
- SOF_FLAG(SOF_TIMESTAMPING_RX_HARDWARE),
-};
-
-static struct socket_type socket_types[] = {
- { "ip", SOCK_RAW, IPPROTO_EGP },
- { "udp", SOCK_DGRAM, IPPROTO_UDP },
- { "tcp", SOCK_STREAM, IPPROTO_TCP },
-};
-
-static struct test_case test_cases[] = {
- { {}, {} },
- {
- { so_timestamp: 1 },
- { tstamp: true }
- },
- {
- { so_timestampns: 1 },
- { tstampns: true }
- },
- {
- { so_timestamp: 1, so_timestampns: 1 },
- { tstampns: true }
- },
- {
- { so_timestamping: SOF_TIMESTAMPING_RX_SOFTWARE },
- {}
- },
- {
- /* Loopback device does not support hw timestamps. */
- { so_timestamping: SOF_TIMESTAMPING_RX_HARDWARE },
- {}
- },
- {
- { so_timestamping: SOF_TIMESTAMPING_SOFTWARE },
- {}
- },
- {
- { so_timestamping: SOF_TIMESTAMPING_RX_SOFTWARE
- | SOF_TIMESTAMPING_RX_HARDWARE },
- {}
- },
- {
- { so_timestamping: SOF_TIMESTAMPING_SOFTWARE
- | SOF_TIMESTAMPING_RX_SOFTWARE },
- { swtstamp: true }
- },
- {
- { so_timestamp: 1, so_timestamping: SOF_TIMESTAMPING_SOFTWARE
- | SOF_TIMESTAMPING_RX_SOFTWARE },
- { tstamp: true, swtstamp: true }
- },
-};
-
-static struct option long_options[] = {
- { "list_tests", no_argument, 0, 'l' },
- { "test_num", required_argument, 0, 'n' },
- { "op_size", required_argument, 0, 's' },
- { "tcp", no_argument, 0, 't' },
- { "udp", no_argument, 0, 'u' },
- { "ip", no_argument, 0, 'i' },
-};
-
-static int next_port = 19999;
-static int op_size = 10 * 1024;
-
-void print_test_case(struct test_case *t)
-{
- int f = 0;
-
- printf("sockopts {");
- if (t->sockopt.so_timestamp)
- printf(" SO_TIMESTAMP ");
- if (t->sockopt.so_timestampns)
- printf(" SO_TIMESTAMPNS ");
- if (t->sockopt.so_timestamping) {
- printf(" SO_TIMESTAMPING: {");
- for (f = 0; f < ARRAY_SIZE(sof_flags); f++)
- if (t->sockopt.so_timestamping & sof_flags[f].mask)
- printf(" %s |", sof_flags[f].name);
- printf("}");
- }
- printf("} expected cmsgs: {");
- if (t->expected.tstamp)
- printf(" SCM_TIMESTAMP ");
- if (t->expected.tstampns)
- printf(" SCM_TIMESTAMPNS ");
- if (t->expected.swtstamp || t->expected.hwtstamp) {
- printf(" SCM_TIMESTAMPING {");
- if (t->expected.swtstamp)
- printf("0");
- if (t->expected.swtstamp && t->expected.hwtstamp)
- printf(",");
- if (t->expected.hwtstamp)
- printf("2");
- printf("}");
- }
- printf("}\n");
-}
-
-void do_send(int src)
-{
- int r;
- char *buf = malloc(op_size);
-
- memset(buf, 'z', op_size);
- r = write(src, buf, op_size);
- if (r < 0)
- error(1, errno, "Failed to sendmsg");
-
- free(buf);
-}
-
-bool do_recv(int rcv, int read_size, struct tstamps expected)
-{
- const int CMSG_SIZE = 1024;
-
- struct scm_timestamping *ts;
- struct tstamps actual = {};
- char cmsg_buf[CMSG_SIZE];
- struct iovec recv_iov;
- struct cmsghdr *cmsg;
- bool failed = false;
- struct msghdr hdr;
- int flags = 0;
- int r;
-
- memset(&hdr, 0, sizeof(hdr));
- hdr.msg_iov = &recv_iov;
- hdr.msg_iovlen = 1;
- recv_iov.iov_base = malloc(read_size);
- recv_iov.iov_len = read_size;
-
- hdr.msg_control = cmsg_buf;
- hdr.msg_controllen = sizeof(cmsg_buf);
-
- r = recvmsg(rcv, &hdr, flags);
- if (r < 0)
- error(1, errno, "Failed to recvmsg");
- if (r != read_size)
- error(1, 0, "Only received %d bytes of payload.", r);
-
- if (hdr.msg_flags & (MSG_TRUNC | MSG_CTRUNC))
- error(1, 0, "Message was truncated.");
-
- for (cmsg = CMSG_FIRSTHDR(&hdr); cmsg != NULL;
- cmsg = CMSG_NXTHDR(&hdr, cmsg)) {
- if (cmsg->cmsg_level != SOL_SOCKET)
- error(1, 0, "Unexpected cmsg_level %d",
- cmsg->cmsg_level);
- switch (cmsg->cmsg_type) {
- case SCM_TIMESTAMP:
- actual.tstamp = true;
- break;
- case SCM_TIMESTAMPNS:
- actual.tstampns = true;
- break;
- case SCM_TIMESTAMPING:
- ts = (struct scm_timestamping *)CMSG_DATA(cmsg);
- actual.swtstamp = !!ts->ts[0].tv_sec;
- if (ts->ts[1].tv_sec != 0)
- error(0, 0, "ts[1] should not be set.");
- actual.hwtstamp = !!ts->ts[2].tv_sec;
- break;
- default:
- error(1, 0, "Unexpected cmsg_type %d", cmsg->cmsg_type);
- }
- }
-
-#define VALIDATE(field) \
- do { \
- if (expected.field != actual.field) { \
- if (expected.field) \
- error(0, 0, "Expected " #field " to be set."); \
- else \
- error(0, 0, \
- "Expected " #field " to not be set."); \
- failed = true; \
- } \
- } while (0)
-
- VALIDATE(tstamp);
- VALIDATE(tstampns);
- VALIDATE(swtstamp);
- VALIDATE(hwtstamp);
-#undef VALIDATE
-
- free(recv_iov.iov_base);
-
- return failed;
-}
-
-void config_so_flags(int rcv, struct options o)
-{
- int on = 1;
-
- if (setsockopt(rcv, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
- error(1, errno, "Failed to enable SO_REUSEADDR");
-
- if (o.so_timestamp &&
- setsockopt(rcv, SOL_SOCKET, SO_TIMESTAMP,
- &o.so_timestamp, sizeof(o.so_timestamp)) < 0)
- error(1, errno, "Failed to enable SO_TIMESTAMP");
-
- if (o.so_timestampns &&
- setsockopt(rcv, SOL_SOCKET, SO_TIMESTAMPNS,
- &o.so_timestampns, sizeof(o.so_timestampns)) < 0)
- error(1, errno, "Failed to enable SO_TIMESTAMPNS");
-
- if (o.so_timestamping &&
- setsockopt(rcv, SOL_SOCKET, SO_TIMESTAMPING,
- &o.so_timestamping, sizeof(o.so_timestamping)) < 0)
- error(1, errno, "Failed to set SO_TIMESTAMPING");
-}
-
-bool run_test_case(struct socket_type s, struct test_case t)
-{
- int port = (s.type == SOCK_RAW) ? 0 : next_port++;
- int read_size = op_size;
- struct sockaddr_in addr;
- bool failed = false;
- int src, dst, rcv;
-
- src = socket(AF_INET, s.type, s.protocol);
- if (src < 0)
- error(1, errno, "Failed to open src socket");
-
- dst = socket(AF_INET, s.type, s.protocol);
- if (dst < 0)
- error(1, errno, "Failed to open dst socket");
-
- memset(&addr, 0, sizeof(addr));
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- addr.sin_port = htons(port);
-
- if (bind(dst, (struct sockaddr *)&addr, sizeof(addr)) < 0)
- error(1, errno, "Failed to bind to port %d", port);
-
- if (s.type == SOCK_STREAM && (listen(dst, 1) < 0))
- error(1, errno, "Failed to listen");
-
- if (connect(src, (struct sockaddr *)&addr, sizeof(addr)) < 0)
- error(1, errno, "Failed to connect");
-
- if (s.type == SOCK_STREAM) {
- rcv = accept(dst, NULL, NULL);
- if (rcv < 0)
- error(1, errno, "Failed to accept");
- close(dst);
- } else {
- rcv = dst;
- }
-
- config_so_flags(rcv, t.sockopt);
- usleep(20000); /* setsockopt for SO_TIMESTAMPING is asynchronous */
- do_send(src);
-
- if (s.type == SOCK_RAW)
- read_size += 20; /* for IP header */
- failed = do_recv(rcv, read_size, t.expected);
-
- close(rcv);
- close(src);
-
- return failed;
-}
-
-int main(int argc, char **argv)
-{
- bool all_protocols = true;
- bool all_tests = true;
- int arg_index = 0;
- int failures = 0;
- int s, t;
- char opt;
-
- while ((opt = getopt_long(argc, argv, "", long_options,
- &arg_index)) != -1) {
- switch (opt) {
- case 'l':
- for (t = 0; t < ARRAY_SIZE(test_cases); t++) {
- printf("%d\t", t);
- print_test_case(&test_cases[t]);
- }
- return 0;
- case 'n':
- t = atoi(optarg);
- if (t >= ARRAY_SIZE(test_cases))
- error(1, 0, "Invalid test case: %d", t);
- all_tests = false;
- test_cases[t].enabled = true;
- break;
- case 's':
- op_size = atoi(optarg);
- break;
- case 't':
- all_protocols = false;
- socket_types[2].enabled = true;
- break;
- case 'u':
- all_protocols = false;
- socket_types[1].enabled = true;
- break;
- case 'i':
- all_protocols = false;
- socket_types[0].enabled = true;
- break;
- default:
- error(1, 0, "Failed to parse parameters.");
- }
- }
-
- for (s = 0; s < ARRAY_SIZE(socket_types); s++) {
- if (!all_protocols && !socket_types[s].enabled)
- continue;
-
- printf("Testing %s...\n", socket_types[s].friendly_name);
- for (t = 0; t < ARRAY_SIZE(test_cases); t++) {
- if (!all_tests && !test_cases[t].enabled)
- continue;
-
- printf("Starting testcase %d...\n", t);
- if (run_test_case(socket_types[s], test_cases[t])) {
- failures++;
- printf("FAILURE in test case ");
- print_test_case(&test_cases[t]);
- }
- }
- }
- if (!failures)
- printf("PASSED.\n");
- return failures;
-}
diff --git a/tools/testing/selftests/networking/timestamping/timestamping.c b/tools/testing/selftests/networking/timestamping/timestamping.c
deleted file mode 100644
index aca3491174a1..000000000000
--- a/tools/testing/selftests/networking/timestamping/timestamping.c
+++ /dev/null
@@ -1,509 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * This program demonstrates how the various time stamping features in
- * the Linux kernel work. It emulates the behavior of a PTP
- * implementation in stand-alone master mode by sending PTPv1 Sync
- * multicasts once every second. It looks for similar packets, but
- * beyond that doesn't actually implement PTP.
- *
- * Outgoing packets are time stamped with SO_TIMESTAMPING with or
- * without hardware support.
- *
- * Incoming packets are time stamped with SO_TIMESTAMPING with or
- * without hardware support, SIOCGSTAMP[NS] (per-socket time stamp) and
- * SO_TIMESTAMP[NS].
- *
- * Copyright (C) 2009 Intel Corporation.
- * Author: Patrick Ohly <patrick.ohly@intel.com>
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-
-#include <sys/time.h>
-#include <sys/socket.h>
-#include <sys/select.h>
-#include <sys/ioctl.h>
-#include <arpa/inet.h>
-#include <net/if.h>
-
-#include <asm/types.h>
-#include <linux/net_tstamp.h>
-#include <linux/errqueue.h>
-#include <linux/sockios.h>
-
-#ifndef SO_TIMESTAMPING
-# define SO_TIMESTAMPING 37
-# define SCM_TIMESTAMPING SO_TIMESTAMPING
-#endif
-
-#ifndef SO_TIMESTAMPNS
-# define SO_TIMESTAMPNS 35
-#endif
-
-static void usage(const char *error)
-{
- if (error)
- printf("invalid option: %s\n", error);
- printf("timestamping interface option*\n\n"
- "Options:\n"
- " IP_MULTICAST_LOOP - looping outgoing multicasts\n"
- " SO_TIMESTAMP - normal software time stamping, ms resolution\n"
- " SO_TIMESTAMPNS - more accurate software time stamping\n"
- " SOF_TIMESTAMPING_TX_HARDWARE - hardware time stamping of outgoing packets\n"
- " SOF_TIMESTAMPING_TX_SOFTWARE - software fallback for outgoing packets\n"
- " SOF_TIMESTAMPING_RX_HARDWARE - hardware time stamping of incoming packets\n"
- " SOF_TIMESTAMPING_RX_SOFTWARE - software fallback for incoming packets\n"
- " SOF_TIMESTAMPING_SOFTWARE - request reporting of software time stamps\n"
- " SOF_TIMESTAMPING_RAW_HARDWARE - request reporting of raw HW time stamps\n"
- " SIOCGSTAMP - check last socket time stamp\n"
- " SIOCGSTAMPNS - more accurate socket time stamp\n");
- exit(1);
-}
-
-static void bail(const char *error)
-{
- printf("%s: %s\n", error, strerror(errno));
- exit(1);
-}
-
-static const unsigned char sync[] = {
- 0x00, 0x01, 0x00, 0x01,
- 0x5f, 0x44, 0x46, 0x4c,
- 0x54, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x01,
-
- /* fake uuid */
- 0x00, 0x01,
- 0x02, 0x03, 0x04, 0x05,
-
- 0x00, 0x01, 0x00, 0x37,
- 0x00, 0x00, 0x00, 0x08,
- 0x00, 0x00, 0x00, 0x00,
- 0x49, 0x05, 0xcd, 0x01,
- 0x29, 0xb1, 0x8d, 0xb0,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x01,
-
- /* fake uuid */
- 0x00, 0x01,
- 0x02, 0x03, 0x04, 0x05,
-
- 0x00, 0x00, 0x00, 0x37,
- 0x00, 0x00, 0x00, 0x04,
- 0x44, 0x46, 0x4c, 0x54,
- 0x00, 0x00, 0xf0, 0x60,
- 0x00, 0x01, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0xf0, 0x60,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x04,
- 0x44, 0x46, 0x4c, 0x54,
- 0x00, 0x01,
-
- /* fake uuid */
- 0x00, 0x01,
- 0x02, 0x03, 0x04, 0x05,
-
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00
-};
-
-static void sendpacket(int sock, struct sockaddr *addr, socklen_t addr_len)
-{
- struct timeval now;
- int res;
-
- res = sendto(sock, sync, sizeof(sync), 0,
- addr, addr_len);
- gettimeofday(&now, 0);
- if (res < 0)
- printf("%s: %s\n", "send", strerror(errno));
- else
- printf("%ld.%06ld: sent %d bytes\n",
- (long)now.tv_sec, (long)now.tv_usec,
- res);
-}
-
-static void printpacket(struct msghdr *msg, int res,
- char *data,
- int sock, int recvmsg_flags,
- int siocgstamp, int siocgstampns)
-{
- struct sockaddr_in *from_addr = (struct sockaddr_in *)msg->msg_name;
- struct cmsghdr *cmsg;
- struct timeval tv;
- struct timespec ts;
- struct timeval now;
-
- gettimeofday(&now, 0);
-
- printf("%ld.%06ld: received %s data, %d bytes from %s, %zu bytes control messages\n",
- (long)now.tv_sec, (long)now.tv_usec,
- (recvmsg_flags & MSG_ERRQUEUE) ? "error" : "regular",
- res,
- inet_ntoa(from_addr->sin_addr),
- msg->msg_controllen);
- for (cmsg = CMSG_FIRSTHDR(msg);
- cmsg;
- cmsg = CMSG_NXTHDR(msg, cmsg)) {
- printf(" cmsg len %zu: ", cmsg->cmsg_len);
- switch (cmsg->cmsg_level) {
- case SOL_SOCKET:
- printf("SOL_SOCKET ");
- switch (cmsg->cmsg_type) {
- case SO_TIMESTAMP: {
- struct timeval *stamp =
- (struct timeval *)CMSG_DATA(cmsg);
- printf("SO_TIMESTAMP %ld.%06ld",
- (long)stamp->tv_sec,
- (long)stamp->tv_usec);
- break;
- }
- case SO_TIMESTAMPNS: {
- struct timespec *stamp =
- (struct timespec *)CMSG_DATA(cmsg);
- printf("SO_TIMESTAMPNS %ld.%09ld",
- (long)stamp->tv_sec,
- (long)stamp->tv_nsec);
- break;
- }
- case SO_TIMESTAMPING: {
- struct timespec *stamp =
- (struct timespec *)CMSG_DATA(cmsg);
- printf("SO_TIMESTAMPING ");
- printf("SW %ld.%09ld ",
- (long)stamp->tv_sec,
- (long)stamp->tv_nsec);
- stamp++;
- /* skip deprecated HW transformed */
- stamp++;
- printf("HW raw %ld.%09ld",
- (long)stamp->tv_sec,
- (long)stamp->tv_nsec);
- break;
- }
- default:
- printf("type %d", cmsg->cmsg_type);
- break;
- }
- break;
- case IPPROTO_IP:
- printf("IPPROTO_IP ");
- switch (cmsg->cmsg_type) {
- case IP_RECVERR: {
- struct sock_extended_err *err =
- (struct sock_extended_err *)CMSG_DATA(cmsg);
- printf("IP_RECVERR ee_errno '%s' ee_origin %d => %s",
- strerror(err->ee_errno),
- err->ee_origin,
-#ifdef SO_EE_ORIGIN_TIMESTAMPING
- err->ee_origin == SO_EE_ORIGIN_TIMESTAMPING ?
- "bounced packet" : "unexpected origin"
-#else
- "probably SO_EE_ORIGIN_TIMESTAMPING"
-#endif
- );
- if (res < sizeof(sync))
- printf(" => truncated data?!");
- else if (!memcmp(sync, data + res - sizeof(sync),
- sizeof(sync)))
- printf(" => GOT OUR DATA BACK (HURRAY!)");
- break;
- }
- case IP_PKTINFO: {
- struct in_pktinfo *pktinfo =
- (struct in_pktinfo *)CMSG_DATA(cmsg);
- printf("IP_PKTINFO interface index %u",
- pktinfo->ipi_ifindex);
- break;
- }
- default:
- printf("type %d", cmsg->cmsg_type);
- break;
- }
- break;
- default:
- printf("level %d type %d",
- cmsg->cmsg_level,
- cmsg->cmsg_type);
- break;
- }
- printf("\n");
- }
-
- if (siocgstamp) {
- if (ioctl(sock, SIOCGSTAMP, &tv))
- printf(" %s: %s\n", "SIOCGSTAMP", strerror(errno));
- else
- printf("SIOCGSTAMP %ld.%06ld\n",
- (long)tv.tv_sec,
- (long)tv.tv_usec);
- }
- if (siocgstampns) {
- if (ioctl(sock, SIOCGSTAMPNS, &ts))
- printf(" %s: %s\n", "SIOCGSTAMPNS", strerror(errno));
- else
- printf("SIOCGSTAMPNS %ld.%09ld\n",
- (long)ts.tv_sec,
- (long)ts.tv_nsec);
- }
-}
-
-static void recvpacket(int sock, int recvmsg_flags,
- int siocgstamp, int siocgstampns)
-{
- char data[256];
- struct msghdr msg;
- struct iovec entry;
- struct sockaddr_in from_addr;
- struct {
- struct cmsghdr cm;
- char control[512];
- } control;
- int res;
-
- memset(&msg, 0, sizeof(msg));
- msg.msg_iov = &entry;
- msg.msg_iovlen = 1;
- entry.iov_base = data;
- entry.iov_len = sizeof(data);
- msg.msg_name = (caddr_t)&from_addr;
- msg.msg_namelen = sizeof(from_addr);
- msg.msg_control = &control;
- msg.msg_controllen = sizeof(control);
-
- res = recvmsg(sock, &msg, recvmsg_flags|MSG_DONTWAIT);
- if (res < 0) {
- printf("%s %s: %s\n",
- "recvmsg",
- (recvmsg_flags & MSG_ERRQUEUE) ? "error" : "regular",
- strerror(errno));
- } else {
- printpacket(&msg, res, data,
- sock, recvmsg_flags,
- siocgstamp, siocgstampns);
- }
-}
-
-int main(int argc, char **argv)
-{
- int so_timestamping_flags = 0;
- int so_timestamp = 0;
- int so_timestampns = 0;
- int siocgstamp = 0;
- int siocgstampns = 0;
- int ip_multicast_loop = 0;
- char *interface;
- int i;
- int enabled = 1;
- int sock;
- struct ifreq device;
- struct ifreq hwtstamp;
- struct hwtstamp_config hwconfig, hwconfig_requested;
- struct sockaddr_in addr;
- struct ip_mreq imr;
- struct in_addr iaddr;
- int val;
- socklen_t len;
- struct timeval next;
-
- if (argc < 2)
- usage(0);
- interface = argv[1];
-
- for (i = 2; i < argc; i++) {
- if (!strcasecmp(argv[i], "SO_TIMESTAMP"))
- so_timestamp = 1;
- else if (!strcasecmp(argv[i], "SO_TIMESTAMPNS"))
- so_timestampns = 1;
- else if (!strcasecmp(argv[i], "SIOCGSTAMP"))
- siocgstamp = 1;
- else if (!strcasecmp(argv[i], "SIOCGSTAMPNS"))
- siocgstampns = 1;
- else if (!strcasecmp(argv[i], "IP_MULTICAST_LOOP"))
- ip_multicast_loop = 1;
- else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_TX_HARDWARE"))
- so_timestamping_flags |= SOF_TIMESTAMPING_TX_HARDWARE;
- else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_TX_SOFTWARE"))
- so_timestamping_flags |= SOF_TIMESTAMPING_TX_SOFTWARE;
- else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_RX_HARDWARE"))
- so_timestamping_flags |= SOF_TIMESTAMPING_RX_HARDWARE;
- else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_RX_SOFTWARE"))
- so_timestamping_flags |= SOF_TIMESTAMPING_RX_SOFTWARE;
- else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_SOFTWARE"))
- so_timestamping_flags |= SOF_TIMESTAMPING_SOFTWARE;
- else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_RAW_HARDWARE"))
- so_timestamping_flags |= SOF_TIMESTAMPING_RAW_HARDWARE;
- else
- usage(argv[i]);
- }
-
- sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if (sock < 0)
- bail("socket");
-
- memset(&device, 0, sizeof(device));
- strncpy(device.ifr_name, interface, sizeof(device.ifr_name));
- if (ioctl(sock, SIOCGIFADDR, &device) < 0)
- bail("getting interface IP address");
-
- memset(&hwtstamp, 0, sizeof(hwtstamp));
- strncpy(hwtstamp.ifr_name, interface, sizeof(hwtstamp.ifr_name));
- hwtstamp.ifr_data = (void *)&hwconfig;
- memset(&hwconfig, 0, sizeof(hwconfig));
- hwconfig.tx_type =
- (so_timestamping_flags & SOF_TIMESTAMPING_TX_HARDWARE) ?
- HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
- hwconfig.rx_filter =
- (so_timestamping_flags & SOF_TIMESTAMPING_RX_HARDWARE) ?
- HWTSTAMP_FILTER_PTP_V1_L4_SYNC : HWTSTAMP_FILTER_NONE;
- hwconfig_requested = hwconfig;
- if (ioctl(sock, SIOCSHWTSTAMP, &hwtstamp) < 0) {
- if ((errno == EINVAL || errno == ENOTSUP) &&
- hwconfig_requested.tx_type == HWTSTAMP_TX_OFF &&
- hwconfig_requested.rx_filter == HWTSTAMP_FILTER_NONE)
- printf("SIOCSHWTSTAMP: disabling hardware time stamping not possible\n");
- else
- bail("SIOCSHWTSTAMP");
- }
- printf("SIOCSHWTSTAMP: tx_type %d requested, got %d; rx_filter %d requested, got %d\n",
- hwconfig_requested.tx_type, hwconfig.tx_type,
- hwconfig_requested.rx_filter, hwconfig.rx_filter);
-
- /* bind to PTP port */
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = htonl(INADDR_ANY);
- addr.sin_port = htons(319 /* PTP event port */);
- if (bind(sock,
- (struct sockaddr *)&addr,
- sizeof(struct sockaddr_in)) < 0)
- bail("bind");
-
- /* set multicast group for outgoing packets */
- inet_aton("224.0.1.130", &iaddr); /* alternate PTP domain 1 */
- addr.sin_addr = iaddr;
- imr.imr_multiaddr.s_addr = iaddr.s_addr;
- imr.imr_interface.s_addr =
- ((struct sockaddr_in *)&device.ifr_addr)->sin_addr.s_addr;
- if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
- &imr.imr_interface.s_addr, sizeof(struct in_addr)) < 0)
- bail("set multicast");
-
- /* join multicast group, loop our own packet */
- if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
- &imr, sizeof(struct ip_mreq)) < 0)
- bail("join multicast group");
-
- if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP,
- &ip_multicast_loop, sizeof(enabled)) < 0) {
- bail("loop multicast");
- }
-
- /* set socket options for time stamping */
- if (so_timestamp &&
- setsockopt(sock, SOL_SOCKET, SO_TIMESTAMP,
- &enabled, sizeof(enabled)) < 0)
- bail("setsockopt SO_TIMESTAMP");
-
- if (so_timestampns &&
- setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPNS,
- &enabled, sizeof(enabled)) < 0)
- bail("setsockopt SO_TIMESTAMPNS");
-
- if (so_timestamping_flags &&
- setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPING,
- &so_timestamping_flags,
- sizeof(so_timestamping_flags)) < 0)
- bail("setsockopt SO_TIMESTAMPING");
-
- /* request IP_PKTINFO for debugging purposes */
- if (setsockopt(sock, SOL_IP, IP_PKTINFO,
- &enabled, sizeof(enabled)) < 0)
- printf("%s: %s\n", "setsockopt IP_PKTINFO", strerror(errno));
-
- /* verify socket options */
- len = sizeof(val);
- if (getsockopt(sock, SOL_SOCKET, SO_TIMESTAMP, &val, &len) < 0)
- printf("%s: %s\n", "getsockopt SO_TIMESTAMP", strerror(errno));
- else
- printf("SO_TIMESTAMP %d\n", val);
-
- if (getsockopt(sock, SOL_SOCKET, SO_TIMESTAMPNS, &val, &len) < 0)
- printf("%s: %s\n", "getsockopt SO_TIMESTAMPNS",
- strerror(errno));
- else
- printf("SO_TIMESTAMPNS %d\n", val);
-
- if (getsockopt(sock, SOL_SOCKET, SO_TIMESTAMPING, &val, &len) < 0) {
- printf("%s: %s\n", "getsockopt SO_TIMESTAMPING",
- strerror(errno));
- } else {
- printf("SO_TIMESTAMPING %d\n", val);
- if (val != so_timestamping_flags)
- printf(" not the expected value %d\n",
- so_timestamping_flags);
- }
-
- /* send packets forever every five seconds */
- gettimeofday(&next, 0);
- next.tv_sec = (next.tv_sec + 1) / 5 * 5;
- next.tv_usec = 0;
- while (1) {
- struct timeval now;
- struct timeval delta;
- long delta_us;
- int res;
- fd_set readfs, errorfs;
-
- gettimeofday(&now, 0);
- delta_us = (long)(next.tv_sec - now.tv_sec) * 1000000 +
- (long)(next.tv_usec - now.tv_usec);
- if (delta_us > 0) {
- /* continue waiting for timeout or data */
- delta.tv_sec = delta_us / 1000000;
- delta.tv_usec = delta_us % 1000000;
-
- FD_ZERO(&readfs);
- FD_ZERO(&errorfs);
- FD_SET(sock, &readfs);
- FD_SET(sock, &errorfs);
- printf("%ld.%06ld: select %ldus\n",
- (long)now.tv_sec, (long)now.tv_usec,
- delta_us);
- res = select(sock + 1, &readfs, 0, &errorfs, &delta);
- gettimeofday(&now, 0);
- printf("%ld.%06ld: select returned: %d, %s\n",
- (long)now.tv_sec, (long)now.tv_usec,
- res,
- res < 0 ? strerror(errno) : "success");
- if (res > 0) {
- if (FD_ISSET(sock, &readfs))
- printf("ready for reading\n");
- if (FD_ISSET(sock, &errorfs))
- printf("has error\n");
- recvpacket(sock, 0,
- siocgstamp,
- siocgstampns);
- recvpacket(sock, MSG_ERRQUEUE,
- siocgstamp,
- siocgstampns);
- }
- } else {
- /* write one packet */
- sendpacket(sock,
- (struct sockaddr *)&addr,
- sizeof(addr));
- next.tv_sec += 5;
- continue;
- }
- }
-
- return 0;
-}
diff --git a/tools/testing/selftests/networking/timestamping/txtimestamp.c b/tools/testing/selftests/networking/timestamping/txtimestamp.c
deleted file mode 100644
index 011b0da6b033..000000000000
--- a/tools/testing/selftests/networking/timestamping/txtimestamp.c
+++ /dev/null
@@ -1,916 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright 2014 Google Inc.
- * Author: willemb@google.com (Willem de Bruijn)
- *
- * Test software tx timestamping, including
- *
- * - SCHED, SND and ACK timestamps
- * - RAW, UDP and TCP
- * - IPv4 and IPv6
- * - various packet sizes (to test GSO and TSO)
- *
- * Consult the command line arguments for help on running
- * the various testcases.
- *
- * This test requires a dummy TCP server.
- * A simple `nc6 [-u] -l -p $DESTPORT` will do
- */
-
-#define _GNU_SOURCE
-
-#include <arpa/inet.h>
-#include <asm/types.h>
-#include <error.h>
-#include <errno.h>
-#include <inttypes.h>
-#include <linux/errqueue.h>
-#include <linux/if_ether.h>
-#include <linux/ipv6.h>
-#include <linux/net_tstamp.h>
-#include <netdb.h>
-#include <net/if.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <netinet/udp.h>
-#include <netinet/tcp.h>
-#include <netpacket/packet.h>
-#include <poll.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/epoll.h>
-#include <sys/ioctl.h>
-#include <sys/select.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <time.h>
-#include <unistd.h>
-
-#define NSEC_PER_USEC 1000L
-#define USEC_PER_SEC 1000000L
-#define NSEC_PER_SEC 1000000000LL
-
-/* command line parameters */
-static int cfg_proto = SOCK_STREAM;
-static int cfg_ipproto = IPPROTO_TCP;
-static int cfg_num_pkts = 4;
-static int do_ipv4 = 1;
-static int do_ipv6 = 1;
-static int cfg_payload_len = 10;
-static int cfg_poll_timeout = 100;
-static int cfg_delay_snd;
-static int cfg_delay_ack;
-static bool cfg_show_payload;
-static bool cfg_do_pktinfo;
-static bool cfg_busy_poll;
-static int cfg_sleep_usec = 50 * 1000;
-static bool cfg_loop_nodata;
-static bool cfg_use_cmsg;
-static bool cfg_use_pf_packet;
-static bool cfg_use_epoll;
-static bool cfg_epollet;
-static bool cfg_do_listen;
-static uint16_t dest_port = 9000;
-static bool cfg_print_nsec;
-
-static struct sockaddr_in daddr;
-static struct sockaddr_in6 daddr6;
-static struct timespec ts_usr;
-
-static int saved_tskey = -1;
-static int saved_tskey_type = -1;
-
-struct timing_event {
- int64_t min;
- int64_t max;
- int64_t total;
- int count;
-};
-
-static struct timing_event usr_enq;
-static struct timing_event usr_snd;
-static struct timing_event usr_ack;
-
-static bool test_failed;
-
-static int64_t timespec_to_ns64(struct timespec *ts)
-{
- return ts->tv_sec * NSEC_PER_SEC + ts->tv_nsec;
-}
-
-static int64_t timespec_to_us64(struct timespec *ts)
-{
- return ts->tv_sec * USEC_PER_SEC + ts->tv_nsec / NSEC_PER_USEC;
-}
-
-static void init_timing_event(struct timing_event *te)
-{
- te->min = INT64_MAX;
- te->max = 0;
- te->total = 0;
- te->count = 0;
-}
-
-static void add_timing_event(struct timing_event *te,
- struct timespec *t_start, struct timespec *t_end)
-{
- int64_t ts_delta = timespec_to_ns64(t_end) - timespec_to_ns64(t_start);
-
- te->count++;
- if (ts_delta < te->min)
- te->min = ts_delta;
- if (ts_delta > te->max)
- te->max = ts_delta;
- te->total += ts_delta;
-}
-
-static void validate_key(int tskey, int tstype)
-{
- int stepsize;
-
- /* compare key for each subsequent request
- * must only test for one type, the first one requested
- */
- if (saved_tskey == -1)
- saved_tskey_type = tstype;
- else if (saved_tskey_type != tstype)
- return;
-
- stepsize = cfg_proto == SOCK_STREAM ? cfg_payload_len : 1;
- if (tskey != saved_tskey + stepsize) {
- fprintf(stderr, "ERROR: key %d, expected %d\n",
- tskey, saved_tskey + stepsize);
- test_failed = true;
- }
-
- saved_tskey = tskey;
-}
-
-static void validate_timestamp(struct timespec *cur, int min_delay)
-{
- int max_delay = min_delay + 500 /* processing time upper bound */;
- int64_t cur64, start64;
-
- cur64 = timespec_to_us64(cur);
- start64 = timespec_to_us64(&ts_usr);
-
- if (cur64 < start64 + min_delay || cur64 > start64 + max_delay) {
- fprintf(stderr, "ERROR: %lu us expected between %d and %d\n",
- cur64 - start64, min_delay, max_delay);
- test_failed = true;
- }
-}
-
-static void __print_ts_delta_formatted(int64_t ts_delta)
-{
- if (cfg_print_nsec)
- fprintf(stderr, "%lu ns", ts_delta);
- else
- fprintf(stderr, "%lu us", ts_delta / NSEC_PER_USEC);
-}
-
-static void __print_timestamp(const char *name, struct timespec *cur,
- uint32_t key, int payload_len)
-{
- int64_t ts_delta;
-
- if (!(cur->tv_sec | cur->tv_nsec))
- return;
-
- if (cfg_print_nsec)
- fprintf(stderr, " %s: %lu s %lu ns (seq=%u, len=%u)",
- name, cur->tv_sec, cur->tv_nsec,
- key, payload_len);
- else
- fprintf(stderr, " %s: %lu s %lu us (seq=%u, len=%u)",
- name, cur->tv_sec, cur->tv_nsec / NSEC_PER_USEC,
- key, payload_len);
-
- if (cur != &ts_usr) {
- ts_delta = timespec_to_ns64(cur) - timespec_to_ns64(&ts_usr);
- fprintf(stderr, " (USR +");
- __print_ts_delta_formatted(ts_delta);
- fprintf(stderr, ")");
- }
-
- fprintf(stderr, "\n");
-}
-
-static void print_timestamp_usr(void)
-{
- if (clock_gettime(CLOCK_REALTIME, &ts_usr))
- error(1, errno, "clock_gettime");
-
- __print_timestamp(" USR", &ts_usr, 0, 0);
-}
-
-static void print_timestamp(struct scm_timestamping *tss, int tstype,
- int tskey, int payload_len)
-{
- const char *tsname;
-
- validate_key(tskey, tstype);
-
- switch (tstype) {
- case SCM_TSTAMP_SCHED:
- tsname = " ENQ";
- validate_timestamp(&tss->ts[0], 0);
- add_timing_event(&usr_enq, &ts_usr, &tss->ts[0]);
- break;
- case SCM_TSTAMP_SND:
- tsname = " SND";
- validate_timestamp(&tss->ts[0], cfg_delay_snd);
- add_timing_event(&usr_snd, &ts_usr, &tss->ts[0]);
- break;
- case SCM_TSTAMP_ACK:
- tsname = " ACK";
- validate_timestamp(&tss->ts[0], cfg_delay_ack);
- add_timing_event(&usr_ack, &ts_usr, &tss->ts[0]);
- break;
- default:
- error(1, 0, "unknown timestamp type: %u",
- tstype);
- }
- __print_timestamp(tsname, &tss->ts[0], tskey, payload_len);
-}
-
-static void print_timing_event(char *name, struct timing_event *te)
-{
- if (!te->count)
- return;
-
- fprintf(stderr, " %s: count=%d", name, te->count);
- fprintf(stderr, ", avg=");
- __print_ts_delta_formatted((int64_t)(te->total / te->count));
- fprintf(stderr, ", min=");
- __print_ts_delta_formatted(te->min);
- fprintf(stderr, ", max=");
- __print_ts_delta_formatted(te->max);
- fprintf(stderr, "\n");
-}
-
-/* TODO: convert to check_and_print payload once API is stable */
-static void print_payload(char *data, int len)
-{
- int i;
-
- if (!len)
- return;
-
- if (len > 70)
- len = 70;
-
- fprintf(stderr, "payload: ");
- for (i = 0; i < len; i++)
- fprintf(stderr, "%02hhx ", data[i]);
- fprintf(stderr, "\n");
-}
-
-static void print_pktinfo(int family, int ifindex, void *saddr, void *daddr)
-{
- char sa[INET6_ADDRSTRLEN], da[INET6_ADDRSTRLEN];
-
- fprintf(stderr, " pktinfo: ifindex=%u src=%s dst=%s\n",
- ifindex,
- saddr ? inet_ntop(family, saddr, sa, sizeof(sa)) : "unknown",
- daddr ? inet_ntop(family, daddr, da, sizeof(da)) : "unknown");
-}
-
-static void __epoll(int epfd)
-{
- struct epoll_event events;
- int ret;
-
- memset(&events, 0, sizeof(events));
- ret = epoll_wait(epfd, &events, 1, cfg_poll_timeout);
- if (ret != 1)
- error(1, errno, "epoll_wait");
-}
-
-static void __poll(int fd)
-{
- struct pollfd pollfd;
- int ret;
-
- memset(&pollfd, 0, sizeof(pollfd));
- pollfd.fd = fd;
- ret = poll(&pollfd, 1, cfg_poll_timeout);
- if (ret != 1)
- error(1, errno, "poll");
-}
-
-static void __recv_errmsg_cmsg(struct msghdr *msg, int payload_len)
-{
- struct sock_extended_err *serr = NULL;
- struct scm_timestamping *tss = NULL;
- struct cmsghdr *cm;
- int batch = 0;
-
- for (cm = CMSG_FIRSTHDR(msg);
- cm && cm->cmsg_len;
- cm = CMSG_NXTHDR(msg, cm)) {
- if (cm->cmsg_level == SOL_SOCKET &&
- cm->cmsg_type == SCM_TIMESTAMPING) {
- tss = (void *) CMSG_DATA(cm);
- } else if ((cm->cmsg_level == SOL_IP &&
- cm->cmsg_type == IP_RECVERR) ||
- (cm->cmsg_level == SOL_IPV6 &&
- cm->cmsg_type == IPV6_RECVERR) ||
- (cm->cmsg_level == SOL_PACKET &&
- cm->cmsg_type == PACKET_TX_TIMESTAMP)) {
- serr = (void *) CMSG_DATA(cm);
- if (serr->ee_errno != ENOMSG ||
- serr->ee_origin != SO_EE_ORIGIN_TIMESTAMPING) {
- fprintf(stderr, "unknown ip error %d %d\n",
- serr->ee_errno,
- serr->ee_origin);
- serr = NULL;
- }
- } else if (cm->cmsg_level == SOL_IP &&
- cm->cmsg_type == IP_PKTINFO) {
- struct in_pktinfo *info = (void *) CMSG_DATA(cm);
- print_pktinfo(AF_INET, info->ipi_ifindex,
- &info->ipi_spec_dst, &info->ipi_addr);
- } else if (cm->cmsg_level == SOL_IPV6 &&
- cm->cmsg_type == IPV6_PKTINFO) {
- struct in6_pktinfo *info6 = (void *) CMSG_DATA(cm);
- print_pktinfo(AF_INET6, info6->ipi6_ifindex,
- NULL, &info6->ipi6_addr);
- } else
- fprintf(stderr, "unknown cmsg %d,%d\n",
- cm->cmsg_level, cm->cmsg_type);
-
- if (serr && tss) {
- print_timestamp(tss, serr->ee_info, serr->ee_data,
- payload_len);
- serr = NULL;
- tss = NULL;
- batch++;
- }
- }
-
- if (batch > 1)
- fprintf(stderr, "batched %d timestamps\n", batch);
-}
-
-static int recv_errmsg(int fd)
-{
- static char ctrl[1024 /* overprovision*/];
- static struct msghdr msg;
- struct iovec entry;
- static char *data;
- int ret = 0;
-
- data = malloc(cfg_payload_len);
- if (!data)
- error(1, 0, "malloc");
-
- memset(&msg, 0, sizeof(msg));
- memset(&entry, 0, sizeof(entry));
- memset(ctrl, 0, sizeof(ctrl));
-
- entry.iov_base = data;
- entry.iov_len = cfg_payload_len;
- msg.msg_iov = &entry;
- msg.msg_iovlen = 1;
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_control = ctrl;
- msg.msg_controllen = sizeof(ctrl);
-
- ret = recvmsg(fd, &msg, MSG_ERRQUEUE);
- if (ret == -1 && errno != EAGAIN)
- error(1, errno, "recvmsg");
-
- if (ret >= 0) {
- __recv_errmsg_cmsg(&msg, ret);
- if (cfg_show_payload)
- print_payload(data, cfg_payload_len);
- }
-
- free(data);
- return ret == -1;
-}
-
-static uint16_t get_ip_csum(const uint16_t *start, int num_words,
- unsigned long sum)
-{
- int i;
-
- for (i = 0; i < num_words; i++)
- sum += start[i];
-
- while (sum >> 16)
- sum = (sum & 0xFFFF) + (sum >> 16);
-
- return ~sum;
-}
-
-static uint16_t get_udp_csum(const struct udphdr *udph, int alen)
-{
- unsigned long pseudo_sum, csum_len;
- const void *csum_start = udph;
-
- pseudo_sum = htons(IPPROTO_UDP);
- pseudo_sum += udph->len;
-
- /* checksum ip(v6) addresses + udp header + payload */
- csum_start -= alen * 2;
- csum_len = ntohs(udph->len) + alen * 2;
-
- return get_ip_csum(csum_start, csum_len >> 1, pseudo_sum);
-}
-
-static int fill_header_ipv4(void *p)
-{
- struct iphdr *iph = p;
-
- memset(iph, 0, sizeof(*iph));
-
- iph->ihl = 5;
- iph->version = 4;
- iph->ttl = 2;
- iph->saddr = daddr.sin_addr.s_addr; /* set for udp csum calc */
- iph->daddr = daddr.sin_addr.s_addr;
- iph->protocol = IPPROTO_UDP;
-
- /* kernel writes saddr, csum, len */
-
- return sizeof(*iph);
-}
-
-static int fill_header_ipv6(void *p)
-{
- struct ipv6hdr *ip6h = p;
-
- memset(ip6h, 0, sizeof(*ip6h));
-
- ip6h->version = 6;
- ip6h->payload_len = htons(sizeof(struct udphdr) + cfg_payload_len);
- ip6h->nexthdr = IPPROTO_UDP;
- ip6h->hop_limit = 64;
-
- ip6h->saddr = daddr6.sin6_addr;
- ip6h->daddr = daddr6.sin6_addr;
-
- /* kernel does not write saddr in case of ipv6 */
-
- return sizeof(*ip6h);
-}
-
-static void fill_header_udp(void *p, bool is_ipv4)
-{
- struct udphdr *udph = p;
-
- udph->source = ntohs(dest_port + 1); /* spoof */
- udph->dest = ntohs(dest_port);
- udph->len = ntohs(sizeof(*udph) + cfg_payload_len);
- udph->check = 0;
-
- udph->check = get_udp_csum(udph, is_ipv4 ? sizeof(struct in_addr) :
- sizeof(struct in6_addr));
-}
-
-static void do_test(int family, unsigned int report_opt)
-{
- char control[CMSG_SPACE(sizeof(uint32_t))];
- struct sockaddr_ll laddr;
- unsigned int sock_opt;
- struct cmsghdr *cmsg;
- struct msghdr msg;
- struct iovec iov;
- char *buf;
- int fd, i, val = 1, total_len, epfd = 0;
-
- init_timing_event(&usr_enq);
- init_timing_event(&usr_snd);
- init_timing_event(&usr_ack);
-
- total_len = cfg_payload_len;
- if (cfg_use_pf_packet || cfg_proto == SOCK_RAW) {
- total_len += sizeof(struct udphdr);
- if (cfg_use_pf_packet || cfg_ipproto == IPPROTO_RAW)
- if (family == PF_INET)
- total_len += sizeof(struct iphdr);
- else
- total_len += sizeof(struct ipv6hdr);
-
- /* special case, only rawv6_sendmsg:
- * pass proto in sin6_port if not connected
- * also see ANK comment in net/ipv4/raw.c
- */
- daddr6.sin6_port = htons(cfg_ipproto);
- }
-
- buf = malloc(total_len);
- if (!buf)
- error(1, 0, "malloc");
-
- fd = socket(cfg_use_pf_packet ? PF_PACKET : family,
- cfg_proto, cfg_ipproto);
- if (fd < 0)
- error(1, errno, "socket");
-
- if (cfg_use_epoll) {
- struct epoll_event ev;
-
- memset(&ev, 0, sizeof(ev));
- ev.data.fd = fd;
- if (cfg_epollet)
- ev.events |= EPOLLET;
- epfd = epoll_create(1);
- if (epfd <= 0)
- error(1, errno, "epoll_create");
- if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev))
- error(1, errno, "epoll_ctl");
- }
-
- /* reset expected key on each new socket */
- saved_tskey = -1;
-
- if (cfg_proto == SOCK_STREAM) {
- if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
- (char*) &val, sizeof(val)))
- error(1, 0, "setsockopt no nagle");
-
- if (family == PF_INET) {
- if (connect(fd, (void *) &daddr, sizeof(daddr)))
- error(1, errno, "connect ipv4");
- } else {
- if (connect(fd, (void *) &daddr6, sizeof(daddr6)))
- error(1, errno, "connect ipv6");
- }
- }
-
- if (cfg_do_pktinfo) {
- if (family == AF_INET6) {
- if (setsockopt(fd, SOL_IPV6, IPV6_RECVPKTINFO,
- &val, sizeof(val)))
- error(1, errno, "setsockopt pktinfo ipv6");
- } else {
- if (setsockopt(fd, SOL_IP, IP_PKTINFO,
- &val, sizeof(val)))
- error(1, errno, "setsockopt pktinfo ipv4");
- }
- }
-
- sock_opt = SOF_TIMESTAMPING_SOFTWARE |
- SOF_TIMESTAMPING_OPT_CMSG |
- SOF_TIMESTAMPING_OPT_ID;
-
- if (!cfg_use_cmsg)
- sock_opt |= report_opt;
-
- if (cfg_loop_nodata)
- sock_opt |= SOF_TIMESTAMPING_OPT_TSONLY;
-
- if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING,
- (char *) &sock_opt, sizeof(sock_opt)))
- error(1, 0, "setsockopt timestamping");
-
- for (i = 0; i < cfg_num_pkts; i++) {
- memset(&msg, 0, sizeof(msg));
- memset(buf, 'a' + i, total_len);
-
- if (cfg_use_pf_packet || cfg_proto == SOCK_RAW) {
- int off = 0;
-
- if (cfg_use_pf_packet || cfg_ipproto == IPPROTO_RAW) {
- if (family == PF_INET)
- off = fill_header_ipv4(buf);
- else
- off = fill_header_ipv6(buf);
- }
-
- fill_header_udp(buf + off, family == PF_INET);
- }
-
- print_timestamp_usr();
-
- iov.iov_base = buf;
- iov.iov_len = total_len;
-
- if (cfg_proto != SOCK_STREAM) {
- if (cfg_use_pf_packet) {
- memset(&laddr, 0, sizeof(laddr));
-
- laddr.sll_family = AF_PACKET;
- laddr.sll_ifindex = 1;
- laddr.sll_protocol = htons(family == AF_INET ? ETH_P_IP : ETH_P_IPV6);
- laddr.sll_halen = ETH_ALEN;
-
- msg.msg_name = (void *)&laddr;
- msg.msg_namelen = sizeof(laddr);
- } else if (family == PF_INET) {
- msg.msg_name = (void *)&daddr;
- msg.msg_namelen = sizeof(daddr);
- } else {
- msg.msg_name = (void *)&daddr6;
- msg.msg_namelen = sizeof(daddr6);
- }
- }
-
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
-
- if (cfg_use_cmsg) {
- memset(control, 0, sizeof(control));
-
- msg.msg_control = control;
- msg.msg_controllen = sizeof(control);
-
- cmsg = CMSG_FIRSTHDR(&msg);
- cmsg->cmsg_level = SOL_SOCKET;
- cmsg->cmsg_type = SO_TIMESTAMPING;
- cmsg->cmsg_len = CMSG_LEN(sizeof(uint32_t));
-
- *((uint32_t *) CMSG_DATA(cmsg)) = report_opt;
- }
-
- val = sendmsg(fd, &msg, 0);
- if (val != total_len)
- error(1, errno, "send");
-
- /* wait for all errors to be queued, else ACKs arrive OOO */
- if (cfg_sleep_usec)
- usleep(cfg_sleep_usec);
-
- if (!cfg_busy_poll) {
- if (cfg_use_epoll)
- __epoll(epfd);
- else
- __poll(fd);
- }
-
- while (!recv_errmsg(fd)) {}
- }
-
- print_timing_event("USR-ENQ", &usr_enq);
- print_timing_event("USR-SND", &usr_snd);
- print_timing_event("USR-ACK", &usr_ack);
-
- if (close(fd))
- error(1, errno, "close");
-
- free(buf);
- usleep(100 * NSEC_PER_USEC);
-}
-
-static void __attribute__((noreturn)) usage(const char *filepath)
-{
- fprintf(stderr, "\nUsage: %s [options] hostname\n"
- "\nwhere options are:\n"
- " -4: only IPv4\n"
- " -6: only IPv6\n"
- " -h: show this message\n"
- " -b: busy poll to read from error queue\n"
- " -c N: number of packets for each test\n"
- " -C: use cmsg to set tstamp recording options\n"
- " -e: use level-triggered epoll() instead of poll()\n"
- " -E: use event-triggered epoll() instead of poll()\n"
- " -F: poll()/epoll() waits forever for an event\n"
- " -I: request PKTINFO\n"
- " -l N: send N bytes at a time\n"
- " -L listen on hostname and port\n"
- " -n: set no-payload option\n"
- " -N: print timestamps and durations in nsec (instead of usec)\n"
- " -p N: connect to port N\n"
- " -P: use PF_PACKET\n"
- " -r: use raw\n"
- " -R: use raw (IP_HDRINCL)\n"
- " -S N: usec to sleep before reading error queue\n"
- " -u: use udp\n"
- " -v: validate SND delay (usec)\n"
- " -V: validate ACK delay (usec)\n"
- " -x: show payload (up to 70 bytes)\n",
- filepath);
- exit(1);
-}
-
-static void parse_opt(int argc, char **argv)
-{
- int proto_count = 0;
- int c;
-
- while ((c = getopt(argc, argv,
- "46bc:CeEFhIl:LnNp:PrRS:uv:V:x")) != -1) {
- switch (c) {
- case '4':
- do_ipv6 = 0;
- break;
- case '6':
- do_ipv4 = 0;
- break;
- case 'b':
- cfg_busy_poll = true;
- break;
- case 'c':
- cfg_num_pkts = strtoul(optarg, NULL, 10);
- break;
- case 'C':
- cfg_use_cmsg = true;
- break;
- case 'e':
- cfg_use_epoll = true;
- break;
- case 'E':
- cfg_use_epoll = true;
- cfg_epollet = true;
- case 'F':
- cfg_poll_timeout = -1;
- break;
- case 'I':
- cfg_do_pktinfo = true;
- break;
- case 'l':
- cfg_payload_len = strtoul(optarg, NULL, 10);
- break;
- case 'L':
- cfg_do_listen = true;
- break;
- case 'n':
- cfg_loop_nodata = true;
- break;
- case 'N':
- cfg_print_nsec = true;
- break;
- case 'p':
- dest_port = strtoul(optarg, NULL, 10);
- break;
- case 'P':
- proto_count++;
- cfg_use_pf_packet = true;
- cfg_proto = SOCK_DGRAM;
- cfg_ipproto = 0;
- break;
- case 'r':
- proto_count++;
- cfg_proto = SOCK_RAW;
- cfg_ipproto = IPPROTO_UDP;
- break;
- case 'R':
- proto_count++;
- cfg_proto = SOCK_RAW;
- cfg_ipproto = IPPROTO_RAW;
- break;
- case 'S':
- cfg_sleep_usec = strtoul(optarg, NULL, 10);
- break;
- case 'u':
- proto_count++;
- cfg_proto = SOCK_DGRAM;
- cfg_ipproto = IPPROTO_UDP;
- break;
- case 'v':
- cfg_delay_snd = strtoul(optarg, NULL, 10);
- break;
- case 'V':
- cfg_delay_ack = strtoul(optarg, NULL, 10);
- break;
- case 'x':
- cfg_show_payload = true;
- break;
- case 'h':
- default:
- usage(argv[0]);
- }
- }
-
- if (!cfg_payload_len)
- error(1, 0, "payload may not be nonzero");
- if (cfg_proto != SOCK_STREAM && cfg_payload_len > 1472)
- error(1, 0, "udp packet might exceed expected MTU");
- if (!do_ipv4 && !do_ipv6)
- error(1, 0, "pass -4 or -6, not both");
- if (proto_count > 1)
- error(1, 0, "pass -P, -r, -R or -u, not multiple");
- if (cfg_do_pktinfo && cfg_use_pf_packet)
- error(1, 0, "cannot ask for pktinfo over pf_packet");
- if (cfg_busy_poll && cfg_use_epoll)
- error(1, 0, "pass epoll or busy_poll, not both");
-
- if (optind != argc - 1)
- error(1, 0, "missing required hostname argument");
-}
-
-static void resolve_hostname(const char *hostname)
-{
- struct addrinfo hints = { .ai_family = do_ipv4 ? AF_INET : AF_INET6 };
- struct addrinfo *addrs, *cur;
- int have_ipv4 = 0, have_ipv6 = 0;
-
-retry:
- if (getaddrinfo(hostname, NULL, &hints, &addrs))
- error(1, errno, "getaddrinfo");
-
- cur = addrs;
- while (cur && !have_ipv4 && !have_ipv6) {
- if (!have_ipv4 && cur->ai_family == AF_INET) {
- memcpy(&daddr, cur->ai_addr, sizeof(daddr));
- daddr.sin_port = htons(dest_port);
- have_ipv4 = 1;
- }
- else if (!have_ipv6 && cur->ai_family == AF_INET6) {
- memcpy(&daddr6, cur->ai_addr, sizeof(daddr6));
- daddr6.sin6_port = htons(dest_port);
- have_ipv6 = 1;
- }
- cur = cur->ai_next;
- }
- if (addrs)
- freeaddrinfo(addrs);
-
- if (do_ipv6 && hints.ai_family != AF_INET6) {
- hints.ai_family = AF_INET6;
- goto retry;
- }
-
- do_ipv4 &= have_ipv4;
- do_ipv6 &= have_ipv6;
-}
-
-static void do_listen(int family, void *addr, int alen)
-{
- int fd, type;
-
- type = cfg_proto == SOCK_RAW ? SOCK_DGRAM : cfg_proto;
-
- fd = socket(family, type, 0);
- if (fd == -1)
- error(1, errno, "socket rx");
-
- if (bind(fd, addr, alen))
- error(1, errno, "bind rx");
-
- if (type == SOCK_STREAM && listen(fd, 10))
- error(1, errno, "listen rx");
-
- /* leave fd open, will be closed on process exit.
- * this enables connect() to succeed and avoids icmp replies
- */
-}
-
-static void do_main(int family)
-{
- fprintf(stderr, "family: %s %s\n",
- family == PF_INET ? "INET" : "INET6",
- cfg_use_pf_packet ? "(PF_PACKET)" : "");
-
- fprintf(stderr, "test SND\n");
- do_test(family, SOF_TIMESTAMPING_TX_SOFTWARE);
-
- fprintf(stderr, "test ENQ\n");
- do_test(family, SOF_TIMESTAMPING_TX_SCHED);
-
- fprintf(stderr, "test ENQ + SND\n");
- do_test(family, SOF_TIMESTAMPING_TX_SCHED |
- SOF_TIMESTAMPING_TX_SOFTWARE);
-
- if (cfg_proto == SOCK_STREAM) {
- fprintf(stderr, "\ntest ACK\n");
- do_test(family, SOF_TIMESTAMPING_TX_ACK);
-
- fprintf(stderr, "\ntest SND + ACK\n");
- do_test(family, SOF_TIMESTAMPING_TX_SOFTWARE |
- SOF_TIMESTAMPING_TX_ACK);
-
- fprintf(stderr, "\ntest ENQ + SND + ACK\n");
- do_test(family, SOF_TIMESTAMPING_TX_SCHED |
- SOF_TIMESTAMPING_TX_SOFTWARE |
- SOF_TIMESTAMPING_TX_ACK);
- }
-}
-
-const char *sock_names[] = { NULL, "TCP", "UDP", "RAW" };
-
-int main(int argc, char **argv)
-{
- if (argc == 1)
- usage(argv[0]);
-
- parse_opt(argc, argv);
- resolve_hostname(argv[argc - 1]);
-
- fprintf(stderr, "protocol: %s\n", sock_names[cfg_proto]);
- fprintf(stderr, "payload: %u\n", cfg_payload_len);
- fprintf(stderr, "server port: %u\n", dest_port);
- fprintf(stderr, "\n");
-
- if (do_ipv4) {
- if (cfg_do_listen)
- do_listen(PF_INET, &daddr, sizeof(daddr));
- do_main(PF_INET);
- }
-
- if (do_ipv6) {
- if (cfg_do_listen)
- do_listen(PF_INET6, &daddr6, sizeof(daddr6));
- do_main(PF_INET6);
- }
-
- return test_failed;
-}
diff --git a/tools/testing/selftests/networking/timestamping/txtimestamp.sh b/tools/testing/selftests/networking/timestamping/txtimestamp.sh
deleted file mode 100755
index 70a8cda7fd53..000000000000
--- a/tools/testing/selftests/networking/timestamping/txtimestamp.sh
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/bin/bash
-# SPDX-License-Identifier: GPL-2.0
-#
-# Send packets with transmit timestamps over loopback with netem
-# Verify that timestamps correspond to netem delay
-
-set -e
-
-setup() {
- # set 1ms delay on lo egress
- tc qdisc add dev lo root netem delay 1ms
-
- # set 2ms delay on ifb0 egress
- modprobe ifb
- ip link add ifb_netem0 type ifb
- ip link set dev ifb_netem0 up
- tc qdisc add dev ifb_netem0 root netem delay 2ms
-
- # redirect lo ingress through ifb0 egress
- tc qdisc add dev lo handle ffff: ingress
- tc filter add dev lo parent ffff: \
- u32 match mark 0 0xffff \
- action mirred egress redirect dev ifb_netem0
-}
-
-run_test_v4v6() {
- # SND will be delayed 1000us
- # ACK will be delayed 6000us: 1 + 2 ms round-trip
- local -r args="$@ -v 1000 -V 6000"
-
- ./txtimestamp ${args} -4 -L 127.0.0.1
- ./txtimestamp ${args} -6 -L ::1
-}
-
-run_test_tcpudpraw() {
- local -r args=$@
-
- run_test_v4v6 ${args} # tcp
- run_test_v4v6 ${args} -u # udp
- run_test_v4v6 ${args} -r # raw
- run_test_v4v6 ${args} -R # raw (IPPROTO_RAW)
- run_test_v4v6 ${args} -P # pf_packet
-}
-
-run_test_all() {
- setup
- run_test_tcpudpraw # setsockopt
- run_test_tcpudpraw -C # cmsg
- run_test_tcpudpraw -n # timestamp w/o data
- echo "OK. All tests passed"
-}
-
-run_test_one() {
- setup
- ./txtimestamp $@
-}
-
-usage() {
- echo "Usage: $0 [ -r | --run ] <txtimestamp args> | [ -h | --help ]"
- echo " (no args) Run all tests"
- echo " -r|--run Run an individual test with arguments"
- echo " -h|--help Help"
-}
-
-main() {
- if [[ $# -eq 0 ]]; then
- run_test_all
- else
- if [[ "$1" = "-r" || "$1" == "--run" ]]; then
- shift
- run_test_one $@
- else
- usage
- fi
- fi
-}
-
-if [[ "$(ip netns identify)" == "root" ]]; then
- ../../net/in_netns.sh $0 $@
-else
- main $@
-fi