net-timestamp: TCP timestamping
[firefly-linux-kernel-4.4.55.git] / net / ipv4 / tcp_offload.c
index 4e86c59ec7f7f07fe06c6db20d17851da6f1563f..f597119fc4e74525bbe8f77a23a9855be958a2f4 100644 (file)
 #include <net/tcp.h>
 #include <net/protocol.h>
 
+void tcp_gso_tstamp(struct sk_buff *skb, unsigned int ts_seq, unsigned int seq,
+                   unsigned int mss)
+{
+       while (skb) {
+               if (ts_seq < (__u64) seq + mss) {
+                       skb_shinfo(skb)->tx_flags = SKBTX_SW_TSTAMP;
+                       skb_shinfo(skb)->tskey = ts_seq;
+                       return;
+               }
+
+               skb = skb->next;
+               seq += mss;
+       }
+}
+
 struct sk_buff *tcp_gso_segment(struct sk_buff *skb,
                                netdev_features_t features)
 {
@@ -91,6 +106,9 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb,
        th = tcp_hdr(skb);
        seq = ntohl(th->seq);
 
+       if (unlikely(skb_shinfo(gso_skb)->tx_flags & SKBTX_SW_TSTAMP))
+               tcp_gso_tstamp(segs, skb_shinfo(gso_skb)->tskey, seq, mss);
+
        newcheck = ~csum_fold((__force __wsum)((__force u32)th->check +
                                               (__force u32)delta));
 
@@ -309,7 +327,7 @@ static int tcp4_gro_complete(struct sk_buff *skb, int thoff)
 
        th->check = ~tcp_v4_check(skb->len - thoff, iph->saddr,
                                  iph->daddr, 0);
-       skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
+       skb_shinfo(skb)->gso_type |= SKB_GSO_TCPV4;
 
        return tcp_gro_complete(skb);
 }