@@ -160,6 +160,7 @@ struct inet_cork {
char priority;
__u16 gso_size;
u64 transmit_time;
+ u64 transmit_hw_time;
u32 mark;
};
@@ -1282,6 +1282,7 @@ static int ip_setup_cork(struct sock *sk, struct inet_cork *cork,
cork->mark = ipc->sockc.mark;
cork->priority = ipc->priority;
cork->transmit_time = ipc->sockc.transmit_time;
+ cork->transmit_hw_time = ipc->sockc.transmit_hw_time;
cork->tx_flags = 0;
sock_tx_timestamp(sk, ipc->sockc.tsflags, &cork->tx_flags);
@@ -1545,6 +1546,7 @@ struct sk_buff *__ip_make_skb(struct sock *sk,
skb->priority = (cork->tos != -1) ? cork->priority: sk->sk_priority;
skb->mark = cork->mark;
skb->tstamp = cork->transmit_time;
+ skb_hwtstamps(skb)->hwtstamp = ns_to_ktime(cork->transmit_hw_time);
/*
* Steal rt from cork.dst to avoid a pair of atomic_inc/atomic_dec
* on dst refcount
@@ -378,6 +378,7 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,
skb->priority = sk->sk_priority;
skb->mark = sockc->mark;
skb->tstamp = sockc->transmit_time;
+ skb_hwtstamps(skb)->hwtstamp = ns_to_ktime(sockc->transmit_hw_time);
skb_dst_set(skb, &rt->dst);
*rtp = NULL;
@@ -1375,6 +1375,7 @@ static int ip6_setup_cork(struct sock *sk, struct inet_cork_full *cork,
cork->base.length = 0;
cork->base.transmit_time = ipc6->sockc.transmit_time;
+ cork->base.transmit_hw_time = ipc6->sockc.transmit_hw_time;
return 0;
}
@@ -1841,6 +1842,7 @@ struct sk_buff *__ip6_make_skb(struct sock *sk,
skb->mark = cork->base.mark;
skb->tstamp = cork->base.transmit_time;
+ skb_hwtstamps(skb)->hwtstamp = ns_to_ktime(cork->base.transmit_hw_time);
skb_dst_set(skb, dst_clone(&rt->dst));
IP6_UPD_PO_STATS(net, rt->rt6i_idev, IPSTATS_MIB_OUT, skb->len);
@@ -648,6 +648,7 @@ static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length,
skb->priority = sk->sk_priority;
skb->mark = sockc->mark;
skb->tstamp = sockc->transmit_time;
+ skb_hwtstamps(skb)->hwtstamp = ns_to_ktime(sockc->transmit_hw_time);
skb_put(skb, length);
skb_reset_network_header(skb);
@@ -1986,6 +1986,7 @@ static int packet_sendmsg_spkt(struct socket *sock, struct msghdr *msg,
skb->priority = sk->sk_priority;
skb->mark = sk->sk_mark;
skb->tstamp = sockc.transmit_time;
+ skb_hwtstamps(skb)->hwtstamp = ns_to_ktime(sockc.transmit_hw_time);
skb_setup_tx_timestamp(skb, sockc.tsflags);
@@ -2500,6 +2501,7 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
skb->priority = po->sk.sk_priority;
skb->mark = po->sk.sk_mark;
skb->tstamp = sockc->transmit_time;
+ skb_hwtstamps(skb)->hwtstamp = ns_to_ktime(sockc->transmit_hw_time);
skb_setup_tx_timestamp(skb, sockc->tsflags);
skb_zcopy_set_nouarg(skb, ph.raw);
@@ -2975,6 +2977,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
skb->priority = sk->sk_priority;
skb->mark = sockc.mark;
skb->tstamp = sockc.transmit_time;
+ skb_hwtstamps(skb)->hwtstamp = ns_to_ktime(sockc.transmit_hw_time);
if (has_vnet_hdr) {
err = virtio_net_hdr_to_skb(skb, &vnet_hdr, vio_le());
Pass TX sending hardware timestamp from the socket layer to a socket's buffer. The TC ETC Qdisc will pass it to the interface network driver. - Add the hardware timestamp to the IP cork, to support the use of IP/UDP with the TX sending hardware timestamp when sending through the TC ETF Qdisc - Pass the TX sending hardware timestamp to a socket's buffer using the hardware timestamp on the socket's buffer shared information. Note: The socket buffer's hardware timestamp is used by the network interface driver to send the actual sending timestamp back to the application. The timestamp is used by the TC ETF before the buffer arrives in the network interface driver. Signed-off-by: Erez Geva <erez.geva.ext@siemens.com> --- include/net/inet_sock.h | 1 + net/ipv4/ip_output.c | 2 ++ net/ipv4/raw.c | 1 + net/ipv6/ip6_output.c | 2 ++ net/ipv6/raw.c | 1 + net/packet/af_packet.c | 3 +++ 6 files changed, 10 insertions(+)