Skip to content

Commit

Permalink
net: ensure correct skb->tstamp in various fragmenters
Browse files Browse the repository at this point in the history
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 8203e2d
("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: fb420d5 ("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>
  • Loading branch information
Eric Dumazet authored and davem330 committed Oct 18, 2019
1 parent 63158ac commit 9669fff
Show file tree
Hide file tree
Showing 4 changed files with 12 additions and 0 deletions.
3 changes: 3 additions & 0 deletions net/bridge/netfilter/nf_conntrack_bridge.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
unsigned int hlen, ll_rs, mtu;
ktime_t tstamp = skb->tstamp;
struct ip_frag_state state;
struct iphdr *iph;
int err;
Expand Down Expand Up @@ -80,6 +81,7 @@ static int nf_br_ip_fragment(struct net *net, struct sock *sk,
if (iter.frag)
ip_fraglist_prepare(skb, &iter);

skb->tstamp = tstamp;
err = output(net, sk, data, skb);
if (err || !iter.frag)
break;
Expand All @@ -104,6 +106,7 @@ static int nf_br_ip_fragment(struct net *net, struct sock *sk,
goto blackhole;
}

skb2->tstamp = tstamp;
err = output(net, sk, data, skb2);
if (err)
goto blackhole;
Expand Down
3 changes: 3 additions & 0 deletions net/ipv4/ip_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -771,6 +771,7 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
struct rtable *rt = skb_rtable(skb);
unsigned int mtu, hlen, ll_rs;
struct ip_fraglist_iter iter;
ktime_t tstamp = skb->tstamp;
struct ip_frag_state state;
int err = 0;

Expand Down Expand Up @@ -846,6 +847,7 @@ int ip_do_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
ip_fraglist_prepare(skb, &iter);
}

skb->tstamp = tstamp;
err = output(net, sk, skb);

if (!err)
Expand Down Expand Up @@ -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.
*/
skb2->tstamp = tstamp;
err = output(net, sk, skb2);
if (err)
goto fail;
Expand Down
3 changes: 3 additions & 0 deletions net/ipv6/ip6_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -768,6 +768,7 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
inet6_sk(skb->sk) : NULL;
struct ip6_frag_state state;
unsigned int mtu, hlen, nexthdr_offset;
ktime_t tstamp = skb->tstamp;
int hroom, err = 0;
__be32 frag_id;
u8 *prevhdr, nexthdr = 0;
Expand Down Expand Up @@ -855,6 +856,7 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
if (iter.frag)
ip6_fraglist_prepare(skb, &iter);

skb->tstamp = tstamp;
err = output(net, sk, skb);
if (!err)
IP6_INC_STATS(net, ip6_dst_idev(&rt->dst),
Expand Down Expand Up @@ -913,6 +915,7 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
/*
* Put this fragment into the sending queue.
*/
frag->tstamp = tstamp;
err = output(net, sk, frag);
if (err)
goto fail;
Expand Down
3 changes: 3 additions & 0 deletions net/ipv6/netfilter.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ int br_ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
struct sk_buff *))
{
int frag_max_size = BR_INPUT_SKB_CB(skb)->frag_max_size;
ktime_t tstamp = skb->tstamp;
struct ip6_frag_state state;
u8 *prevhdr, nexthdr = 0;
unsigned int mtu, hlen;
Expand Down Expand Up @@ -183,6 +184,7 @@ int br_ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
if (iter.frag)
ip6_fraglist_prepare(skb, &iter);

skb->tstamp = tstamp;
err = output(net, sk, data, skb);
if (err || !iter.frag)
break;
Expand Down Expand Up @@ -215,6 +217,7 @@ int br_ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
goto blackhole;
}

skb2->tstamp = tstamp;
err = output(net, sk, data, skb2);
if (err)
goto blackhole;
Expand Down

0 comments on commit 9669fff

Please sign in to comment.