Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 49ca0d8b authored by Willem de Bruijn's avatar Willem de Bruijn Committed by David S. Miller
Browse files

net-timestamp: no-payload option



Add timestamping option SOF_TIMESTAMPING_OPT_TSONLY. For transmit
timestamps, this loops timestamps on top of empty packets.

Doing so reduces the pressure on SO_RCVBUF. Payload inspection and
cmsg reception (aside from timestamps) are no longer possible. This
works together with a follow on patch that allows administrators to
only allow tx timestamping if it does not loop payload or metadata.

Signed-off-by: default avatarWillem de Bruijn <willemb@google.com>

----

Changes (rfc -> v1)
  - add documentation
  - remove unnecessary skb->len test (thanks to Richard Cochran)
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9766e97a
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -162,6 +162,27 @@ SOF_TIMESTAMPING_OPT_CMSG:
  option IP_PKTINFO simultaneously.


SOF_TIMESTAMPING_OPT_TSONLY:

  Applies to transmit timestamps only. Makes the kernel return the
  timestamp as a cmsg alongside an empty packet, as opposed to
  alongside the original packet. This reduces the amount of memory
  charged to the socket's receive budget (SO_RCVBUF) and delivers
  the timestamp even if sysctl net.core.tstamp_allow_data is 0.
  This option disables SOF_TIMESTAMPING_OPT_CMSG.


New applications are encouraged to pass SOF_TIMESTAMPING_OPT_ID to
disambiguate timestamps and SOF_TIMESTAMPING_OPT_TSONLY to operate
regardless of the setting of sysctl net.core.tstamp_allow_data.

An exception is when a process needs additional cmsg data, for
instance SOL_IP/IP_PKTINFO to detect the egress network interface.
Then pass option SOF_TIMESTAMPING_OPT_CMSG. This option depends on
having access to the contents of the original packet, so cannot be
combined with SOF_TIMESTAMPING_OPT_TSONLY.


1.4 Bytestream Timestamps

The SO_TIMESTAMPING interface supports timestamping of bytes in a
+2 −1
Original line number Diff line number Diff line
@@ -24,8 +24,9 @@ enum {
	SOF_TIMESTAMPING_TX_SCHED = (1<<8),
	SOF_TIMESTAMPING_TX_ACK = (1<<9),
	SOF_TIMESTAMPING_OPT_CMSG = (1<<10),
	SOF_TIMESTAMPING_OPT_TSONLY = (1<<11),

	SOF_TIMESTAMPING_LAST = SOF_TIMESTAMPING_OPT_CMSG,
	SOF_TIMESTAMPING_LAST = SOF_TIMESTAMPING_OPT_TSONLY,
	SOF_TIMESTAMPING_MASK = (SOF_TIMESTAMPING_LAST - 1) |
				 SOF_TIMESTAMPING_LAST
};
+14 −5
Original line number Diff line number Diff line
@@ -3710,19 +3710,28 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb,
		     struct sock *sk, int tstype)
{
	struct sk_buff *skb;
	bool tsonly = sk->sk_tsflags & SOF_TIMESTAMPING_OPT_TSONLY;

	if (!sk)
		return;

	if (hwtstamps)
		*skb_hwtstamps(orig_skb) = *hwtstamps;
	if (tsonly)
		skb = alloc_skb(0, GFP_ATOMIC);
	else
		orig_skb->tstamp = ktime_get_real();

		skb = skb_clone(orig_skb, GFP_ATOMIC);
	if (!skb)
		return;

	if (tsonly) {
		skb_shinfo(skb)->tx_flags = skb_shinfo(orig_skb)->tx_flags;
		skb_shinfo(skb)->tskey = skb_shinfo(orig_skb)->tskey;
	}

	if (hwtstamps)
		*skb_hwtstamps(skb) = *hwtstamps;
	else
		skb->tstamp = ktime_get_real();

	__skb_complete_tx_timestamp(skb, sk, tstype);
}
EXPORT_SYMBOL_GPL(__skb_tstamp_tx);
+4 −3
Original line number Diff line number Diff line
@@ -483,7 +483,7 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)

	serr = SKB_EXT_ERR(skb);

	if (sin) {
	if (sin && skb->len) {
		sin->sin_family = AF_INET;
		sin->sin_addr.s_addr = *(__be32 *)(skb_network_header(skb) +
						   serr->addr_offset);
@@ -496,8 +496,9 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
	sin = &errhdr.offender;
	memset(sin, 0, sizeof(*sin));

	if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP ||
	    ipv4_pktinfo_prepare_errqueue(sk, skb, serr->ee.ee_origin)) {
	if (skb->len &&
	    (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP ||
	     ipv4_pktinfo_prepare_errqueue(sk, skb, serr->ee.ee_origin))) {
		sin->sin_family = AF_INET;
		sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
		if (inet_sk(sk)->cmsg_flags)
+2 −3
Original line number Diff line number Diff line
@@ -369,7 +369,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)

	serr = SKB_EXT_ERR(skb);

	if (sin) {
	if (sin && skb->len) {
		const unsigned char *nh = skb_network_header(skb);
		sin->sin6_family = AF_INET6;
		sin->sin6_flowinfo = 0;
@@ -394,8 +394,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
	memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err));
	sin = &errhdr.offender;
	memset(sin, 0, sizeof(*sin));

	if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) {
	if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL && skb->len) {
		sin->sin6_family = AF_INET6;
		if (np->rxopt.all) {
			if (serr->ee.ee_origin != SO_EE_ORIGIN_ICMP &&
Loading