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) 2010 University of Washington | 3 * Copyright (c) 2010 University of Washington |
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 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 // =========================================================================== | 62 // =========================================================================== |
63 // Tests of TCP implementation loss behavior | 63 // Tests of TCP implementation loss behavior |
64 // =========================================================================== | 64 // =========================================================================== |
65 // | 65 // |
66 | 66 |
67 class Ns3TcpLossTestCase : public TestCase | 67 class Ns3TcpLossTestCase : public TestCase |
68 { | 68 { |
69 public: | 69 public: |
70 Ns3TcpLossTestCase (); | 70 Ns3TcpLossTestCase (); |
71 Ns3TcpLossTestCase (std::string tcpModel, uint32_t testCase); | 71 Ns3TcpLossTestCase (std::string tcpModel, uint32_t testCase); |
72 virtual ~Ns3TcpLossTestCase () {} | 72 virtual ~Ns3TcpLossTestCase () |
| 73 { |
| 74 } |
73 | 75 |
74 private: | 76 private: |
75 virtual void DoSetup (void); | 77 virtual void DoSetup (void); |
76 virtual void DoRun (void); | 78 virtual void DoRun (void); |
77 virtual void DoTeardown (void); | 79 virtual void DoTeardown (void); |
78 | 80 |
79 Ptr<OutputStreamWrapper> m_osw; | 81 Ptr<OutputStreamWrapper> m_osw; |
80 std::string m_pcapFilename; | 82 std::string m_pcapFilename; |
81 PcapFile m_pcapFile; | 83 PcapFile m_pcapFile; |
82 uint32_t m_testCase; | 84 uint32_t m_testCase; |
83 uint32_t m_totalTxBytes; | 85 uint32_t m_totalTxBytes; |
84 uint32_t m_currentTxBytes; | 86 uint32_t m_currentTxBytes; |
85 bool m_writeVectors; | 87 bool m_writeVectors; |
86 bool m_writeResults; | 88 bool m_writeResults; |
87 bool m_writeLogging; | 89 bool m_writeLogging; |
88 bool m_needToClose; | 90 bool m_needToClose; |
89 std::string m_tcpModel; | 91 std::string m_tcpModel; |
90 | 92 |
91 void Ipv4L3Tx (std::string context, Ptr<const Packet> packet, Ptr<Ipv4> ipv4,
uint32_t interface); | 93 void Ipv4L3Tx (std::string context, Ptr<const Packet> packet, Ptr<Ipv4> ipv4,
uint32_t interface); |
92 void CwndTracer (uint32_t oldval, uint32_t newval); | 94 void CwndTracer (uint32_t oldval, uint32_t newval); |
93 void WriteUntilBufferFull (Ptr<Socket> localSocket, uint32_t txSpace); | 95 void WriteUntilBufferFull (Ptr<Socket> localSocket, uint32_t txSpace); |
94 void StartFlow (Ptr<Socket> localSocket, | 96 void StartFlow (Ptr<Socket> localSocket, |
95 Ipv4Address servAddress, | 97 Ipv4Address servAddress, |
96 uint16_t servPort); | 98 uint16_t servPort); |
97 | 99 |
98 }; | 100 }; |
99 | 101 |
100 Ns3TcpLossTestCase::Ns3TcpLossTestCase () | 102 Ns3TcpLossTestCase::Ns3TcpLossTestCase () |
101 : TestCase ("Check the operation of the TCP state machine for several cases"), | 103 : TestCase ("Check the operation of the TCP state machine for several cases"), |
102 m_testCase (0), | 104 m_testCase (0), |
103 m_totalTxBytes (200000), | 105 m_totalTxBytes (200000), |
104 m_currentTxBytes (0), | 106 m_currentTxBytes (0), |
105 m_writeVectors (WRITE_VECTORS), | 107 m_writeVectors (WRITE_VECTORS), |
(...skipping 19 matching lines...) Expand all Loading... |
125 | 127 |
126 void | 128 void |
127 Ns3TcpLossTestCase::DoSetup (void) | 129 Ns3TcpLossTestCase::DoSetup (void) |
128 { | 130 { |
129 // | 131 // |
130 // We expect there to be a file called ns3tcp-state-response-vectors.pcap in | 132 // We expect there to be a file called ns3tcp-state-response-vectors.pcap in |
131 // the data directory | 133 // the data directory |
132 // | 134 // |
133 std::ostringstream oss; | 135 std::ostringstream oss; |
134 oss << "ns3tcp-loss-" << m_tcpModel << m_testCase << "-response-vectors.pcap"; | 136 oss << "ns3tcp-loss-" << m_tcpModel << m_testCase << "-response-vectors.pcap"; |
135 m_pcapFilename = CreateDataDirFilename(oss.str ()); | 137 m_pcapFilename = CreateDataDirFilename (oss.str ()); |
136 | 138 |
137 if (m_writeVectors) | 139 if (m_writeVectors) |
138 { | 140 { |
139 m_pcapFile.Open (m_pcapFilename, std::ios::out|std::ios::binary); | 141 m_pcapFile.Open (m_pcapFilename, std::ios::out | std::ios::binary); |
140 m_pcapFile.Init (PCAP_LINK_TYPE, PCAP_SNAPLEN); | 142 m_pcapFile.Init (PCAP_LINK_TYPE, PCAP_SNAPLEN); |
141 } | 143 } |
142 else | 144 else |
143 { | 145 { |
144 m_pcapFile.Open (m_pcapFilename, std::ios::in|std::ios::binary); | 146 m_pcapFile.Open (m_pcapFilename, std::ios::in | std::ios::binary); |
145 NS_ABORT_MSG_UNLESS (m_pcapFile.GetDataLinkType () == PCAP_LINK_TYPE, | 147 NS_ABORT_MSG_UNLESS (m_pcapFile.GetDataLinkType () == PCAP_LINK_TYPE, |
146 "Wrong response vectors in directory: opening " << | 148 "Wrong response vectors in directory: opening " << |
147 m_pcapFilename); | 149 m_pcapFilename); |
148 } | 150 } |
149 } | 151 } |
150 | 152 |
151 void | 153 void |
152 Ns3TcpLossTestCase::DoTeardown (void) | 154 Ns3TcpLossTestCase::DoTeardown (void) |
153 { | 155 { |
154 m_pcapFile.Close (); | 156 m_pcapFile.Close (); |
155 } | 157 } |
156 | 158 |
157 void | 159 void |
158 Ns3TcpLossTestCase::Ipv4L3Tx (std::string context, Ptr<const Packet> packet, Ptr
<Ipv4> ipv4, uint32_t interface) | 160 Ns3TcpLossTestCase::Ipv4L3Tx (std::string context, Ptr<const Packet> packet, Ptr
<Ipv4> ipv4, uint32_t interface) |
159 { | 161 { |
160 // | 162 // |
161 // We're not testing IP so remove and toss the header. In order to do this, | 163 // We're not testing IP so remove and toss the header. In order to do this, |
162 // though, we need to copy the packet since we have a const version. | 164 // though, we need to copy the packet since we have a const version. |
163 // | 165 // |
164 Ptr<Packet> p = packet->Copy (); | 166 Ptr<Packet> received = packet->Copy (); |
165 Ipv4Header ipHeader; | 167 Ipv4Header ipHeader; |
166 p->RemoveHeader (ipHeader); | 168 received->RemoveHeader (ipHeader); |
167 | 169 |
168 // | 170 // |
169 // What is left is the TCP header and any data that may be sent. We aren't | 171 // What is left is the TCP header and any data that may be sent. We aren't |
170 // sending any TCP data, so we expect what remains is only TCP header, which | 172 // sending any TCP data, so we expect what remains is only TCP header, which |
171 // is a small thing to save. | 173 // is a small thing to save. |
172 // | 174 // |
173 if (m_writeVectors) | 175 if (m_writeVectors) |
174 { | 176 { |
175 // | 177 // |
176 // Save the TCP under test response for later testing. | 178 // Save the TCP under test response for later testing. |
177 // | 179 // |
178 Time tNow = Simulator::Now (); | 180 Time tNow = Simulator::Now (); |
179 int64_t tMicroSeconds = tNow.GetMicroSeconds (); | 181 int64_t tMicroSeconds = tNow.GetMicroSeconds (); |
180 | 182 |
181 | 183 |
182 m_pcapFile.Write (uint32_t (tMicroSeconds / 1000000), | 184 m_pcapFile.Write (uint32_t (tMicroSeconds / 1000000), |
183 uint32_t (tMicroSeconds % 1000000), | 185 uint32_t (tMicroSeconds % 1000000), |
184 p | 186 received); |
185 ); | |
186 } | 187 } |
187 else | 188 else |
188 { | 189 { |
189 // | 190 // |
190 // Read the TCP under test expected response from the expected vector | 191 // Read the TCP under test expected response from the expected vector |
191 // file and see if it still does the right thing. | 192 // file and see if it still does the right thing. |
192 // | 193 // |
193 uint8_t expected[PCAP_SNAPLEN]; | 194 uint8_t expectedBuffer[PCAP_SNAPLEN]; |
194 uint32_t tsSec, tsUsec, inclLen, origLen, readLen; | 195 uint32_t tsSec, tsUsec, inclLen, origLen, readLen; |
195 m_pcapFile.Read (expected, sizeof(expected), tsSec, tsUsec, inclLen, origL
en, readLen); | 196 m_pcapFile.Read (expectedBuffer, sizeof(expectedBuffer), tsSec, tsUsec, in
clLen, origLen, readLen); |
196 | 197 |
197 NS_LOG_DEBUG ("read " << readLen); | 198 NS_LOG_INFO ("read " << readLen << " bytes"); |
198 | 199 |
199 uint8_t *actual = new uint8_t[readLen]; | 200 uint8_t *actual = new uint8_t[readLen]; |
200 p->CopyData (actual, readLen); | 201 received->CopyData (actual, readLen); |
201 | 202 |
202 int result = memcmp (actual, expected, readLen); | 203 int result = memcmp (actual, expectedBuffer, readLen); |
| 204 |
| 205 TcpHeader expectedHeader, receivedHeader; |
| 206 Ptr<Packet> expected = Create<Packet> (expectedBuffer, readLen); |
| 207 |
| 208 expected->RemoveHeader (expectedHeader); |
| 209 received->RemoveHeader (receivedHeader); |
| 210 |
| 211 NS_LOG_DEBUG ("Expected " << expectedHeader << " received: " << receivedHe
ader); |
203 | 212 |
204 delete [] actual; | 213 delete [] actual; |
205 | 214 |
206 // | 215 // |
207 // Avoid streams of errors -- only report the first. | 216 // Avoid streams of errors -- only report the first. |
208 // | 217 // |
209 if (IsStatusSuccess ()) | 218 if (IsStatusSuccess ()) |
210 { | 219 { |
211 NS_TEST_EXPECT_MSG_EQ (result, 0, "Expected data comparison error: " <
< m_tcpModel << "-" << m_testCase); | 220 NS_TEST_EXPECT_MSG_EQ (result, 0, "Expected data comparison error: " <
< m_tcpModel << "-" << m_testCase); |
212 } | 221 } |
213 } | 222 } |
214 } | 223 } |
215 | 224 |
216 void | 225 void |
217 Ns3TcpLossTestCase::CwndTracer (uint32_t oldval, uint32_t newval) | 226 Ns3TcpLossTestCase::CwndTracer (uint32_t oldval, uint32_t newval) |
218 { | 227 { |
219 if (m_writeLogging) | 228 if (m_writeLogging) |
220 { | 229 { |
221 *(m_osw->GetStream ()) << "Moving cwnd from " << oldval << " to " << newva
l | 230 *(m_osw->GetStream ()) << "Moving cwnd from " << oldval << " to " << newva
l |
222 << " at time " << Simulator::Now ().GetSeconds () | 231 << " at time " << Simulator::Now ().GetSeconds () |
223 << " seconds" << std::endl; | 232 << " seconds" << std::endl; |
224 } | 233 } |
225 } | 234 } |
226 | 235 |
227 //////////////////////////////////////////////////////////////////// | 236 //////////////////////////////////////////////////////////////////// |
228 // Implementing an "application" to send bytes over a TCP connection | 237 // Implementing an "application" to send bytes over a TCP connection |
229 void | 238 void |
230 Ns3TcpLossTestCase::WriteUntilBufferFull (Ptr<Socket> localSocket, uint32_t txSp
ace) | 239 Ns3TcpLossTestCase::WriteUntilBufferFull (Ptr<Socket> localSocket, uint32_t txSp
ace) |
231 { | 240 { |
232 while (m_currentTxBytes < m_totalTxBytes) | 241 while (m_currentTxBytes < m_totalTxBytes) |
233 { | 242 { |
234 uint32_t left = m_totalTxBytes - m_currentTxBytes; | 243 uint32_t left = m_totalTxBytes - m_currentTxBytes; |
235 uint32_t dataOffset = m_currentTxBytes % 1040; | 244 uint32_t dataOffset = m_currentTxBytes % 1040; |
236 uint32_t toWrite = 1040 - dataOffset; | 245 uint32_t toWrite = 1040 - dataOffset; |
237 uint32_t txAvail = localSocket->GetTxAvailable (); | 246 uint32_t txAvail = localSocket->GetTxAvailable (); |
238 toWrite = std::min (toWrite, left); | 247 toWrite = std::min (toWrite, left); |
239 toWrite = std::min (toWrite, txAvail); | 248 toWrite = std::min (toWrite, txAvail); |
240 if (txAvail == 0) | 249 if (txAvail == 0) |
241 { | 250 { |
242 return; | 251 return; |
243 }; | 252 } |
244 if (m_writeLogging) | 253 if (m_writeLogging) |
245 { | 254 { |
246 std::clog << "Submitting " << toWrite | 255 std::clog << "Submitting " << toWrite |
247 << " bytes to TCP socket" << std::endl; | 256 << " bytes to TCP socket" << std::endl; |
248 } | 257 } |
249 int amountSent = localSocket->Send (0, toWrite, 0); | 258 int amountSent = localSocket->Send (0, toWrite, 0); |
250 NS_ASSERT (amountSent > 0); // Given GetTxAvailable() non-zero, amountSen
t should not be zero | 259 NS_ASSERT (amountSent > 0); // Given GetTxAvailable() non-zero, amountSen
t should not be zero |
251 m_currentTxBytes += amountSent; | 260 m_currentTxBytes += amountSent; |
252 } | 261 } |
253 if (m_needToClose) | 262 if (m_needToClose) |
254 { | 263 { |
255 if (m_writeLogging) | 264 if (m_writeLogging) |
256 { | 265 { |
257 std::clog << "Close socket at " | 266 std::clog << "Close socket at " |
258 << Simulator::Now ().GetSeconds () << std::endl; | 267 << Simulator::Now ().GetSeconds () << std::endl; |
259 } | 268 } |
260 localSocket->Close (); | 269 localSocket->Close (); |
261 m_needToClose = false; | 270 m_needToClose = false; |
262 } | 271 } |
263 } | 272 } |
264 | 273 |
265 void | 274 void |
266 Ns3TcpLossTestCase::StartFlow (Ptr<Socket> localSocket, | 275 Ns3TcpLossTestCase::StartFlow (Ptr<Socket> localSocket, |
267 Ipv4Address servAddress, | 276 Ipv4Address servAddress, |
268 uint16_t servPort) | 277 uint16_t servPort) |
269 { | 278 { |
270 if (m_writeLogging) | 279 if (m_writeLogging) |
271 { | 280 { |
272 std::clog << "Starting flow at time " | 281 std::clog << "Starting flow at time " |
273 << Simulator::Now ().GetSeconds () << std::endl; | 282 << Simulator::Now ().GetSeconds () << std::endl; |
274 } | 283 } |
275 localSocket->Connect (InetSocketAddress (servAddress, servPort)); // connect | 284 localSocket->Connect (InetSocketAddress (servAddress, servPort)); // connect |
276 | 285 |
277 // tell the tcp implementation to call WriteUntilBufferFull again | 286 // tell the tcp implementation to call WriteUntilBufferFull again |
278 // if we blocked and new tx buffer space becomes available | 287 // if we blocked and new tx buffer space becomes available |
279 localSocket->SetSendCallback (MakeCallback | 288 localSocket->SetSendCallback (MakeCallback |
280 (&Ns3TcpLossTestCase::WriteUntilBufferFull, | 289 (&Ns3TcpLossTestCase::WriteUntilBufferFull, |
281 this)); | 290 this)); |
282 WriteUntilBufferFull (localSocket, localSocket->GetTxAvailable ()); | 291 WriteUntilBufferFull (localSocket, localSocket->GetTxAvailable ()); |
283 } | 292 } |
284 | 293 |
285 void | 294 void |
286 Ns3TcpLossTestCase::DoRun (void) | 295 Ns3TcpLossTestCase::DoRun (void) |
287 { | 296 { |
288 // Network topology | 297 // Network topology |
289 // | 298 // |
290 // 8Mb/s, 0.1ms 0.8Mb/s, 100ms | 299 // 8Mb/s, 0.1ms 0.8Mb/s, 100ms |
291 // s1-----------------r1-----------------k1 | 300 // s1-----------------r1-----------------k1 |
292 // | 301 // |
293 // Example corresponding to simulations in the paper "Simulation-based | 302 // Example corresponding to simulations in the paper "Simulation-based |
294 // Comparisons of Tahoe, Reno, and SACK TCP | 303 // Comparisons of Tahoe, Reno, and SACK TCP |
| 304 |
| 305 Config::SetDefault ("ns3::TcpSocketBase::Sack", BooleanValue (false)); |
295 | 306 |
296 std::ostringstream tcpModel; | 307 std::ostringstream tcpModel; |
297 tcpModel << "ns3::Tcp" << m_tcpModel; | 308 tcpModel << "ns3::Tcp" << m_tcpModel; |
298 if (m_tcpModel.compare("WestwoodPlus") == 0) | 309 if (m_tcpModel.compare ("WestwoodPlus") == 0) |
299 { | 310 { |
300 » Config::SetDefault("ns3::TcpL4Protocol::SocketType", | 311 Config::SetDefault ("ns3::TcpL4Protocol::SocketType", |
301 » » » TypeIdValue (TcpWestwood::GetTypeId())); | 312 TypeIdValue (TcpWestwood::GetTypeId ())); |
302 » Config::SetDefault("ns3::TcpWestwood::ProtocolType", | 313 Config::SetDefault ("ns3::TcpWestwood::ProtocolType", |
303 » » » EnumValue(TcpWestwood::WESTWOODPLUS)); | 314 EnumValue (TcpWestwood::WESTWOODPLUS)); |
304 } | 315 } |
305 else | 316 else |
306 { | 317 { |
307 » Config::SetDefault ("ns3::TcpL4Protocol::SocketType", | 318 Config::SetDefault ("ns3::TcpL4Protocol::SocketType", |
308 StringValue (tcpModel.str ())); | 319 StringValue (tcpModel.str ())); |
309 } | 320 } |
310 | 321 |
311 Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (1000)); | 322 Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (1000)); |
312 Config::SetDefault ("ns3::TcpSocket::DelAckCount", UintegerValue (1)); | 323 Config::SetDefault ("ns3::TcpSocket::DelAckCount", UintegerValue (1)); |
313 Config::SetDefault ("ns3::TcpSocketBase::Timestamp", BooleanValue (false)); | 324 Config::SetDefault ("ns3::TcpSocketBase::Timestamp", BooleanValue (false)); |
314 | 325 |
315 if (m_writeLogging) | 326 if (m_writeLogging) |
316 { | 327 { |
317 LogComponentEnableAll (LOG_PREFIX_FUNC); | 328 LogComponentEnableAll (LOG_PREFIX_FUNC); |
318 LogComponentEnable ("Ns3TcpLossTest", LOG_LEVEL_ALL); | 329 LogComponentEnable ("Ns3TcpLossTest", LOG_LEVEL_ALL); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
367 InetSocketAddress (Ipv4Address::GetAny (), servPort)); | 378 InetSocketAddress (Ipv4Address::GetAny (), servPort)); |
368 ApplicationContainer apps = sink.Install (r1k1.Get (1)); | 379 ApplicationContainer apps = sink.Install (r1k1.Get (1)); |
369 apps.Start (Seconds (0.0)); | 380 apps.Start (Seconds (0.0)); |
370 apps.Stop (Seconds (100.0)); | 381 apps.Stop (Seconds (100.0)); |
371 | 382 |
372 // Create a data source to send packets on node s0. | 383 // Create a data source to send packets on node s0. |
373 // Instead of full application, here use the socket directly by | 384 // Instead of full application, here use the socket directly by |
374 // registering callbacks in function StarFlow(). | 385 // registering callbacks in function StarFlow(). |
375 Ptr<Socket> localSocket = Socket::CreateSocket (s1r1.Get (0), TcpSocketFactory
::GetTypeId ()); | 386 Ptr<Socket> localSocket = Socket::CreateSocket (s1r1.Get (0), TcpSocketFactory
::GetTypeId ()); |
376 localSocket->Bind (); | 387 localSocket->Bind (); |
377 Simulator::ScheduleNow (&Ns3TcpLossTestCase::StartFlow, | 388 Simulator::ScheduleNow (&Ns3TcpLossTestCase::StartFlow, |
378 this, | 389 this, |
379 localSocket, | 390 localSocket, |
380 ipInterfs.GetAddress (1), | 391 ipInterfs.GetAddress (1), |
381 servPort); | 392 servPort); |
382 | 393 |
383 Config::Connect ("/NodeList/0/$ns3::Ipv4L3Protocol/Tx", | 394 Config::Connect ("/NodeList/0/$ns3::Ipv4L3Protocol/Tx", |
384 MakeCallback (&Ns3TcpLossTestCase::Ipv4L3Tx, this)); | 395 MakeCallback (&Ns3TcpLossTestCase::Ipv4L3Tx, this)); |
385 | 396 |
386 Config::ConnectWithoutContext | 397 Config::ConnectWithoutContext |
387 ("/NodeList/0/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow", | 398 ("/NodeList/0/$ns3::TcpL4Protocol/SocketList/0/CongestionWindow", |
388 MakeCallback (&Ns3TcpLossTestCase::CwndTracer, this)); | 399 MakeCallback (&Ns3TcpLossTestCase::CwndTracer, this)); |
389 | 400 |
390 //////////////////////////////////////////////////////// | 401 //////////////////////////////////////////////////////// |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
482 AddTestCase (new Ns3TcpLossTestCase ("WestwoodPlus", 0), TestCase::QUICK); | 493 AddTestCase (new Ns3TcpLossTestCase ("WestwoodPlus", 0), TestCase::QUICK); |
483 AddTestCase (new Ns3TcpLossTestCase ("WestwoodPlus", 1), TestCase::QUICK); | 494 AddTestCase (new Ns3TcpLossTestCase ("WestwoodPlus", 1), TestCase::QUICK); |
484 AddTestCase (new Ns3TcpLossTestCase ("WestwoodPlus", 2), TestCase::QUICK); | 495 AddTestCase (new Ns3TcpLossTestCase ("WestwoodPlus", 2), TestCase::QUICK); |
485 AddTestCase (new Ns3TcpLossTestCase ("WestwoodPlus", 3), TestCase::QUICK); | 496 AddTestCase (new Ns3TcpLossTestCase ("WestwoodPlus", 3), TestCase::QUICK); |
486 AddTestCase (new Ns3TcpLossTestCase ("WestwoodPlus", 4), TestCase::QUICK); | 497 AddTestCase (new Ns3TcpLossTestCase ("WestwoodPlus", 4), TestCase::QUICK); |
487 | 498 |
488 } | 499 } |
489 | 500 |
490 static Ns3TcpLossTestSuite ns3TcpLossTestSuite; | 501 static Ns3TcpLossTestSuite ns3TcpLossTestSuite; |
491 | 502 |
LEFT | RIGHT |