LEFT | RIGHT |
(no file at all) | |
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ | 1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */ |
2 /* | 2 /* |
3 * Copyright (c) 2016 Natale Patriciello <natale.patriciello@gmail.com> | 3 * Copyright (c) 2016 Natale Patriciello <natale.patriciello@gmail.com> |
4 * | 4 * |
5 * This program is free software; you can redistribute it and/or modify | 5 * This program is free software; you can redistribute it and/or modify |
6 * it under the terms of the GNU General Public License version 2 as | 6 * it under the terms of the GNU General Public License version 2 as |
7 * published by the Free Software Foundation; | 7 * published by the Free Software Foundation; |
8 * | 8 * |
9 * This program is distributed in the hope that it will be useful, | 9 * This program is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 * GNU General Public License for more details. | 12 * GNU General Public License for more details. |
13 * | 13 * |
14 * You should have received a copy of the GNU General Public License | 14 * You should have received a copy of the GNU General Public License |
15 * along with this program; if not, write to the Free Software | 15 * along with this program; if not, write to the Free Software |
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
17 * | 17 * |
18 */ | 18 */ |
19 | 19 |
20 #include "tcp-general-test.h" | 20 #include "tcp-general-test.h" |
21 #include "ns3/node.h" | 21 #include "ns3/node.h" |
22 #include "ns3/log.h" | 22 #include "ns3/log.h" |
| 23 #include "ns3/config.h" |
23 #include "tcp-error-model.h" | 24 #include "tcp-error-model.h" |
24 | 25 |
25 namespace ns3 { | 26 namespace ns3 { |
26 | 27 |
27 NS_LOG_COMPONENT_DEFINE ("TcpBytesInFlightTestSuite"); | 28 NS_LOG_COMPONENT_DEFINE ("TcpBytesInFlightTestSuite"); |
28 | 29 |
29 /** | 30 /** |
30 * \brief Check the value of BytesInFlight against a home-made guess | 31 * \brief Check the value of BytesInFlight against a home-made guess |
31 * | 32 * |
32 * The guess is made wrt to segments that travel the network; we have, | 33 * The guess is made wrt to segments that travel the network; we have, |
33 * in theory, the possibility to know the real amount of bytes in flight. Howeve
r | 34 * in theory, the possibility to know the real amount of bytes in flight. Howeve
r |
34 * this value is useless, since the sender bases its guess on the received ACK. | 35 * this value is useless, since the sender bases its guess on the received ACK. |
35 * | 36 * |
36 * \see Tx | 37 * \see Tx |
37 * \see BytesInFlightTrace | 38 * \see BytesInFlightTrace |
38 */ | 39 */ |
39 class TcpBytesInFlightTest : public TcpGeneralTest | 40 class TcpBytesInFlightTest : public TcpGeneralTest |
40 { | 41 { |
41 public: | 42 public: |
42 TcpBytesInFlightTest (const std::string &desc, std::vector<uint32_t> &toDrop); | 43 TcpBytesInFlightTest (const std::string &desc, std::vector<uint32_t> &toDrop); |
43 | 44 |
44 protected: | 45 protected: |
45 virtual Ptr<ErrorModel> CreateReceiverErrorModel (); | 46 virtual Ptr<ErrorModel> CreateReceiverErrorModel (); |
46 virtual void Rx (const Ptr<const Packet> p, const TcpHeader&h, SocketWho who); | 47 virtual void Rx (const Ptr<const Packet> p, const TcpHeader&h, SocketWho who); |
47 virtual void Tx (const Ptr<const Packet> p, const TcpHeader&h, SocketWho who); | 48 virtual void Tx (const Ptr<const Packet> p, const TcpHeader&h, SocketWho who); |
48 virtual void BytesInFlightTrace (uint32_t oldValue, uint32_t newValue); | 49 virtual void BytesInFlightTrace (uint32_t oldValue, uint32_t newValue); |
49 | 50 |
50 void PktDropped (const Ipv4Header &ipH, const TcpHeader& tcpH, Ptr<const Packe
t> p); | 51 void PktDropped (const Ipv4Header &ipH, const TcpHeader& tcpH, Ptr<const Packe
t> p); |
| 52 void BeforeRTOExpired (const Ptr<const TcpSocketState> tcb, SocketWho who); |
51 void ConfigureEnvironment (); | 53 void ConfigureEnvironment (); |
52 | 54 |
53 void FinalChecks (); | 55 void FinalChecks (); |
54 | 56 |
55 private: | 57 private: |
56 uint32_t m_realBytesInFlight; | |
57 uint32_t m_guessedBytesInFlight; | 58 uint32_t m_guessedBytesInFlight; |
58 uint32_t m_dupAckRecv; | 59 uint32_t m_dupAckRecv; |
59 SequenceNumber32 m_lastAckRecv; | 60 SequenceNumber32 m_lastAckRecv; |
60 SequenceNumber32 m_greatestSeqSent; | 61 SequenceNumber32 m_greatestSeqSent; |
61 std::vector<uint32_t> m_toDrop; // List of SequenceNumber to drop | 62 std::vector<uint32_t> m_toDrop; // List of SequenceNumber to drop |
62 }; | 63 }; |
63 | 64 |
64 TcpBytesInFlightTest::TcpBytesInFlightTest (const std::string &desc, | 65 TcpBytesInFlightTest::TcpBytesInFlightTest (const std::string &desc, |
65 std::vector<uint32_t> &toDrop) | 66 std::vector<uint32_t> &toDrop) |
66 : TcpGeneralTest (desc), | 67 : TcpGeneralTest (desc), |
67 m_realBytesInFlight (0), | |
68 m_guessedBytesInFlight (0), | 68 m_guessedBytesInFlight (0), |
69 m_dupAckRecv (0), | 69 m_dupAckRecv (0), |
70 m_lastAckRecv (1), | 70 m_lastAckRecv (1), |
71 m_greatestSeqSent (0), | 71 m_greatestSeqSent (0), |
72 m_toDrop (toDrop) | 72 m_toDrop (toDrop) |
73 { | 73 { |
74 } | 74 } |
75 | 75 |
76 void | 76 void |
77 TcpBytesInFlightTest::ConfigureEnvironment () | 77 TcpBytesInFlightTest::ConfigureEnvironment () |
78 { | 78 { |
79 TcpGeneralTest::ConfigureEnvironment (); | 79 TcpGeneralTest::ConfigureEnvironment (); |
80 SetAppPktCount (30); | 80 SetAppPktCount (30); |
81 SetPropagationDelay (MilliSeconds (50)); | 81 SetPropagationDelay (MilliSeconds (50)); |
82 SetTransmitStart (Seconds (2.0)); | 82 SetTransmitStart (Seconds (2.0)); |
83 | 83 |
| 84 Config::SetDefault ("ns3::TcpSocketBase::Sack", BooleanValue (false)); |
84 } | 85 } |
85 | 86 |
86 Ptr<ErrorModel> | 87 Ptr<ErrorModel> |
87 TcpBytesInFlightTest::CreateReceiverErrorModel () | 88 TcpBytesInFlightTest::CreateReceiverErrorModel () |
88 { | 89 { |
89 Ptr<TcpSeqErrorModel> m_errorModel = CreateObject<TcpSeqErrorModel> (); | 90 Ptr<TcpSeqErrorModel> m_errorModel = CreateObject<TcpSeqErrorModel> (); |
90 for (std::vector<uint32_t>::iterator it = m_toDrop.begin (); it != m_toDrop.en
d (); ++it) | 91 for (std::vector<uint32_t>::iterator it = m_toDrop.begin (); it != m_toDrop.en
d (); ++it) |
91 { | 92 { |
92 m_errorModel->AddSeqToKill (SequenceNumber32 (*it)); | 93 m_errorModel->AddSeqToKill (SequenceNumber32 (*it)); |
93 } | 94 } |
94 | 95 |
95 m_errorModel->SetDropCallback (MakeCallback (&TcpBytesInFlightTest::PktDropped
, this)); | 96 m_errorModel->SetDropCallback (MakeCallback (&TcpBytesInFlightTest::PktDropped
, this)); |
96 | 97 |
97 return m_errorModel; | 98 return m_errorModel; |
98 } | 99 } |
99 | 100 |
100 void | 101 void |
| 102 TcpBytesInFlightTest::BeforeRTOExpired (const Ptr<const TcpSocketState> tcb, Soc
ketWho who) |
| 103 { |
| 104 NS_LOG_DEBUG ("RTO for " << who); |
| 105 |
| 106 // Reset the bytes in flight |
| 107 // NB: If in the future informations about SACK is maintained, this should be |
| 108 // rewritten |
| 109 |
| 110 if (who == SENDER) |
| 111 { |
| 112 m_guessedBytesInFlight = 0; |
| 113 } |
| 114 } |
| 115 |
| 116 void |
101 TcpBytesInFlightTest::PktDropped (const Ipv4Header &ipH, const TcpHeader &tcpH, | 117 TcpBytesInFlightTest::PktDropped (const Ipv4Header &ipH, const TcpHeader &tcpH, |
102 Ptr<const Packet> p) | 118 Ptr<const Packet> p) |
103 { | 119 { |
104 NS_LOG_DEBUG ("Drop seq= " << tcpH.GetSequenceNumber () << " size " << p->GetS
ize ()); | 120 NS_LOG_DEBUG ("Drop seq= " << tcpH.GetSequenceNumber () << " size " << p->GetS
ize ()); |
105 | |
106 // These bytes leave the world, they were not loved by anyone | |
107 m_realBytesInFlight -= p->GetSize (); | |
108 } | 121 } |
109 | 122 |
110 void | 123 void |
111 TcpBytesInFlightTest::Rx (const Ptr<const Packet> p, const TcpHeader &h, SocketW
ho who) | 124 TcpBytesInFlightTest::Rx (const Ptr<const Packet> p, const TcpHeader &h, SocketW
ho who) |
112 { | 125 { |
113 if (who == RECEIVER) | 126 if (who == RECEIVER) |
114 { | 127 { |
115 // Received has got data; bytes are not in flight anymore | |
116 m_realBytesInFlight -= p->GetSize (); | |
117 } | 128 } |
118 else if (who == SENDER) | 129 else if (who == SENDER) |
119 { | 130 { |
120 if (h.GetAckNumber () > m_lastAckRecv) | 131 if (h.GetAckNumber () > m_lastAckRecv) |
121 { // New ack | 132 { // New ack |
122 uint32_t diff = h.GetAckNumber () - m_lastAckRecv; | 133 uint32_t diff = h.GetAckNumber () - m_lastAckRecv; |
123 NS_LOG_DEBUG ("Recv ACK=" << h.GetAckNumber ()); | 134 NS_LOG_DEBUG ("Recv ACK=" << h.GetAckNumber ()); |
124 | 135 |
125 if (m_dupAckRecv > 0) | 136 if (m_dupAckRecv > 0) |
126 { // Previously we got some ACKs | 137 { // Previously we got some ACKs |
(...skipping 28 matching lines...) Expand all Loading... |
155 m_guessedBytesInFlight); | 166 m_guessedBytesInFlight); |
156 } | 167 } |
157 else if (h.GetAckNumber () == m_lastAckRecv | 168 else if (h.GetAckNumber () == m_lastAckRecv |
158 && m_lastAckRecv != SequenceNumber32 (1) | 169 && m_lastAckRecv != SequenceNumber32 (1) |
159 && (h.GetFlags () & TcpHeader::FIN) == 0) | 170 && (h.GetFlags () & TcpHeader::FIN) == 0) |
160 { | 171 { |
161 // For each dupack I should guess that a segment has been received | 172 // For each dupack I should guess that a segment has been received |
162 // Please do not count FIN and SYN/ACK as dupacks | 173 // Please do not count FIN and SYN/ACK as dupacks |
163 m_guessedBytesInFlight -= GetSegSize (SENDER); | 174 m_guessedBytesInFlight -= GetSegSize (SENDER); |
164 m_dupAckRecv++; | 175 m_dupAckRecv++; |
| 176 // RFC 6675 says after two dupacks, the segment is considered lost |
| 177 if (m_dupAckRecv == 3) |
| 178 { |
| 179 m_guessedBytesInFlight -= GetSegSize (SENDER); |
| 180 NS_LOG_DEBUG ("Loss of a segment detected"); |
| 181 } |
165 NS_LOG_DEBUG ("Dupack received, Update m_guessedBytesInFlight to " << | 182 NS_LOG_DEBUG ("Dupack received, Update m_guessedBytesInFlight to " << |
166 m_guessedBytesInFlight); | 183 m_guessedBytesInFlight); |
167 } | 184 } |
168 | 185 |
169 } | 186 } |
170 } | 187 } |
171 | 188 |
172 void | 189 void |
173 TcpBytesInFlightTest::Tx (const Ptr<const Packet> p, const TcpHeader &h, SocketW
ho who) | 190 TcpBytesInFlightTest::Tx (const Ptr<const Packet> p, const TcpHeader &h, SocketW
ho who) |
174 { | 191 { |
175 if (who == SENDER) | 192 if (who == SENDER) |
176 { | 193 { |
177 m_realBytesInFlight += p->GetSize (); | 194 static SequenceNumber32 retr = SequenceNumber32 (0); |
| 195 static uint32_t times = 0; |
| 196 |
178 if (m_greatestSeqSent <= h.GetSequenceNumber ()) | 197 if (m_greatestSeqSent <= h.GetSequenceNumber ()) |
179 { // This is not a retransmission | 198 { // This is not a retransmission |
| 199 m_greatestSeqSent = h.GetSequenceNumber (); |
| 200 times = 0; |
| 201 } |
| 202 |
| 203 if (retr == h.GetSequenceNumber ()) |
| 204 { |
| 205 ++times; |
| 206 } |
| 207 |
| 208 if (times < 2) |
| 209 { |
| 210 // count retransmission only one time |
180 m_guessedBytesInFlight += p->GetSize (); | 211 m_guessedBytesInFlight += p->GetSize (); |
181 m_greatestSeqSent = h.GetSequenceNumber (); | 212 } |
182 } | 213 retr = h.GetSequenceNumber (); |
183 | |
184 // TODO: Maybe we need to account retransmission in another variable, | |
185 // such as m_guessedRetransOut ? | |
186 | 214 |
187 NS_LOG_DEBUG ("TX size=" << p->GetSize () << " seq=" << h.GetSequenceNumbe
r () << | 215 NS_LOG_DEBUG ("TX size=" << p->GetSize () << " seq=" << h.GetSequenceNumbe
r () << |
188 " m_guessedBytesInFlight=" << m_guessedBytesInFlight); | 216 " m_guessedBytesInFlight=" << m_guessedBytesInFlight); |
189 } | 217 } |
190 } | 218 } |
191 | 219 |
192 void | 220 void |
193 TcpBytesInFlightTest::BytesInFlightTrace (uint32_t oldValue, uint32_t newValue) | 221 TcpBytesInFlightTest::BytesInFlightTrace (uint32_t oldValue, uint32_t newValue) |
194 { | 222 { |
195 NS_LOG_DEBUG ("Socket BytesInFlight=" << newValue << | 223 NS_LOG_DEBUG ("Socket BytesInFlight=" << newValue << |
(...skipping 26 matching lines...) Expand all Loading... |
222 AddTestCase (new TcpBytesInFlightTest ("BytesInFlight value, two drop of sam
e segment", toDrop), | 250 AddTestCase (new TcpBytesInFlightTest ("BytesInFlight value, two drop of sam
e segment", toDrop), |
223 TestCase::QUICK); | 251 TestCase::QUICK); |
224 toDrop.pop_back (); | 252 toDrop.pop_back (); |
225 toDrop.push_back (4501); | 253 toDrop.push_back (4501); |
226 AddTestCase (new TcpBytesInFlightTest ("BytesInFlight value, two drop of con
secutive segments", toDrop), | 254 AddTestCase (new TcpBytesInFlightTest ("BytesInFlight value, two drop of con
secutive segments", toDrop), |
227 TestCase::QUICK); | 255 TestCase::QUICK); |
228 } | 256 } |
229 } g_tcpBytesInFlightTestSuite; | 257 } g_tcpBytesInFlightTestSuite; |
230 | 258 |
231 } // namespace ns3 | 259 } // namespace ns3 |
LEFT | RIGHT |