diff --git a/src/internet/model/tcp-socket-base.cc b/src/internet/model/tcp-socket-base.cc index 66a49b9fd..b72dfc32c 100644 --- a/src/internet/model/tcp-socket-base.cc +++ b/src/internet/model/tcp-socket-base.cc @@ -138,6 +138,10 @@ TcpSocketBase::GetTypeId (void) "TCP state", MakeTraceSourceAccessor (&TcpSocketBase::m_state), "ns3::TcpStatesTracedValueCallback") + .AddTraceSource ("AckState", + "TCP ACK machine state", + MakeTraceSourceAccessor (&TcpSocketBase::m_ackState), + "ns3::TcpAckStatesTracedValueCallback") .AddTraceSource ("RWND", "Remote side's flow control window", MakeTraceSourceAccessor (&TcpSocketBase::m_rWnd), @@ -190,7 +194,8 @@ TcpSocketBase::TcpSocketBase (void) m_sndScaleFactor (0), m_rcvScaleFactor (0), m_timestampEnabled (true), - m_timestampToEcho (0) + m_timestampToEcho (0), + m_ackState (OPEN) { NS_LOG_FUNCTION (this); @@ -237,7 +242,8 @@ TcpSocketBase::TcpSocketBase (const TcpSocketBase& sock) m_sndScaleFactor (sock.m_sndScaleFactor), m_rcvScaleFactor (sock.m_rcvScaleFactor), m_timestampEnabled (sock.m_timestampEnabled), - m_timestampToEcho (sock.m_timestampToEcho) + m_timestampToEcho (sock.m_timestampToEcho), + m_ackState (sock.m_ackState) { NS_LOG_FUNCTION (this); @@ -2784,6 +2790,13 @@ TcpSocketBase::GetRxBuffer (void) const return m_rxBuffer; } +const char* const +TcpSocketBase::TcpAckStateName[TcpSocketBase::LAST_ACKSTATE] = +{ + "OPEN", "DISORDER", "CWR", "RECOVERY", + "LOSS" +}; + //RttHistory methods RttHistory::RttHistory (SequenceNumber32 s, uint32_t c, Time t) diff --git a/src/internet/model/tcp-socket-base.h b/src/internet/model/tcp-socket-base.h index 20627d55d..6566aa163 100644 --- a/src/internet/model/tcp-socket-base.h +++ b/src/internet/model/tcp-socket-base.h @@ -166,6 +166,40 @@ public: */ Ptr GetRxBuffer (void) const; + /** + * \brief Definition of the ACK state machine + * + * The design of this state machine is taken from Linux v4.0, but it has been + * maintained in the Linux mainline from ages. It basically avoids to maintain + * a lot of boolean variables, and it allows to check the transitions from + * different algorithm in a cleaner way. + * + * These states represent the situation from a congestion control point of view: + * in fact, apart the OPEN state, the other states represent a situation in + * which there is a congestion, and different actions should be taken, + * depending on the case. + * + * \see ReceivedAck + * \see Retransmit + */ + typedef enum + { + OPEN, /**< Normal state, no dubious events */ + DISORDER, /**< In all the respects it is "Open", + * but requires a bit more attention. It is entered when + * we see some SACKs or dupacks. It is split of "Open" */ + CWR, /**< cWnd was reduced due to some Congestion Notification event. + * It can be ECN, ICMP source quench, local device congestion. + * Not used in NS-3 right now. */ + RECOVERY, /**< CWND was reduced, we are fast-retransmitting. */ + LOSS, /**< CWND was reduced due to RTO timeout or SACK reneging. */ + LAST_ACKSTATE /**< Used only in debug messages */ + } TcpAckState_t; + + /** + * \brief Literal names of TCP states for use in log messages + */ + static const char* const TcpAckStateName[TcpSocketBase::LAST_ACKSTATE]; // Necessary implementations of null functions from ns3::Socket virtual enum SocketErrno GetErrno (void) const; // returns m_errno @@ -774,8 +808,20 @@ protected: uint32_t m_timestampToEcho; //!< Timestamp to echo EventId m_sendPendingDataEvent; //!< micro-delay event to send pending data + + TracedValue m_ackState; //!< State in the ACK state machine }; +/** + * \ingroup tcp + * TracedValue Callback signature for TcpAckState_t + * + * \param [in] oldValue original value of the traced variable + * \param [in] newValue new value of the traced variable + */ +typedef void (* TcpAckStatesTracedValueCallback)(const TcpSocketBase::TcpAckState_t oldValue, + const TcpSocketBase::TcpAckState_t newValue); + } // namespace ns3 #endif /* TCP_SOCKET_BASE_H */