From: Jason Xing <kernelxing@xxxxxxxxxxx> A few weeks ago, I planned to extend SO_TIMESTMAMPING feature by using tracepoint to print information (say, tstamp) so that we can transparently equip applications with this feature and require no modification in user side. Later, we discussed at netconf and agreed that we can use bpf for better extension, which is mainly suggested by John Fastabend and Willem de Bruijn. Many thanks here! So I post this series to see if we have a better solution to extend. This approach relies on existing SO_TIMESTAMPING feature, for tx path, users only needs to pass certain flags through bpf program to make sure the last skb from each sendmsg() has timestamp related controlled flag. For rx path, we have to use bpf_setsockopt() to set the sk->sk_tsflags and wait for the moment when recvmsg() is called. After this series, we could step by step implement more advanced functions/flags already in SO_TIMESTAMPING feature for bpf extension. Here is the test output: 1) receive path iperf3-987305 [008] ...11 179955.200990: bpf_trace_printk: rx: port: 5201:55192, swtimestamp: 1728167973,670426346, hwtimestamp: 0,0 2) xmit path iperf3-19765 [013] ...11 2021.329602: bpf_trace_printk: tx: port: 47528:5201, key: 1036, timestamp: 1728357067,436678584 iperf3-19765 [013] b..11 2021.329611: bpf_trace_printk: tx: port: 47528:5201, key: 1036, timestamp: 1728357067,436689976 iperf3-19765 [013] ...11 2021.329622: bpf_trace_printk: tx: port: 47528:5201, key: 1036, timestamp: 1728357067,436700739 Here is the full bpf program: #include <linux/bpf.h> #include <bpf/bpf_helpers.h> #include <bpf/bpf_endian.h> #include <uapi/linux/net_tstamp.h> int _version SEC("version") = 1; char _license[] SEC("license") = "GPL"; # define SO_TIMESTAMPING 37 __section("sockops") int set_initial_rto(struct bpf_sock_ops *skops) { int op = (int) skops->op; u32 sport = 0, dport = 0; int rcv_flags; switch (op) { case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB: case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB: rcv_flags = SOF_TIMESTAMPING_RX_SOFTWARE; bpf_setsockopt(skops, SOL_SOCKET, SO_TIMESTAMPING, &rcv_flags, sizeof(rcv_flags)); bpf_sock_ops_cb_flags_set(skops, BPF_SOCK_OPS_RX_TIMESTAMPING_OPT_CB_FLAG); break; case BPF_SOCK_OPS_TX_TS_OPT_CB: skops->reply = SOF_TIMESTAMPING_TX_SCHED|SOF_TIMESTAMPING_TX_ACK|SOF_TIMESTAMPING_TX_SOFTWARE| SOF_TIMESTAMPING_OPT_ID|SOF_TIMESTAMPING_OPT_ID_TCP; bpf_sock_ops_cb_flags_set(skops, BPF_SOCK_OPS_TX_TIMESTAMPING_OPT_CB_FLAG); break; case BPF_SOCK_OPS_TS_SCHED_OPT_CB: case BPF_SOCK_OPS_TS_SW_OPT_CB: case BPF_SOCK_OPS_TS_ACK_OPT_CB: dport = bpf_ntohl(skops->remote_port); sport = skops->local_port; bpf_printk("tx: port: %u:%u, key: %u, timestamp: %u,%u\n", sport, dport, skops->args[0], skops->args[1], skops->args[2]); break; case BPF_SOCK_OPS_TS_RX_OPT_CB: dport = bpf_ntohl(skops->remote_port); sport = skops->local_port; bpf_printk("rx: port: %u:%u, swtimestamp: %u,%u, hwtimestamp: %u,%u\n", sport, dport, skops->args[0], skops->args[1], skops->args[2], skops->args[3]); break; } return 1; } Jason Xing (9): net-timestamp: add bpf infrastructure to allow exposing more information later net-timestamp: introduce TS_SCHED_OPT_CB to generate dev xmit timestamp net-timestamp: introduce TS_SW_OPT_CB to generate driver timestamp net-timestamp: introduce TS_ACK_OPT_CB to generate tcp acked timestamp net-timestamp: ready to turn on the button to generate tx timestamps net-timestamp: add tx OPT_ID_TCP support for bpf case net-timestamp: open gate for bpf_setsockopt net-timestamp: add bpf framework for rx timestamps net-timestamp: add bpf support for rx software/hardware timestamp include/linux/tcp.h | 2 +- include/net/tcp.h | 14 ++++++ include/uapi/linux/bpf.h | 36 ++++++++++++++- net/core/filter.c | 3 ++ net/core/skbuff.c | 51 +++++++++++++++++++++ net/ipv4/tcp.c | 81 ++++++++++++++++++++++++++++++++-- tools/include/uapi/linux/bpf.h | 36 ++++++++++++++- 7 files changed, 217 insertions(+), 6 deletions(-) -- 2.37.3