summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2019-10-16 21:00:56 -0400
committerDavid S. Miller <davem@davemloft.net>2019-10-18 13:02:37 -0400
commit9669fffc1415bb0c30e5d2ec98a8e1c3a418cb9c (patch)
tree3abe73fdf43b7a670cc69b6930d07c2683ade0d4
parent63158ac0ba5d5a279999387c86791a09930610aa (diff)
net: ensure correct skb->tstamp in various fragmenters
Thomas found that some forwarded packets would be stuck in FQ packet scheduler because their skb->tstamp contained timestamps far in the future. We thought we addressed this point in commit 8203e2d844d3 ("net: clear skb->tstamp in forwarding paths") but there is still an issue when/if a packet needs to be fragmented. In order to meet EDT requirements, we have to make sure all fragments get the original skb->tstamp. Note that this original skb->tstamp should be zero in forwarding path, but might have a non zero value in output path if user decided so. Fixes: fb420d5d91c1 ("tcp/fq: move back to CLOCK_MONOTONIC") Signed-off-by: Eric Dumazet <edumazet@google.com> Reported-by: Thomas Bartschies <Thomas.Bartschies@cvk.de> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/bridge/netfilter/nf_conntrack_bridge.c3
-rw-r--r--net/ipv4/ip_output.c3
-rw-r--r--net/ipv6/ip6_output.c3
-rw-r--r--net/ipv6/netfilter.c3
4 files changed, 12 insertions, 0 deletions
diff --git a/net/bridge/netfilter/nf_conntrack_bridge.c b/net/bridge/netfilter/nf_conntrack_bridge.c
index 8842798c29e6..506d6141e44e 100644
--- a/net/bridge/netfilter/nf_conntrack_bridge.c
+++ b/net/bridge/netfilter/nf_conntrack_bridge.c
@@ -33,6 +33,7 @@ static int nf_br_ip_fragment(struct net *net, struct sock *sk,
33{ 33{
34 int frag_max_size = BR_INPUT_SKB_CB(skb)->frag_max_size; 34 int frag_max_size = BR_INPUT_SKB_CB(skb)->frag_max_size;
35 unsigned int hlen, ll_rs, mtu; 35 unsigned int hlen, ll_rs, mtu;
36 ktime_t tstamp = skb->tstamp;
36 struct ip_frag_state state; 37 struct ip_frag_state state;
37 struct iphdr *iph; 38 struct iphdr *iph;
38 int err; 39 int err;
@@ -80,6 +81,7 @@ static int nf_br_ip_fragment(struct net *net, struct sock *sk,
80 if (iter.frag) 81 if (iter.frag)
81 ip_fraglist_prepare(skb, &iter); 82 ip_fraglist_prepare(skb, &iter);
82 83
84 skb->tstamp = tstamp;
83 err = output(net, sk, data, skb); 85 err = output(net, sk, data, skb);
84 if (err || !iter.frag) 86 if (err || !iter.frag)
85 break; 87 break;
@@ -104,6 +106,7 @@ slow_path:
104 goto blackhole; 106 goto blackhole;
105 } 107 }
106 108
109 skb2->tstamp = tstamp;
107 err = output(net, sk, data, skb2); 110 err = output(net, sk, data, skb2);
108 if (err) 111 if (err)
109 goto blackhole; 112 goto blackhole;
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 28fca408812c..814b9b8882a0 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -771,6 +771,7 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
771 struct rtable *rt = skb_rtable(skb); 771 struct rtable *rt = skb_rtable(skb);
772 unsigned int mtu, hlen, ll_rs; 772 unsigned int mtu, hlen, ll_rs;
773 struct ip_fraglist_iter iter; 773 struct ip_fraglist_iter iter;
774 ktime_t tstamp = skb->tstamp;
774 struct ip_frag_state state; 775 struct ip_frag_state state;
775 int err = 0; 776 int err = 0;
776 777
@@ -846,6 +847,7 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
846 ip_fraglist_prepare(skb, &iter); 847 ip_fraglist_prepare(skb, &iter);
847 } 848 }
848 849
850 skb->tstamp = tstamp;
849 err = output(net, sk, skb); 851 err = output(net, sk, skb);
850 852
851 if (!err) 853 if (!err)
@@ -900,6 +902,7 @@ slow_path:
900 /* 902 /*
901 * Put this fragment into the sending queue. 903 * Put this fragment into the sending queue.
902 */ 904 */
905 skb2->tstamp = tstamp;
903 err = output(net, sk, skb2); 906 err = output(net, sk, skb2);
904 if (err) 907 if (err)
905 goto fail; 908 goto fail;
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index edadee4a7e76..71827b56c006 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -768,6 +768,7 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
768 inet6_sk(skb->sk) : NULL; 768 inet6_sk(skb->sk) : NULL;
769 struct ip6_frag_state state; 769 struct ip6_frag_state state;
770 unsigned int mtu, hlen, nexthdr_offset; 770 unsigned int mtu, hlen, nexthdr_offset;
771 ktime_t tstamp = skb->tstamp;
771 int hroom, err = 0; 772 int hroom, err = 0;
772 __be32 frag_id; 773 __be32 frag_id;
773 u8 *prevhdr, nexthdr = 0; 774 u8 *prevhdr, nexthdr = 0;
@@ -855,6 +856,7 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
855 if (iter.frag) 856 if (iter.frag)
856 ip6_fraglist_prepare(skb, &iter); 857 ip6_fraglist_prepare(skb, &iter);
857 858
859 skb->tstamp = tstamp;
858 err = output(net, sk, skb); 860 err = output(net, sk, skb);
859 if (!err) 861 if (!err)
860 IP6_INC_STATS(net, ip6_dst_idev(&rt->dst), 862 IP6_INC_STATS(net, ip6_dst_idev(&rt->dst),
@@ -913,6 +915,7 @@ slow_path:
913 /* 915 /*
914 * Put this fragment into the sending queue. 916 * Put this fragment into the sending queue.
915 */ 917 */
918 frag->tstamp = tstamp;
916 err = output(net, sk, frag); 919 err = output(net, sk, frag);
917 if (err) 920 if (err)
918 goto fail; 921 goto fail;
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index a9bff556d3b2..409e79b84a83 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -119,6 +119,7 @@ int br_ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
119 struct sk_buff *)) 119 struct sk_buff *))
120{ 120{
121 int frag_max_size = BR_INPUT_SKB_CB(skb)->frag_max_size; 121 int frag_max_size = BR_INPUT_SKB_CB(skb)->frag_max_size;
122 ktime_t tstamp = skb->tstamp;
122 struct ip6_frag_state state; 123 struct ip6_frag_state state;
123 u8 *prevhdr, nexthdr = 0; 124 u8 *prevhdr, nexthdr = 0;
124 unsigned int mtu, hlen; 125 unsigned int mtu, hlen;
@@ -183,6 +184,7 @@ int br_ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
183 if (iter.frag) 184 if (iter.frag)
184 ip6_fraglist_prepare(skb, &iter); 185 ip6_fraglist_prepare(skb, &iter);
185 186
187 skb->tstamp = tstamp;
186 err = output(net, sk, data, skb); 188 err = output(net, sk, data, skb);
187 if (err || !iter.frag) 189 if (err || !iter.frag)
188 break; 190 break;
@@ -215,6 +217,7 @@ slow_path:
215 goto blackhole; 217 goto blackhole;
216 } 218 }
217 219
220 skb2->tstamp = tstamp;
218 err = output(net, sk, data, skb2); 221 err = output(net, sk, data, skb2);
219 if (err) 222 if (err)
220 goto blackhole; 223 goto blackhole;