Subject: Re: [tcpm] Congestion Window Validation

From: Arjuna Sathiaseelan <[email-masked]>
Date: Sat, 1 Feb 2014 13:12:23 +0000

Thanks Martin.

> I have a question regarding section 4.4 on page 9 where it is stated "A
> cwnd-limited sender uses the standard TCP method to increase cwnd (i.e. a
> TCP sender that fully utilises the cwnd is permitted to increase cwnd each
> received ACK)." I don't fully understand when this scenario can occur in the
> non-validated phase?

Good question - i think you are right, we may not need that. -
gorry/raffaello: thoughts?

> On the same page I found what appears to be two typos.
>
> "reducing the cwnd as defined in section 4.3.1" should be "reducing the cwnd
> as defined in section 4.4.1"?
>
> "The resulting reduction of cwnd described in section 4.3.2 is appropriate,
> since any accumulated path history is considered unreliable" should be "The
> resulting reduction of cwnd described in section 4.4.2 is appropriate, since
> any accumulated path history is considered unreliable"?

Yes those are NiTs - thanks for spotting.

> I also have a request regarding an equation on page 11.
>
> May "cwnd = max(1/2*cwnd, IW)" have parentheses added around 1 / 2 for added
> clarity?

Sure - thanks

Arjuna

> Regards
> Martin Winbjörk

---

From: Gorry Fairhurst <[email-masked]>
Date: Tue, 04 Feb 2014 15:59:57 +0000

Thanks Martin,

Some quick feedback below, as I also prepare an update to the ID.

Does this answer the questions?

Gorry

On 31/01/2014 09:54, Martin Winbjörk wrote:
> Hello
>
> My name is Martin Winbjörk and I am a student at Luleå University of Technology. I am currently writing my master thesis "TCP Optimized for Wireless Access" at Ericsson in Sweden, Luleå. In the thesis I am evaluating different TCP enhancements and Congestion Window Validation is one of them.
>
Hopefully you now have the Linux source code from github.

> I have a question regarding section 4.4 on page 9 where it is stated "A cwnd-limited sender uses the standard TCP method to increase cwnd (i.e. a TCP sender that fully utilises the cwnd is permitted to increase cwnd each received ACK)." I don't fully understand when this scenario can occur in the non-validated phase?
>
The first two bullets of section 4.4 should be read as a pair, IF ... 
ELSE...
We plan to rework the text by making this clearer, something like:

OLD:
 >
 >    o  A cwnd-limited sender uses the standard TCP method to increase
 >        cwnd (i.e. a TCP sender that fully utilises the cwnd is permitted
 >        to increase cwnd each received ACK).
 >
 >     o  A sender that is not cwnd-limited MUST NOT increase the cwnd when
 >        ACK packets are received in this phase.
 >
NEW:

o A sender determines whether to increase the cwnd based on whether it 
is cwnd-limited (see section 4.5.2):

   o  A sender that is cwnd-limited  MAY use the standard TCP
      method to increase cwnd (i.e. a TCP sender that fully utilises
      the cwnd is permitted to increase cwnd after each received ACK).

  o  A sender that is not cwnd-limited MUST NOT increase the cwnd when
     ACK packets are received in this phase.

There is then, the question of "why" - and this we will try to explain 
better:

Basically, this behaviour is triggered during transient conditions that 
occur when a sender in the non-validated phase receives an ACK that 
acknowledges received data, the cwnd was fully utilised, and more data 
is awaiting transmission than may be sent with the current cwnd.  The 
rule is intended to allow the sender in this case to use the standard 
method to increase the cwnd. (Note if the
sender suceeds in sending these new segments, the updated cwnd and 
pipeACK variables will eventually result in a transition to the 
validated phase.)

> "reducing the cwnd as defined in section 4.3.1" should be "reducing the cwnd as defined in section 4.4.1"?
> "The resulting reduction of cwnd described in section 4.3.2 is appropriate, since any accumulated path history is considered unreliable" should be "The resulting reduction of cwnd described in section 4.4.2 is appropriate, since any accumulated path history is considered unreliable"?
>
> May "cwnd = max(1/2*cwnd, IW)" have parentheses added around 1 / 2 for added clarity?
>
Both of these I have now resolved in the XML, and hope to publish an 
update soon.

-- 
Prof Gorry Fairhurst, School of Engineering, University of Aberdeen.
The University of Aberdeen is a charity registered in Scotland,
No SC013683.

---

From: Martin Winbjörk <[email-masked]>
Date: Thu, 6 Feb 2014 09:33:51 +0000

Thank you. Yes that answers my questions and I have the code from github. 

I have one new question regarding the following behavior specified on page 8 in the updated draft. 

"If the Retransmission Time Out (RTO) expires while in the non-
      validated phase, the sender MUST exit the non-validated phase.  It
      then resumes using the Standard TCP RTO mechanism [RFC5681].  (The
      resulting reduction of cwnd described in section 4.4.3 is
      appropriate, since any accumulated path history is considered
      unreliable)."

The reduction of cwnd in 4.4.3 is "cwnd = max((1/2)*cwnd, IW)."

That equation might set the cwnd very high after a RTO. Should it really be set that high? I don't fully understand if the cwnd should be set by Standard TCP RTO mechanism or according to 4.4.3.?

Regards
Martin Winbjörk

-----Original Message-----
From: Gorry Fairhurst [mailto:[email-masked]] 
Sent: den 4 februari 2014 17:00
To: Martin Winbjörk; [email-masked]; [email-masked]; [email-masked]
Subject: Re: Congestion Window Validation

Thanks Martin,

Gorry

NEW:

o A sender determines whether to increase the cwnd based on whether it is cwnd-limited (see section 4.5.2):

Basically, this behaviour is triggered during transient conditions that occur when a sender in the non-validated phase receives an ACK that acknowledges received data, the cwnd was fully utilised, and more data is awaiting transmission than may be sent with the current cwnd.  The rule is intended to allow the sender in this case to use the standard method to increase the cwnd. (Note if the sender suceeds in sending these new segments, the updated cwnd and pipeACK variables will eventually result in a transition to the validated phase.)

> May "cwnd = max(1/2*cwnd, IW)" have parentheses added around 1 / 2 for added clarity?
Both of these I have now resolved in the XML, and hope to publish an update soon.

--
Prof Gorry Fairhurst, School of Engineering, University of Aberdeen.
The University of Aberdeen is a charity registered in Scotland, No SC013683.

---

From: Gorry Fairhurst <[email-masked]>
Date: Thu, 06 Feb 2014 19:22:38 +0000

> That equation might set the cwnd very high after a RTO. Should it really be set that high? I don't fully understand if the cwnd should be set by Standard TCP RTO mechanism or according to 4.4.3.?
After RTO it should be the standard method - I assume an RTO indicates 
potential loss of path information, and therefore it must reset the 
congestion window. I confirm, the part in brackets should be removed.

Gorry

---

From: Martin Winbjörk <[email-masked]>
Date: Thu, 13 Feb 2014 11:58:28 +0000

I some questions regarding Congestion Window Validations condition for the validated phase.  The condition is: 
"pipeACK >=(1/2)*cwnd, or pipeACK is undefined". 

In my own implementation I had some problems during startup when the pipeACK variable is small. This has caused a bouncing behavior between non-validated and validated phase. A fix I made for it was an additional condition for the validated phase: 
" pipeACK >=(1/2)*cwnd, or pipeACK is undefined, or cwnd <= 10*MSS". 

Will this fix cause problems for the CWV algorithm? Have you experienced any similar problems?

Regards
Martin Winbjörk

---

From: Raffaello Secchi <[email-masked]>
Date: Thu, 13 Feb 2014 14:47:13 +0000

Yes indeed, we have found a similar issue. In our case, the problem
caused lots of "bouncing" during the initial SS phase and consequently
could delay the usual growth of cwnd. This seemed wrong and we updated
the method to counter this.

The solution you suggest also likely helps, but there could also be
drawbacks - e.g. it assumes the constant of 10 segments - this may
often be OK, but this is not always the case ... after a loss, the
ssthresh may be smaller. It's also possible the "bouncing" can also
occur with more complex types of traffic bursts, and so to be sure we
preferred a more generic approach of saying that the sender doesn't
need to be more conservative than TCP when it is behaving as a "bulk"
sender where we know it successfully utilises all the cwnd.

The current rev of the draft introduced an extra bullet in Section 4.4:

o  A sender determines whether to increase the cwnd based upon
      whether it is cwnd-limited (see section 4.5.2):

      *  A sender that is cwnd-limited MAY use the standard TCP method
         to increase cwnd (i.e. a TCP sender that fully utilises the
         cwnd is permitted to increase cwnd each received ACK using
         standard methods).

      *  A sender that is not cwnd-limited MUST NOT increase the cwnd
         when ACK packets are received in this phase.

The first sub-bullet allows TCP to increase cwnd when it is
cwnd-limited in the NVP. (The reason for this to avoid the transient
problem above).

In section 4.5.2 we provided some hints of how to implement the
cwnd-limited functions (this based on what was actually implemented in
"our" Linux module).

-------

The code below shows how we fixed it in our out-of-the-kernel newcwv LKM:

(https://github.com/rsecchi/newcwv/blob/master/tcp_newcwv.c)

The function tcp_newcwv_con_avoid is called to update cwnd every time
an ACK (not a DUPACK) is received not in a recovery phase. The line:

              if (!(nc->flags & IS_VALID) && !tcp_is_cwnd_limited(sk,
in_flight))
                              return;

prevents TCP to follow Reno behaviour in any case except when is not
in NVP and not cwnd-limited. This allows TCP to increase cwnd when the
FS is about cwnd. Here the function tcp_is_cwnd_limited takes into
account also TSO, so it's not exactly FS=cwnd.

That change fixed the problem for us. In the draft we wanted to be a
little more flexible on what means cwnd-limited and we used "MAY" in
case a better way to estimate pipeACK was found that did not cause
that problem.

------
static void tcp_newcwv_cong_avoid(struct sock *sk, u32 ack, u32 in_flight)
{
struct newcwv *nc = inet_csk_ca(sk);
struct tcp_sock *tp = tcp_sk(sk);

             nc->prior_in_flight = in_flight;
             nc->prior_retrans = tp->total_retrans;

              update_pipeack(sk);

              /* Check if cwnd is validated */
              if (!(nc->flags & IS_VALID) && !tcp_is_cwnd_limited(sk,
in_flight))
                              return;

            /* The following is the Reno behaviour */

            /* In "safe" area, increase. */
           if (tp->snd_cwnd <= tp->snd_ssthresh)
                  tcp_slow_start(tp);

           /* In dangerous area, increase slowly. */
           else
                 tcp_cong_avoid_ai(tp, tp->snd_cwnd);

}

-- 
Raffaello Secchi (Ph.D.) - ERG
University of Aberdeen
Aberdeen AB24 3UE
phone: +441224272807