Subject: [PATCH net-next v2 00/12] net-timestamp: bpf extension to equip applications transparently

From: Jason Xing <[email-masked]>
Date: Sat, 12 Oct 2024 12:06:39 +0800

From: Jason Xing <[email-masked]>

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. My feeling is BPF is a good place to provide
a way to add timestamping by administrators, without having to rebuild
applications. 

This approach mostly relies on existing SO_TIMESTAMPING feature, users
only needs to pass certain flags through bpf_setsocktop() to a separate
tsflags. For TX timestamps, they will be printed during generation
phase. For RX timestamps, we will 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.

In this series, I only support TCP protocol which is widely used in
SO_TIMESTAMPING feature.

---
V2
Link: https://lore.kernel.org/all/[email-masked]/
1. Introduce tsflag requestors so that we are able to extend more in the
future. Besides, it enables TX flags for bpf extension feature separately
without breaking users. It is suggested by Vadim Fedorenko.
2. introduce a static key to control the whole feature. (Willem)
3. Open the gate of bpf_setsockopt for the SO_TIMESTAMPING feature in
some TX/RX cases, not all the cases.

Note:
The main concern we've discussion in V1 thread is how to deal with the
applications using SO_TIMESTAMPING feature? In this series, I allow both
cases to happen at the same time, which indicates that even one
applications setting SO_TIMESTAMPING can still be traced through BPF
program. Please see patch [04/12].

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 flags;

	switch (op) {
	//case BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB:
	case BPF_SOCK_OPS_TCP_CONNECT_CB:
	case BPF_SOCK_OPS_PASSIVE_ESTABLISHED_CB:
		flags = SOF_TIMESTAMPING_RX_SOFTWARE |
			SOF_TIMESTAMPING_TX_SCHED | SOF_TIMESTAMPING_TX_ACK | SOF_TIMESTAMPING_TX_SOFTWARE |
			SOF_TIMESTAMPING_OPT_ID | SOF_TIMESTAMPING_OPT_ID_TCP;
		bpf_setsockopt(skops, SOL_SOCKET, SO_TIMESTAMPING, &flags, sizeof(flags));
		bpf_sock_ops_cb_flags_set(skops, BPF_SOCK_OPS_TX_TIMESTAMPING_OPT_CB_FLAG|BPF_SOCK_OPS_RX_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 (12):
  net-timestamp: introduce socket tsflag requestors
  net-timestamp: open gate for bpf_setsockopt
  net-timestamp: reorganize in skb_tstamp_tx_output()
  net-timestamp: add static key to control the whole bpf extension
  net-timestamp: add bpf infrastructure to allow exposing timestamp
    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: add tx OPT_ID_TCP support for bpf case
  net-timestamp: make bpf for tx timestamp work
  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/ip.h               |   2 +-
 include/net/sock.h             |  19 ++++--
 include/net/tcp.h              |  16 +++++-
 include/uapi/linux/bpf.h       |  28 ++++++++-
 net/can/j1939/socket.c         |   2 +-
 net/core/filter.c              |  39 +++++++++++++
 net/core/skbuff.c              | 102 ++++++++++++++++++++++++++++++---
 net/core/sock.c                |  68 +++++++++++++++-------
 net/ipv4/ip_output.c           |   2 +-
 net/ipv4/ip_sockglue.c         |   2 +-
 net/ipv4/tcp.c                 |  60 ++++++++++++++++++-
 net/ipv6/ip6_output.c          |   2 +-
 net/ipv6/ping.c                |   2 +-
 net/ipv6/raw.c                 |   2 +-
 net/ipv6/udp.c                 |   2 +-
 net/sctp/socket.c              |   2 +-
 net/socket.c                   |   4 +-
 tools/include/uapi/linux/bpf.h |  28 ++++++++-
 19 files changed, 333 insertions(+), 51 deletions(-)

-- 
2.37.3