tools/testing/selftests/bpf/prog_tests/net_timestamping.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/bpf/prog_tests/net_timestamping.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/bpf/prog_tests/net_timestamping.c
Extension
.c
Size
5847 bytes
Lines
240
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

#include <linux/net_tstamp.h>
#include <sys/time.h>
#include <linux/errqueue.h>
#include "test_progs.h"
#include "network_helpers.h"
#include "net_timestamping.skel.h"

#define CG_NAME "/net-timestamping-test"
#define NSEC_PER_SEC    1000000000LL

static const char addr4_str[] = "127.0.0.1";
static const char addr6_str[] = "::1";
static struct net_timestamping *skel;
static const int cfg_payload_len = 30;
static struct timespec usr_ts;
static u64 delay_tolerance_nsec = 10000000000; /* 10 seconds */
int SK_TS_SCHED;
int SK_TS_TXSW;
int SK_TS_ACK;

static int64_t timespec_to_ns64(struct timespec *ts)
{
	return ts->tv_sec * NSEC_PER_SEC + ts->tv_nsec;
}

static void validate_key(int tskey, int tstype)
{
	static int expected_tskey = -1;

	if (tstype == SCM_TSTAMP_SCHED)
		expected_tskey = cfg_payload_len - 1;

	ASSERT_EQ(expected_tskey, tskey, "tskey mismatch");

	expected_tskey = tskey;
}

static void validate_timestamp(struct timespec *cur, struct timespec *prev)
{
	int64_t cur_ns, prev_ns;

	cur_ns = timespec_to_ns64(cur);
	prev_ns = timespec_to_ns64(prev);

	ASSERT_LT(cur_ns - prev_ns, delay_tolerance_nsec, "latency");
}

static void test_socket_timestamp(struct scm_timestamping *tss, int tstype,
				  int tskey)
{
	static struct timespec prev_ts;

	validate_key(tskey, tstype);

	switch (tstype) {
	case SCM_TSTAMP_SCHED:
		validate_timestamp(&tss->ts[0], &usr_ts);
		SK_TS_SCHED += 1;
		break;
	case SCM_TSTAMP_SND:
		validate_timestamp(&tss->ts[0], &prev_ts);
		SK_TS_TXSW += 1;
		break;
	case SCM_TSTAMP_ACK:
		validate_timestamp(&tss->ts[0], &prev_ts);
		SK_TS_ACK += 1;
		break;
	}

	prev_ts = tss->ts[0];
}

static void test_recv_errmsg_cmsg(struct msghdr *msg)
{
	struct sock_extended_err *serr = NULL;
	struct scm_timestamping *tss = NULL;
	struct cmsghdr *cm;

	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)) {

Annotation

Implementation Notes