net/tcp:Add NewReno congestion control.

- NewReno congestion control algorithm is used to solve the problem
  of network congestion breakdown. NewReno congestion control includes
  slow start, collision avoidance, fast retransmission, and fast
  recovery. The implementation refers to RFC6582 and RFC5681.

- In addition, we optimize the congestion algorithm. In the conflict
  avoidance stage, the maximum congestion window max_cwnd is used to
  limit the excessive growth of cwnd and prevent network jitter
  caused by congestion. Maximum congestion window max_cwnd is updated
  with the current congestion window cwnd and the update weight is
  0.875 when an RTO timeout occurs.

Signed-off-by: liqinhui <liqinhui@xiaomi.com>
This commit is contained in:
liqinhui 2023-04-20 11:08:02 +08:00 committed by Alan Carvalho de Assis
parent 7a8cf7ff70
commit f61dc72892
10 changed files with 652 additions and 5 deletions

View file

@ -0,0 +1,172 @@
==========================
Congestion Control NewReno
==========================
NewReno congestion control algorithm is used to solve the problem of network congestion breakdown, which includes:
- Slow Start
- Congestion Avoidance
- Fast Retransmission
- Fast Recovery.
The implementation refers to RFC6582 and RFC5681. In addition, we optimize the congestion algorithm. In the congestion avoidance state, the maximum congestion window (max_cwnd) is used to limit the excessive growth of cwnd and prevent network jitter caused by congestion. Maximum congestion window (max_cwnd) is updated with the current congestion window (cwnd) and the update weight is 0.875 when an RTO timeout occurs.
Workflow
========
The NewReno on the tcp sender adjusts the cwnd and ssthresh based on received ack and Retransmitted Timeout (RTO) events.
Using the cwnd, together with snd_wnd, controls the number of bytes sent to the network. Here's how newreno works, as following:
- Initialize the ssthresh and cwnd, on establishing the tcp connection.
- When the ack is received, check whether the ack is repeated.
+ If yes, increase the dupack counts. If the dupack exceeds the Fast Retransmission Threshold 3, after retransmitting the lost segments (Fast Retransmission), enter to the Fast Recovery state.
+ If no, receive the new ack.
* If the current ackno is bigger than fr_ack which is the snd_seq when Fast Retransmission ocurrs, exit the Fast Recovery state and enter to congestion avoidance.
* If the cwnd is less than ssthresh, increase the cwnd on slow start state.
* If the cwnd is greater than or equal to ssthresh, the increased cwnd can not exceed max_cwnd.
- when RTO times out, reset the values of cwnd and ssthresh, update the max_cwnd, and enter to Slow Start state.
- When sending a segment, the minimum value of cwnd and snd_wnd is used to calculate the number of bytes that can be sent.
The simple state transition diagram of the NewReno is shown below.
::
| ^
| ------------------------
| initialize cwnd ssthresh
V
+------------+
.--------------->| Slow Start |-----------------.
| +------------+ |
| | | |
| timeout | | recv dup ack | recv new ack
|------------------ | | --------------- | ----------------
|reset cwnd ssthresh | | dupack >= 3 | cwnd >= ssthresh
|update max_cwnd | | fr_ack = snd_seq |
|<--------------------' |<------------------. |
| | | |
| v | V
| +--------+ +--------------------+
| | FT | |Congestion Avoidance|
| +--------+ +--------------------+
| | ^ |
| retransmit|lost segment | |
| | | |
| | recv new ack | |
| v ------------ | |
| +--------+ ack > fr_ack | |
| | FR |--------------' |
| +--------+ |
| | |
| v v
'-----------------------------------------------'
Configuration Options
=====================
``NET_TCP_CC_NEWRENO``
Enable or disable NewRenofunction.
Depends on ``NET_TCP_FAST_RETRANSMIT``.
Test
====
Test topology
-------------
::
IP:10.0.1.1
+--------+
--------| nuttx0 |--------
| +--------+ |
| /|\ |
| | |
| +-------+ |
| | ifb0 | |
| +-------+ |
\|/ /|\ \|/
+-------+ | +-------+
| tap0 |------/ \-------| tap1 |
+-------+ +-------+
/|\ /|\
| |
\|/ \|/
+-------+ +-------+
sim1 | eth0 | | eth0 | sim2
+-------+ +-------+
IP:10.0.1.3 IP:10.0.1.4
Test steps
----------
Test the function on the Ubuntu 22.04 x86_64 with NuttX SIM by following steps:
:1.Configure the test environment:
- Set the nuttx0 inbound speed to 10Mbps.
.. code-block:: bash
# Load fib module, and start ifb0 interface
modprobe ifb
ip link set dev ifb0 up
# Import the nuttx0 ingress packets into ifb0
tc qdisc add dev nuttx0 handle ffff: ingress
tc filter add dev nuttx0 parent ffff: u32 match u32 0 0 action mirred egress redirect dev ifb0
# Limit nuttx0 ingress 10Mbps
tc qdisc add dev ifb0 root tbf rate 10Mbit latency 50ms burst 1540
- configure the sim simulator.
+ Start iperf3 server on ubuntu.
.. code-block:: bash
iperf3 -s -i1 -p10003 #for sim1
iperf3 -s -i1 -p10004 #for sim2
+ start the emulators sim1 and sim2 and configure ip addresses.
.. code-block:: bash
# start and configure sim1
start gdb nuttx
ifconfig eth0 10.0.1.3
# start and configure sim2
start gdb nuttx
ifconfig eth0 10.0.1.4 # sim2
:2.Stream Testing:
- Use iperf3 to perform the stream testing.
.. code-block:: bash
iperf3 -c 10.0.1.1 -i1 -t60 -p10003 # sim1
iperf3 -c 10.0.1.1 -i1 -t60 -p10004 # sim2
:3.Comparison Testing:
Compares the test results of enabling and disabling NewReno.
Test results
------------
The test results should indicate that the total network throughput was significantly increased when NewReno congestion control was enabled, which was close to the actual total network bandwidth, and the rates of both sim devices were stable.

View file

@ -149,6 +149,15 @@ config NET_TCP_FAST_RETRANSMIT
missing segment, without waiting for a retransmission timer to
expire.
config NET_TCP_CC_NEWRENO
bool "Enable the NewReno Congestion Control algorithm"
default n
select NET_TCP_FAST_RETRANSMIT
---help---
RFC5681:
The TCP Congestion Control defines four congestion control algorithms,
slow start, congestion avoidance, fast retransmit, and fast recovery.
config NET_TCP_WINDOW_SCALE
bool "Enable TCP/IP Window Scale Option"
default n

View file

@ -61,6 +61,12 @@ ifeq ($(CONFIG_NET_TCP_WRITE_BUFFERS),y)
NET_CSRCS += tcp_wrbuffer.c
endif
# TCP congestion control
ifeq ($(CONFIG_NET_TCP_CC_NEWRENO),y)
NET_CSRCS += tcp_cc.c
endif
# TCP debug
ifeq ($(CONFIG_DEBUG_FEATURES),y)

View file

@ -71,7 +71,7 @@
# define TCP_WBPKTLEN(wrb) ((wrb)->wb_iob->io_pktlen)
# define TCP_WBSENT(wrb) ((wrb)->wb_sent)
# define TCP_WBNRTX(wrb) ((wrb)->wb_nrtx)
#ifdef CONFIG_NET_TCP_FAST_RETRANSMIT
#if defined(CONFIG_NET_TCP_FAST_RETRANSMIT) && !defined(CONFIG_NET_TCP_CC_NEWRENO)
# define TCP_WBNACK(wrb) ((wrb)->wb_nack)
#endif
# define TCP_WBIOB(wrb) ((wrb)->wb_iob)
@ -107,6 +107,14 @@
#define TCP_WSCALE 0x01U /* Window Scale option enabled */
#define TCP_SACK 0x02U /* Selective ACKs enabled */
#ifdef CONFIG_NET_TCP_CC_NEWRENO
/* The TCP flags for congestion control */
#define TCP_INFR 0x04U /* The flag in Fast Recovery */
#define TCP_INFT 0x08U /* The flag in Fast Transmitted */
#endif
/* The Max Range count of TCP Selective ACKs */
#define TCP_SACK_RANGES_MAX 4
@ -234,6 +242,15 @@ struct tcp_conn_s
* connection */
#endif
uint32_t rcv_adv; /* The right edge of the recv window advertized */
#ifdef CONFIG_NET_TCP_CC_NEWRENO
uint32_t last_ackno; /* The ack number at the last receive ack */
uint32_t dupacks; /* The number of duplicate ack */
uint32_t fr_recover; /* The snd_seq at the retransmissions */
uint32_t cwnd; /* The Congestion window */
uint32_t max_cwnd; /* The Congestion window maximum value */
uint32_t ssthresh; /* The Slow start threshold */
#endif
#ifdef CONFIG_NET_TCP_WINDOW_SCALE
uint32_t snd_wnd; /* Sequence and acknowledgement numbers of last
* window update */
@ -389,7 +406,7 @@ struct tcp_wrbuffer_s
uint16_t wb_sent; /* Number of bytes sent from the I/O buffer chain */
uint8_t wb_nrtx; /* The number of retransmissions for the last
* segment sent */
#ifdef CONFIG_NET_TCP_FAST_RETRANSMIT
#if defined(CONFIG_NET_TCP_FAST_RETRANSMIT) && !defined(CONFIG_NET_TCP_CC_NEWRENO)
uint8_t wb_nack; /* The number of ack count */
#endif
struct iob_s *wb_iob; /* Head of the I/O buffer chain */
@ -2234,6 +2251,70 @@ int tcp_ofoseg_bufsize(FAR struct tcp_conn_s *conn);
bool tcp_reorder_ofosegs(int nofosegs, FAR struct tcp_ofoseg_s *ofosegs);
/****************************************************************************
* Name: tcp_cc_init
*
* Description:
* Initialize the congestion control variables, cwnd, ssthresh and dupacks.
* The function is called on starting a new connection.
*
* Input Parameters:
* conn - The TCP connection of interest
*
* Returned Value:
* None
*
* Assumptions:
* The normal user level code is calling the connect/accept to start a new
* connection.
*
****************************************************************************/
#ifdef CONFIG_NET_TCP_CC_NEWRENO
void tcp_cc_init(FAR struct tcp_conn_s *conn);
/****************************************************************************
* Name: tcp_cc_update
*
* Description:
* Update the congestion control variables when recieve the SYNACK/ACK
* packet from the peer in the connection phase.
*
* Input Parameters:
* conn - The TCP connection of interest
* tcp - The TCP header.
*
* Returned Value:
* None
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
void tcp_cc_update(FAR struct tcp_conn_s *conn, FAR struct tcp_hdr_s *tcp);
/****************************************************************************
* Name: tcp_cc_recv_ack
*
* Description:
* Update congestion control variables
*
* Input Parameters:
* conn - The TCP connection of interest
* tcp - The TCP header.
*
* Returned Value:
* None
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
void tcp_cc_recv_ack(FAR struct tcp_conn_s *conn, FAR struct tcp_hdr_s *tcp);
#endif
#ifdef __cplusplus
}
#endif

301
net/tcp/tcp_cc.c Normal file
View file

@ -0,0 +1,301 @@
/****************************************************************************
* net/tcp/tcp_cc.c
* Handling TCP congestion control
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <debug.h>
#include "tcp/tcp.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define TCP_IPV4_DEFAULT_MSS 536
/* Initial Window threshold constants */
#define IW_MAX 4380 /* Initial Window maximum */
#define IW_MAX_HALF 2190
#define IW_MAX_QUATER 1095
/* Calculate the Initial Window, also used as Restart Window
* RFC5681 Section 3.1 specifies the default conservative values.
*/
#define CC_INIT_CWND(cwnd, mss) \
do { \
if ((mss) > IW_MAX_HALF) \
{ \
(cwnd) = 2 * (mss); \
} \
else if ((mss) > IW_MAX_QUATER) \
{ \
(cwnd) = 3 * (mss); \
} \
else \
{ \
(cwnd) = 4 * (mss); \
} \
} while(0)
/* Increments a size inc and holds at max value rather than rollover. */
#define CC_CWND_INC(wnd, inc) \
do { \
if ((uint32_t)((wnd) + (inc)) >= (wnd)) \
{ \
(wnd) = (uint32_t)((wnd) + (inc)); \
} \
else \
{ \
(wnd) = (uint32_t)-1; \
} \
} while(0)
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: tcp_cc_init
*
* Description:
* Initialize the congestion control variables, cwnd, ssthresh and dupacks.
* The function is called on starting a new connection.
*
* Input Parameters:
* conn - The TCP connection of interest
*
* Returned Value:
* None
*
* Assumptions:
* The normal user level code is calling the connect/accept to start a new
* connection.
*
****************************************************************************/
void tcp_cc_init(FAR struct tcp_conn_s *conn)
{
CC_INIT_CWND(conn->cwnd, conn->mss);
/* RFC 5681 recommends setting ssthresh arbitrarily high and
* gives an example of using the largest advertised receive window.
* We've seen complications with receiving TCPs that use window
* scaling and/or window auto-tuning where the initial advertised
* window is very small and then grows rapidly once the connection
* is established. To avoid these complications, we set ssthresh to
* the largest effective cwnd (amount of in-flight data) that the
* sender can have.
*/
conn->ssthresh = 2 * TCP_IPV4_DEFAULT_MSS;
conn->dupacks = 0;
}
/****************************************************************************
* Name: tcp_cc_update
*
* Description:
* Update the congestion control variables when recieve the SYNACK/ACK
* packet from the peer in the connection phase.
*
* Input Parameters:
* conn - The TCP connection of interest
* tcp - The TCP header.
*
* Returned Value:
* None
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
void tcp_cc_update(FAR struct tcp_conn_s *conn, FAR struct tcp_hdr_s *tcp)
{
/* After Fast retransmitted, set ssthresh to the maximum of
* the unacked and the 2*SMSS, and enter to Fast Recovery.
* ssthresh = max (FlightSize / 2, 2*SMSS) referring to rfc5681
* cwnd=ssthresh + 3*SMSS referring to rfc5681
*/
if (conn->flags & TCP_INFT)
{
conn->ssthresh = MAX(conn->tx_unacked / 2, 2 * conn->mss);
conn->cwnd = conn->ssthresh + 3 * conn->mss;
conn->flags &= ~TCP_INFT;
conn->flags |= TCP_INFR;
}
/* Update the cc parameters in the TCP_SYN_RCVD and TCP_SYN_SENT states
* when the tcp connection is established.
*/
else
{
conn->last_ackno = tcp_getsequence(tcp->ackno);
CC_INIT_CWND(conn->cwnd, conn->mss);
conn->max_cwnd = conn->snd_wnd;
conn->ssthresh = MAX(conn->snd_wnd, conn->ssthresh);
}
}
/****************************************************************************
* Name: tcp_cc_recv_ack
*
* Description:
* Update congestion control variables
*
* Input Parameters:
* conn - The TCP connection of interest
* tcp - The TCP header.
*
* Returned Value:
* None
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
void tcp_cc_recv_ack(FAR struct tcp_conn_s *conn, FAR struct tcp_hdr_s *tcp)
{
uint32_t ackno = tcp_getsequence(tcp->ackno);
/* Its only a duplicate ack if:
* 1) It doesn't ACK new data
* 2) There is outstanding unacknowledged data (retransmission
* timer running)
* 3) The ACK is == biggest ACK sequence number so far (last_ackno)
*
* If it passes all conditions, should process as a dupack:
* a) dupacks < 3: do nothing
* b) dupacks == 3: fast retransmit
* c) dupacks > 3: increase cwnd
*
* If ackno is between last_ackno and snd_seq, should reset dupack counter.
*/
/* Clause 1 */
if (TCP_SEQ_LTE(ackno, conn->last_ackno))
{
/* Clause 2 and Clause 3 */
if (conn->timer >= 0 &&
conn->last_ackno == ackno)
{
if (++conn->dupacks > TCP_FAST_RETRANSMISSION_THRESH)
{
/* Inflate the congestion window */
CC_CWND_INC(conn->cwnd, conn->mss);
}
if (conn->dupacks >= TCP_FAST_RETRANSMISSION_THRESH)
{
/* Do fast retransmit, but it is delayed in
* psock_send_eventhandler. Set the TCP_INFT flag.
*/
conn->flags |= TCP_INFT;
conn->fr_recover = tcp_getsequence(conn->sndseq);
}
}
}
else if (TCP_SEQ_GT(ackno, conn->last_ackno) &&
TCP_SEQ_LTE(ackno, tcp_getsequence(conn->sndseq)))
{
/* We come here when the ACK acknowledges new data. */
uint32_t acked = TCP_SEQ_SUB(ackno, conn->last_ackno);
/* Reset dupacks and update last_ackno. */
conn->dupacks = 0;
conn->last_ackno = ackno;
/* When the ackno covers more than the fr_recover, exit the
* fast recovery. Then, reset the "IN Fast Recovery" flags.
* Also reset the congestion window to the slow start threshold.
* If not, cwnd should be increased by mss. RFC6582.
*/
if (conn->flags & TCP_INFR)
{
if (ackno - 1 > conn->fr_recover)
{
/* Reset the fast retransmit variables. */
conn->flags &= ~TCP_INFR;
conn->cwnd = conn->ssthresh;
}
else
{
CC_CWND_INC(conn->cwnd, conn->mss);
return;
}
}
/* Update the congestion control variables (cwnd and ssthresh). */
if (conn->tcpstateflags >= TCP_ESTABLISHED)
{
uint32_t increase;
if (conn->cwnd < conn->ssthresh)
{
/* slow start (RFC 5681):
* Grow cwnd exponentially by maxseg(smss) per ACK.
*/
increase = acked > 0 ? MIN(acked, conn->mss) : conn->mss;
CC_CWND_INC(conn->cwnd, increase);
ninfo("update slow start cwnd to %u\n", conn->cwnd);
}
else
{
/* cong avoid (RFC 5681):
* Grow cwnd linearly by approximately maxseg per RTT using
* maxseg^2 / cwnd per ACK as the increment.
* If cwnd > maxseg^2, fix the cwnd increment at 1 byte to
* avoid capping cwnd.
*/
increase = MAX((conn->mss * conn->mss / conn->cwnd), 1);
CC_CWND_INC(conn->cwnd, increase);
conn->cwnd = MIN(conn->cwnd, conn->max_cwnd);
ninfo("update congestion avoidance cwnd to %u\n", conn->cwnd);
}
}
}
}

View file

@ -1149,6 +1149,12 @@ FAR struct tcp_conn_s *tcp_alloc_accept(FAR struct net_driver_s *dev,
conn->sndseq_max = 0;
#endif
#ifdef CONFIG_NET_TCP_CC_NEWRENO
/* Initialize the variables of congestion control */
tcp_cc_init(conn);
#endif
/* rcvseq should be the seqno from the incoming packet + 1. */
memcpy(conn->rcvseq, tcp->seqno, 4);
@ -1449,6 +1455,12 @@ int tcp_connect(FAR struct tcp_conn_s *conn, FAR const struct sockaddr *addr)
conn->sndseq_max = 0;
#endif
#ifdef CONFIG_NET_TCP_CC_NEWRENO
/* Initialize the variables of congestion control. */
tcp_cc_init(conn);
#endif
/* Initialize the list of TCP read-ahead buffers */
conn->readahead = NULL;

View file

@ -1160,6 +1160,11 @@ found:
if ((tcp->flags & TCP_ACK) != 0 &&
(conn->tcpstateflags & TCP_STATE_MASK) != TCP_SYN_RCVD)
{
#ifdef CONFIG_NET_TCP_CC_NEWRENO
/* If the packet is ack, update the cc var. */
tcp_cc_recv_ack(conn, tcp);
#endif
if (tcp_snd_wnd_update(conn, tcp))
{
/* Window updated, set the acknowledged flag. */
@ -1230,6 +1235,9 @@ found:
tcp_snd_wnd_init(conn, tcp);
tcp_snd_wnd_update(conn, tcp);
#ifdef CONFIG_NET_TCP_CC_NEWRENO
tcp_cc_update(conn, tcp);
#endif
flags = TCP_CONNECTED;
ninfo("TCP state: TCP_ESTABLISHED\n");
@ -1279,6 +1287,9 @@ found:
tcp_snd_wnd_init(conn, tcp);
tcp_snd_wnd_update(conn, tcp);
#ifdef CONFIG_NET_TCP_CC_NEWRENO
tcp_cc_update(conn, tcp);
#endif
net_incr32(conn->rcvseq, 1); /* ack SYN */
conn->tx_unacked = 0;

View file

@ -584,6 +584,9 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev,
}
else if (ackno == TCP_WBSEQNO(wrb))
{
#ifdef CONFIG_NET_TCP_CC_NEWRENO
if (conn->dupacks >= TCP_FAST_RETRANSMISSION_THRESH)
#else
/* Reset the duplicate ack counter */
if ((flags & TCP_NEWDATA) != 0)
@ -594,6 +597,7 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev,
/* Duplicate ACK? Retransmit data if need */
if (++TCP_WBNACK(wrb) == TCP_FAST_RETRANSMISSION_THRESH)
#endif
{
#ifdef CONFIG_NET_TCP_SELECTIVE_ACK
if ((conn->flags & TCP_SACK) &&
@ -614,11 +618,12 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev,
/* Do fast retransmit */
rexmitno = ackno;
#endif
#ifndef CONFIG_NET_TCP_CC_NEWRENO
/* Reset counter */
TCP_WBNACK(wrb) = 0;
#endif
#endif
}
}
}
@ -744,6 +749,19 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev,
return flags;
}
#ifdef CONFIG_NET_TCP_CC_NEWRENO
/* After Fast retransmitted, set ssthresh to the maximum of
* the unacked and the 2*SMSS, and enter to Fast Recovery.
* ssthresh = max (FlightSize / 2, 2*SMSS) referring to rfc5681
* cwnd=ssthresh + 3*SMSS referring to rfc5681
*/
if (conn->flags & TCP_INFT)
{
tcp_cc_update(conn, NULL);
}
#endif
/* Reset the retransmission timer. */
tcp_update_retrantimer(conn, conn->rto);
@ -802,6 +820,19 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev,
right = ofosegs[i].right;
}
}
#ifdef CONFIG_NET_TCP_CC_NEWRENO
/* After Fast retransmitted, set ssthresh to the maximum of
* the unacked and the 2*SMSS, and enter to Fast Recovery.
* ssthresh = max (FlightSize / 2, 2*SMSS) referring to rfc5681
* cwnd=ssthresh + 3*SMSS referring to rfc5681
*/
if (conn->flags & TCP_INFT)
{
tcp_cc_update(conn, NULL);
}
#endif
}
else
#endif
@ -965,7 +996,12 @@ static uint16_t psock_send_eventhandler(FAR struct net_driver_s *dev,
*/
seq = TCP_WBSEQNO(wrb) + TCP_WBSENT(wrb);
#ifdef CONFIG_NET_TCP_CC_NEWRENO
snd_wnd_edge = conn->snd_wl2 + MIN(conn->snd_wnd, conn->cwnd);
#else
snd_wnd_edge = conn->snd_wl2 + conn->snd_wnd;
#endif
if (TCP_SEQ_LT(seq, snd_wnd_edge))
{
uint32_t remaining_snd_wnd;

View file

@ -567,6 +567,25 @@ void tcp_timer(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn)
result = tcp_callback(dev, conn, TCP_REXMIT);
tcp_rexmit(dev, conn, result);
#ifdef CONFIG_NET_TCP_CC_NEWRENO
/* If conn is TCP_INFR, it should enter to slow start */
if (conn->flags & TCP_INFR)
{
conn->flags &= ~TCP_INFR;
}
/* update the max_cwnd */
conn->max_cwnd = (conn->max_cwnd + 7 * conn->cwnd) >> 3;
/* reset cwnd and ssthresh, refers to RFC5861. */
conn->ssthresh =
MAX(conn->tx_unacked / 2, 2 * conn->mss);
conn->cwnd = conn->mss;
#endif
goto done;
case TCP_FIN_WAIT_1:

View file

@ -236,7 +236,7 @@ void tcp_wrbuffer_release(FAR struct tcp_wrbuffer_s *wrb)
iob_free_chain(wrb->wb_iob);
}
#ifdef CONFIG_NET_TCP_FAST_RETRANSMIT
#if defined(CONFIG_NET_TCP_FAST_RETRANSMIT) && !defined(CONFIG_NET_TCP_CC_NEWRENO)
/* Reset the ack counter */
TCP_WBNACK(wrb) = 0;