History

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: Willem de Bruijn <willemb@google.com> ---- Changes (rfc -> v1) - add documentation - remove unnecessary skb->len test (thanks to Richard Cochran) Signed-off-by: David S. Miller <davem@davemloft.net>

Willem de Bruijn committed 11 years ago

Commit 49ca0d81 parent 9766e976 files · +48 −12Browse files

Unified · Split

6 files
  1. Documentation/networking/timestamping.txt +21 −0
  2. include/uapi/linux/net_tstamp.h +2 −1
  3. net/core/skbuff.c +14 −5
  4. net/ipv4/ip_sockglue.c +4 −3
  5. net/ipv6/datagram.c +2 −3
  6. net/rxrpc/ar-error.c +5 −0
Documentation/networking/timestamping.txt+21−0
@@ -162,6 +162,27 @@ SOF_TIMESTAMPING_OPT_CMSG: · 161 unmodified lines
162162 option IP_PKTINFO simultaneously.
163163
164164
165+SOF_TIMESTAMPING_OPT_TSONLY:
166+
167+ Applies to transmit timestamps only. Makes the kernel return the
168+ timestamp as a cmsg alongside an empty packet, as opposed to
169+ alongside the original packet. This reduces the amount of memory
170+ charged to the socket's receive budget (SO_RCVBUF) and delivers
171+ the timestamp even if sysctl net.core.tstamp_allow_data is 0.
172+ This option disables SOF_TIMESTAMPING_OPT_CMSG.
173+
174+
175+New applications are encouraged to pass SOF_TIMESTAMPING_OPT_ID to
176+disambiguate timestamps and SOF_TIMESTAMPING_OPT_TSONLY to operate
177+regardless of the setting of sysctl net.core.tstamp_allow_data.
178+
179+An exception is when a process needs additional cmsg data, for
180+instance SOL_IP/IP_PKTINFO to detect the egress network interface.
181+Then pass option SOF_TIMESTAMPING_OPT_CMSG. This option depends on
182+having access to the contents of the original packet, so cannot be
183+combined with SOF_TIMESTAMPING_OPT_TSONLY.
184+
185+
165186 1.4 Bytestream Timestamps
166187
167188 The SO_TIMESTAMPING interface supports timestamping of bytes in a
include/uapi/linux/net_tstamp.h+2−1
@@ -24,8 +24,9 @@ enum { · 23 unmodified lines
2424 SOF_TIMESTAMPING_TX_SCHED = (1<<8),
2525 SOF_TIMESTAMPING_TX_ACK = (1<<9),
2626 SOF_TIMESTAMPING_OPT_CMSG = (1<<10),
27+ SOF_TIMESTAMPING_OPT_TSONLY = (1<<11),
2728
28− SOF_TIMESTAMPING_LAST = SOF_TIMESTAMPING_OPT_CMSG,
29+ SOF_TIMESTAMPING_LAST = SOF_TIMESTAMPING_OPT_TSONLY,
2930 SOF_TIMESTAMPING_MASK = (SOF_TIMESTAMPING_LAST - 1) |
3031 SOF_TIMESTAMPING_LAST
3132 };
net/core/skbuff.c+14−5
@@ -3710,19 +3710,28 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb, · 3709 unmodified lines
37103710 struct sock *sk, int tstype)
37113711 {
37123712 struct sk_buff *skb;
3713+ bool tsonly = sk->sk_tsflags & SOF_TIMESTAMPING_OPT_TSONLY;
37133714
37143715 if (!sk)
37153716 return;
37163717
3717− if (hwtstamps)
3718− *skb_hwtstamps(orig_skb) = *hwtstamps;
3718+ if (tsonly)
3719+ skb = alloc_skb(0, GFP_ATOMIC);
37193720 else
3720− orig_skb->tstamp = ktime_get_real();
3721−
3722− skb = skb_clone(orig_skb, GFP_ATOMIC);
3721+ skb = skb_clone(orig_skb, GFP_ATOMIC);
37233722 if (!skb)
37243723 return;
37253724
3725+ if (tsonly) {
3726+ skb_shinfo(skb)->tx_flags = skb_shinfo(orig_skb)->tx_flags;
3727+ skb_shinfo(skb)->tskey = skb_shinfo(orig_skb)->tskey;
3728+ }
3729+
3730+ if (hwtstamps)
3731+ *skb_hwtstamps(skb) = *hwtstamps;
3732+ else
3733+ skb->tstamp = ktime_get_real();
3734+
37263735 __skb_complete_tx_timestamp(skb, sk, tstype);
37273736 }
37283737 EXPORT_SYMBOL_GPL(__skb_tstamp_tx);
net/ipv4/ip_sockglue.c+4−3
@@ -483,7 +483,7 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) · 482 unmodified lines
483483
484484 serr = SKB_EXT_ERR(skb);
485485
486− if (sin) {
486+ if (sin && skb->len) {
487487 sin->sin_family = AF_INET;
488488 sin->sin_addr.s_addr = *(__be32 *)(skb_network_header(skb) +
489489 serr->addr_offset);
@@ -496,8 +496,9 @@ int ip_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) · 6 unmodified lines
496496 sin = &errhdr.offender;
497497 memset(sin, 0, sizeof(*sin));
498498
499− if (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP ||
500− ipv4_pktinfo_prepare_errqueue(sk, skb, serr->ee.ee_origin)) {
499+ if (skb->len &&
500+ (serr->ee.ee_origin == SO_EE_ORIGIN_ICMP ||
501+ ipv4_pktinfo_prepare_errqueue(sk, skb, serr->ee.ee_origin))) {
501502 sin->sin_family = AF_INET;
502503 sin->sin_addr.s_addr = ip_hdr(skb)->saddr;
503504 if (inet_sk(sk)->cmsg_flags)
net/ipv6/datagram.c+2−3
@@ -369,7 +369,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) · 368 unmodified lines
369369
370370 serr = SKB_EXT_ERR(skb);
371371
372− if (sin) {
372+ if (sin && skb->len) {
373373 const unsigned char *nh = skb_network_header(skb);
374374 sin->sin6_family = AF_INET6;
375375 sin->sin6_flowinfo = 0;
@@ -394,8 +394,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len) · 18 unmodified lines
394394 memcpy(&errhdr.ee, &serr->ee, sizeof(struct sock_extended_err));
395395 sin = &errhdr.offender;
396396 memset(sin, 0, sizeof(*sin));
397−
398− if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) {
397+ if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL && skb->len) {
399398 sin->sin6_family = AF_INET6;
400399 if (np->rxopt.all) {
401400 if (serr->ee.ee_origin != SO_EE_ORIGIN_ICMP &&
net/rxrpc/ar-error.c+5−0
@@ -42,6 +42,11 @@ void rxrpc_UDP_error_report(struct sock *sk) · 41 unmodified lines
4242 _leave("UDP socket errqueue empty");
4343 return;
4444 }
45+ if (!skb->len) {
46+ _leave("UDP empty message");
47+ kfree_skb(skb);
48+ return;
49+ }
4550
4651 rxrpc_new_skb(skb);
4752