2018-11-03 16:57:16

by Yafang Shao

[permalink] [raw]
Subject: [PATCH] tcp: do not update snd_una if it is same with ack_seq

In the slow path, TCP_SKB_SB(skb)->ack_seq may be same with tp->snd_una,
and under this condition we don't need to update the snd_una.

Furthermore, tcp_ack_update_window() is only called in slow path,
so introducing this check won't affect the fast path processing.

By the way, '&' is a little faster than '-', so I replaced after() with
"flag & FLAG_SND_UNA_ADVANCED".

Signed-off-by: Yafang Shao <[email protected]>
---
net/ipv4/tcp_input.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 2868ef2..db5a6b7 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -3376,7 +3376,8 @@ static int tcp_ack_update_window(struct sock *sk, const struct sk_buff *skb, u32
}
}

- tcp_snd_una_update(tp, ack);
+ if (after(ack, tp->snd_una))
+ tcp_snd_una_update(tp, ack);

return flag;
}
@@ -3610,7 +3611,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
if (flag & FLAG_UPDATE_TS_RECENT)
tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);

- if (!(flag & FLAG_SLOWPATH) && after(ack, prior_snd_una)) {
+ if (!(flag & FLAG_SLOWPATH) && flag & FLAG_SND_UNA_ADVANCED) {
/* Window is constant, pure forward advance.
* No more checks are required.
* Note, we use the fact that SND.UNA>=SND.WL2.
--
1.8.3.1



2018-11-03 17:04:42

by Joe Perches

[permalink] [raw]
Subject: Re: [PATCH] tcp: do not update snd_una if it is same with ack_seq

On Sun, 2018-11-04 at 00:54 +0800, Yafang Shao wrote:
> In the slow path, TCP_SKB_SB(skb)->ack_seq may be same with tp->snd_una,
> and under this condition we don't need to update the snd_una.
>
> Furthermore, tcp_ack_update_window() is only called in slow path,
> so introducing this check won't affect the fast path processing.
[]
> diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
[]
> @@ -3610,7 +3611,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
> if (flag & FLAG_UPDATE_TS_RECENT)
> tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
>
> - if (!(flag & FLAG_SLOWPATH) && after(ack, prior_snd_una)) {
> + if (!(flag & FLAG_SLOWPATH) && flag & FLAG_SND_UNA_ADVANCED) {

stylistic nit:

While the precedence is correct in any case,
perhaps adding parentheses around
flag & FLAG_SND_UNA_ADVANCED
would make it more obvious.



2018-11-04 00:43:19

by Eric Dumazet

[permalink] [raw]
Subject: Re: [PATCH] tcp: do not update snd_una if it is same with ack_seq



On 11/03/2018 09:54 AM, Yafang Shao wrote:
> In the slow path, TCP_SKB_SB(skb)->ack_seq may be same with tp->snd_una,
> and under this condition we don't need to update the snd_una.
>
> Furthermore, tcp_ack_update_window() is only called in slow path,
> so introducing this check won't affect the fast path processing.
>
> By the way, '&' is a little faster than '-', so I replaced after() with
> "flag & FLAG_SND_UNA_ADVANCED".
>
> Signed-off-by: Yafang Shao <[email protected]>
> ---
> net/ipv4/tcp_input.c | 5 +++--
> 1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
> index 2868ef2..db5a6b7 100644
> --- a/net/ipv4/tcp_input.c
> +++ b/net/ipv4/tcp_input.c
> @@ -3376,7 +3376,8 @@ static int tcp_ack_update_window(struct sock *sk, const struct sk_buff *skb, u32
> }
> }
>
> - tcp_snd_una_update(tp, ack);
> + if (after(ack, tp->snd_una))
> + tcp_snd_una_update(tp, ack);
>

Adding this after() here is confusing, how ack could be before snd_una ?
That would be a serious bug.

I do not see why another conditional has any gain here.

You are trying to avoid very cheap operations :

u32 delta = ack - tp->snd_una;

tp->bytes_acked += delta;
tp->snd_una = ack;

Maybe the real reason for this patch is not explained in the changelog ?

2018-11-04 01:28:42

by Yafang Shao

[permalink] [raw]
Subject: Re: [PATCH] tcp: do not update snd_una if it is same with ack_seq

On Sun, Nov 4, 2018 at 8:40 AM Eric Dumazet <[email protected]> wrote:
>
>
>
> On 11/03/2018 09:54 AM, Yafang Shao wrote:
> > In the slow path, TCP_SKB_SB(skb)->ack_seq may be same with tp->snd_una,
> > and under this condition we don't need to update the snd_una.
> >
> > Furthermore, tcp_ack_update_window() is only called in slow path,
> > so introducing this check won't affect the fast path processing.
> >
> > By the way, '&' is a little faster than '-', so I replaced after() with
> > "flag & FLAG_SND_UNA_ADVANCED".
> >
> > Signed-off-by: Yafang Shao <[email protected]>
> > ---
> > net/ipv4/tcp_input.c | 5 +++--
> > 1 file changed, 3 insertions(+), 2 deletions(-)
> >
> > diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
> > index 2868ef2..db5a6b7 100644
> > --- a/net/ipv4/tcp_input.c
> > +++ b/net/ipv4/tcp_input.c
> > @@ -3376,7 +3376,8 @@ static int tcp_ack_update_window(struct sock *sk, const struct sk_buff *skb, u32
> > }
> > }
> >
> > - tcp_snd_una_update(tp, ack);
> > + if (after(ack, tp->snd_una))
> > + tcp_snd_una_update(tp, ack);
> >
>
> Adding this after() here is confusing, how ack could be before snd_una ?
> That would be a serious bug.
>

ack can't be before snd_una, but it can be equal with snd_una.
Seems bellow change would be more specific,
if (ack != tp->snd_una)
tcp_snd_una_update(tp, ack);

> I do not see why another conditional has any gain here.
>
> You are trying to avoid very cheap operations :
>
> u32 delta = ack - tp->snd_una;
>
> tp->bytes_acked += delta;
> tp->snd_una = ack;
>
> Maybe the real reason for this patch is not explained in the changelog ?

No additional reason. I just want to avoid these uneccessary operations.
Because I find that this uncessary operations always happen,
especially when head prediction fails and then the packet can't go to
fast path processing.

Thanks
Yafang

2018-11-04 01:30:03

by Yafang Shao

[permalink] [raw]
Subject: Re: [PATCH] tcp: do not update snd_una if it is same with ack_seq

On Sun, Nov 4, 2018 at 1:04 AM Joe Perches <[email protected]> wrote:
>
> On Sun, 2018-11-04 at 00:54 +0800, Yafang Shao wrote:
> > In the slow path, TCP_SKB_SB(skb)->ack_seq may be same with tp->snd_una,
> > and under this condition we don't need to update the snd_una.
> >
> > Furthermore, tcp_ack_update_window() is only called in slow path,
> > so introducing this check won't affect the fast path processing.
> []
> > diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
> []
> > @@ -3610,7 +3611,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
> > if (flag & FLAG_UPDATE_TS_RECENT)
> > tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
> >
> > - if (!(flag & FLAG_SLOWPATH) && after(ack, prior_snd_una)) {
> > + if (!(flag & FLAG_SLOWPATH) && flag & FLAG_SND_UNA_ADVANCED) {
>
> stylistic nit:
>
> While the precedence is correct in any case,
> perhaps adding parentheses around
> flag & FLAG_SND_UNA_ADVANCED
> would make it more obvious.
>

Sure. will change it.

Thanks
Yafang