Commit 9669fffc authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

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 8203e2d8
("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: fb420d5d ("tcp/fq: move back to CLOCK_MONOTONIC")
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Reported-by: default avatarThomas Bartschies <Thomas.Bartschies@cvk.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 63158ac0
...@@ -33,6 +33,7 @@ static int nf_br_ip_fragment(struct net *net, struct sock *sk, ...@@ -33,6 +33,7 @@ static int nf_br_ip_fragment(struct net *net, struct sock *sk,
{ {
int frag_max_size = BR_INPUT_SKB_CB(skb)->frag_max_size; int frag_max_size = BR_INPUT_SKB_CB(skb)->frag_max_size;
unsigned int hlen, ll_rs, mtu; unsigned int hlen, ll_rs, mtu;
ktime_t tstamp = skb->tstamp;
struct ip_frag_state state; struct ip_frag_state state;
struct iphdr *iph; struct iphdr *iph;
int err; int err;
...@@ -80,6 +81,7 @@ static int nf_br_ip_fragment(struct net *net, struct sock *sk, ...@@ -80,6 +81,7 @@ static int nf_br_ip_fragment(struct net *net, struct sock *sk,
if (iter.frag) if (iter.frag)
ip_fraglist_prepare(skb, &iter); ip_fraglist_prepare(skb, &iter);
skb->tstamp = tstamp;
err = output(net, sk, data, skb); err = output(net, sk, data, skb);
if (err || !iter.frag) if (err || !iter.frag)
break; break;
...@@ -104,6 +106,7 @@ static int nf_br_ip_fragment(struct net *net, struct sock *sk, ...@@ -104,6 +106,7 @@ static int nf_br_ip_fragment(struct net *net, struct sock *sk,
goto blackhole; goto blackhole;
} }
skb2->tstamp = tstamp;
err = output(net, sk, data, skb2); err = output(net, sk, data, skb2);
if (err) if (err)
goto blackhole; goto blackhole;
......
...@@ -771,6 +771,7 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, ...@@ -771,6 +771,7 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
struct rtable *rt = skb_rtable(skb); struct rtable *rt = skb_rtable(skb);
unsigned int mtu, hlen, ll_rs; unsigned int mtu, hlen, ll_rs;
struct ip_fraglist_iter iter; struct ip_fraglist_iter iter;
ktime_t tstamp = skb->tstamp;
struct ip_frag_state state; struct ip_frag_state state;
int err = 0; int err = 0;
...@@ -846,6 +847,7 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, ...@@ -846,6 +847,7 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
ip_fraglist_prepare(skb, &iter); ip_fraglist_prepare(skb, &iter);
} }
skb->tstamp = tstamp;
err = output(net, sk, skb); err = output(net, sk, skb);
if (!err) if (!err)
...@@ -900,6 +902,7 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, ...@@ -900,6 +902,7 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
/* /*
* Put this fragment into the sending queue. * Put this fragment into the sending queue.
*/ */
skb2->tstamp = tstamp;
err = output(net, sk, skb2); err = output(net, sk, skb2);
if (err) if (err)
goto fail; goto fail;
......
...@@ -768,6 +768,7 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, ...@@ -768,6 +768,7 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
inet6_sk(skb->sk) : NULL; inet6_sk(skb->sk) : NULL;
struct ip6_frag_state state; struct ip6_frag_state state;
unsigned int mtu, hlen, nexthdr_offset; unsigned int mtu, hlen, nexthdr_offset;
ktime_t tstamp = skb->tstamp;
int hroom, err = 0; int hroom, err = 0;
__be32 frag_id; __be32 frag_id;
u8 *prevhdr, nexthdr = 0; u8 *prevhdr, nexthdr = 0;
...@@ -855,6 +856,7 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, ...@@ -855,6 +856,7 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
if (iter.frag) if (iter.frag)
ip6_fraglist_prepare(skb, &iter); ip6_fraglist_prepare(skb, &iter);
skb->tstamp = tstamp;
err = output(net, sk, skb); err = output(net, sk, skb);
if (!err) if (!err)
IP6_INC_STATS(net, ip6_dst_idev(&rt->dst), IP6_INC_STATS(net, ip6_dst_idev(&rt->dst),
...@@ -913,6 +915,7 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, ...@@ -913,6 +915,7 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
/* /*
* Put this fragment into the sending queue. * Put this fragment into the sending queue.
*/ */
frag->tstamp = tstamp;
err = output(net, sk, frag); err = output(net, sk, frag);
if (err) if (err)
goto fail; goto fail;
......
...@@ -119,6 +119,7 @@ int br_ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, ...@@ -119,6 +119,7 @@ int br_ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
struct sk_buff *)) struct sk_buff *))
{ {
int frag_max_size = BR_INPUT_SKB_CB(skb)->frag_max_size; int frag_max_size = BR_INPUT_SKB_CB(skb)->frag_max_size;
ktime_t tstamp = skb->tstamp;
struct ip6_frag_state state; struct ip6_frag_state state;
u8 *prevhdr, nexthdr = 0; u8 *prevhdr, nexthdr = 0;
unsigned int mtu, hlen; unsigned int mtu, hlen;
...@@ -183,6 +184,7 @@ int br_ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, ...@@ -183,6 +184,7 @@ int br_ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
if (iter.frag) if (iter.frag)
ip6_fraglist_prepare(skb, &iter); ip6_fraglist_prepare(skb, &iter);
skb->tstamp = tstamp;
err = output(net, sk, data, skb); err = output(net, sk, data, skb);
if (err || !iter.frag) if (err || !iter.frag)
break; break;
...@@ -215,6 +217,7 @@ int br_ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, ...@@ -215,6 +217,7 @@ int br_ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
goto blackhole; goto blackhole;
} }
skb2->tstamp = tstamp;
err = output(net, sk, data, skb2); err = output(net, sk, data, skb2);
if (err) if (err)
goto blackhole; goto blackhole;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment