|
|
| 41 |
|
41 |
|
| 42 |
NS_LOG_COMPONENT_DEFINE ("Ns3TcpLossTest"); |
42 |
NS_LOG_COMPONENT_DEFINE ("Ns3TcpLossTest"); |
| 43 |
|
43 |
|
|
|
44 |
const bool WRITE_VECTORS = false; // set to true to write response vectors |
| 45 |
const uint32_t PCAP_LINK_TYPE = 1187373553; // Some large random number -- we use to verify data was written by this program |
| 46 |
const uint32_t PCAP_SNAPLEN = 64; // Don't bother to save much data |
| 47 |
|
| 44 |
// =========================================================================== |
48 |
// =========================================================================== |
| 45 |
// Tests of TCP implementation loss behavior |
49 |
// Tests of TCP implementation loss behavior |
| 46 |
// =========================================================================== |
50 |
// =========================================================================== |
|
|
| 53 |
virtual ~Ns3TcpLossTestCase1 () {} |
57 |
virtual ~Ns3TcpLossTestCase1 () {} |
| 54 |
|
58 |
|
| 55 |
private: |
59 |
private: |
|
|
60 |
virtual void DoSetup (void); |
| 56 |
virtual bool DoRun (void); |
61 |
virtual bool DoRun (void); |
|
|
62 |
virtual void DoTeardown (void); |
| 63 |
|
| 64 |
std::string m_pcapFilename; |
| 65 |
PcapFile m_pcapFile; |
| 66 |
bool m_writeVectors; |
| 57 |
bool m_writeResults; |
67 |
bool m_writeResults; |
| 58 |
|
68 |
|
| 59 |
void SinkRx (std::string path, Ptr<const Packet> p, const Address &address); |
69 |
void Ipv4L3Tx (std::string context, Ptr<const Packet> packet, Ptr<Ipv4> ipv4, uint32_t interface); |
| 60 |
|
70 |
|
| 61 |
TestVectors<uint32_t> m_inputs; |
|
|
| 62 |
TestVectors<uint32_t> m_responses; |
| 63 |
}; |
71 |
}; |
| 64 |
|
72 |
|
| 65 |
Ns3TcpLossTestCase1::Ns3TcpLossTestCase1 () |
73 |
Ns3TcpLossTestCase1::Ns3TcpLossTestCase1 () |
| 66 |
: TestCase ("Check that ns-3 TCP survives loss of first two SYNs"), |
74 |
: TestCase ("Check that ns-3 TCP survives loss of first two SYNs"), |
|
|
75 |
m_writeVectors (WRITE_VECTORS), |
| 67 |
m_writeResults (false) |
76 |
m_writeResults (false) |
| 68 |
{ |
77 |
{ |
| 69 |
} |
78 |
} |
| 70 |
|
79 |
|
| 71 |
void |
80 |
void |
| 72 |
Ns3TcpLossTestCase1::SinkRx (std::string path, Ptr<const Packet> p, const Address &address) |
81 |
Ns3TcpLossTestCase1::DoSetup (void) |
| 73 |
{ |
82 |
{ |
| 74 |
m_responses.Add (p->GetSize ()); |
83 |
// |
|
|
84 |
// We expect there to be a file called ns3tcp-loss1-response-vectors.pcap" in |
| 85 |
// the source directory of this file. |
| 86 |
// |
| 87 |
m_pcapFilename = NS_TEST_SOURCEDIR + "ns3tcp-loss1-response-vectors.pcap"; |
| 88 |
|
| 89 |
if (m_writeVectors) |
| 90 |
{ |
| 91 |
m_pcapFile.Open (m_pcapFilename, std::ios::out|std::ios::binary); |
| 92 |
m_pcapFile.Init(PCAP_LINK_TYPE, PCAP_SNAPLEN); |
| 93 |
} |
| 94 |
else |
| 95 |
{ |
| 96 |
m_pcapFile.Open (m_pcapFilename, std::ios::in|std::ios::binary); |
| 97 |
NS_ABORT_MSG_UNLESS (m_pcapFile.GetDataLinkType () == PCAP_LINK_TYPE, "Wrong response vectors in directory"); |
| 98 |
} |
| 99 |
} |
| 100 |
|
| 101 |
void |
| 102 |
Ns3TcpLossTestCase1::DoTeardown (void) |
| 103 |
{ |
| 104 |
m_pcapFile.Close (); |
| 105 |
} |
| 106 |
|
| 107 |
void |
| 108 |
Ns3TcpLossTestCase1::Ipv4L3Tx (std::string context, Ptr<const Packet> packet, Ptr<Ipv4> ipv4, uint32_t interface) |
| 109 |
{ |
| 110 |
// |
| 111 |
// We're not testing IP so remove and toss the header. In order to do this, |
| 112 |
// though, we need to copy the packet since we have a const version. |
| 113 |
// |
| 114 |
Ptr<Packet> p = packet->Copy (); |
| 115 |
Ipv4Header ipHeader; |
| 116 |
p->RemoveHeader (ipHeader); |
| 117 |
|
| 118 |
// |
| 119 |
// What is left is the TCP header and any data that may be sent. We aren't |
| 120 |
// sending any TCP data, so we expect what remains is only TCP header, which |
| 121 |
// is a small thing to save. |
| 122 |
// |
| 123 |
if (m_writeVectors) |
| 124 |
{ |
| 125 |
// |
| 126 |
// Save the TCP under test response for later testing. |
| 127 |
// |
| 128 |
Time tNow = Simulator::Now (); |
| 129 |
int64_t tMicroSeconds = tNow.GetMicroSeconds (); |
| 130 |
m_pcapFile.Write (uint32_t (tMicroSeconds / 1000000), |
| 131 |
uint32_t (tMicroSeconds % 1000000), |
| 132 |
p->PeekData(), |
| 133 |
p->GetSize ()); |
| 134 |
} |
| 135 |
else |
| 136 |
{ |
| 137 |
// |
| 138 |
// Read the TCP under test expected response from the expected vector |
| 139 |
// file and see if it still does the right thing. |
| 140 |
// |
| 141 |
uint8_t expected[PCAP_SNAPLEN]; |
| 142 |
uint32_t tsSec, tsUsec, inclLen, origLen, readLen; |
| 143 |
m_pcapFile.Read (expected, sizeof(expected), tsSec, tsUsec, inclLen, origLen, readLen); |
| 144 |
|
| 145 |
uint8_t const *actual = p->PeekData(); |
| 146 |
|
| 147 |
uint32_t result = memcmp(actual, expected, readLen); |
| 148 |
|
| 149 |
// |
| 150 |
// Avoid streams of errors -- only report the first. |
| 151 |
// |
| 152 |
if (GetErrorStatus () == false) |
| 153 |
{ |
| 154 |
NS_TEST_EXPECT_MSG_EQ (result, 0, "Expected data comparison error"); |
| 155 |
} |
| 156 |
} |
| 75 |
} |
157 |
} |
| 76 |
|
158 |
|
| 77 |
bool |
159 |
bool |
|
|
| 116 |
apps.Start (Seconds (0.0)); |
198 |
apps.Start (Seconds (0.0)); |
| 117 |
apps.Stop (sinkStopTimeObj); |
199 |
apps.Stop (sinkStopTimeObj); |
| 118 |
|
200 |
|
| 119 |
Config::Connect ("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx", |
201 |
Config::Connect ("/NodeList/0/$ns3::Ipv4L3Protocol/Tx", |
| 120 |
MakeCallback (&Ns3TcpLossTestCase1::SinkRx, this)); |
202 |
MakeCallback (&Ns3TcpLossTestCase1::Ipv4L3Tx, this)); |
| 121 |
|
203 |
|
| 122 |
Simulator::Schedule(Seconds (2), &SocketWriter::Connect, socketWriter); |
204 |
Simulator::Schedule(Seconds (2), &SocketWriter::Connect, socketWriter); |
| 123 |
Simulator::Schedule(Seconds (10), &SocketWriter::Write, socketWriter, 500); |
205 |
Simulator::Schedule(Seconds (10), &SocketWriter::Write, socketWriter, 500); |
| 124 |
m_inputs.Add (500); |
|
|
| 125 |
Simulator::Schedule(writerStopTimeObj, &SocketWriter::Close, socketWriter); |
206 |
Simulator::Schedule(writerStopTimeObj, &SocketWriter::Close, socketWriter); |
| 126 |
|
207 |
|
| 127 |
std::list<uint32_t> sampleList; |
208 |
std::list<uint32_t> sampleList; |
|
|
| 143 |
Simulator::Run (); |
224 |
Simulator::Run (); |
| 144 |
Simulator::Destroy (); |
225 |
Simulator::Destroy (); |
| 145 |
|
226 |
|
| 146 |
// Compare inputs and outputs |
|
|
| 147 |
NS_TEST_ASSERT_MSG_EQ (m_inputs.GetN (), m_responses.GetN (), "Incorrect number of expected receive events"); |
| 148 |
for (uint32_t i = 0; i < m_responses.GetN (); i++) |
| 149 |
{ |
| 150 |
uint32_t in = m_inputs.Get (i); |
| 151 |
uint32_t out = m_responses.Get (i); |
| 152 |
NS_TEST_ASSERT_MSG_EQ (in, out, "Mismatch: expected " << in << " bytes, got " << out << " bytes"); |
| 153 |
} |
| 154 |
|
| 155 |
return GetErrorStatus (); |
227 |
return GetErrorStatus (); |
| 156 |
} |
228 |
} |
| 157 |
|
229 |
|
|
|
| 162 |
virtual ~Ns3TcpLossTestCase2 () {} |
234 |
virtual ~Ns3TcpLossTestCase2 () {} |
| 163 |
|
235 |
|
| 164 |
private: |
236 |
private: |
|
|
237 |
virtual void DoSetup (void); |
| 165 |
virtual bool DoRun (void); |
238 |
virtual bool DoRun (void); |
|
|
239 |
virtual void DoTeardown (void); |
| 240 |
|
| 241 |
std::string m_pcapFilename; |
| 242 |
PcapFile m_pcapFile; |
| 243 |
bool m_writeVectors; |
| 166 |
bool m_writeResults; |
244 |
bool m_writeResults; |
| 167 |
|
245 |
|
| 168 |
void SinkRx (std::string path, Ptr<const Packet> p, const Address &address); |
246 |
void Ipv4L3Tx (std::string context, Ptr<const Packet> packet, Ptr<Ipv4> ipv4, uint32_t interface); |
| 169 |
|
|
|
| 170 |
TestVectors<uint32_t> m_inputs; |
| 171 |
TestVectors<uint32_t> m_responses; |
| 172 |
}; |
247 |
}; |
| 173 |
|
248 |
|
| 174 |
Ns3TcpLossTestCase2::Ns3TcpLossTestCase2 () |
249 |
Ns3TcpLossTestCase2::Ns3TcpLossTestCase2 () |
| 175 |
: TestCase ("Check that ns-3 TCP survives loss of first data packet"), |
250 |
: TestCase ("Check that ns-3 TCP survives loss of first data packet"), |
|
|
251 |
m_writeVectors (WRITE_VECTORS), |
| 176 |
m_writeResults (false) |
252 |
m_writeResults (false) |
| 177 |
{ |
253 |
{ |
| 178 |
} |
254 |
} |
| 179 |
|
255 |
|
| 180 |
void |
256 |
void |
| 181 |
Ns3TcpLossTestCase2::SinkRx (std::string path, Ptr<const Packet> p, const Address &address) |
257 |
Ns3TcpLossTestCase2::DoSetup (void) |
| 182 |
{ |
258 |
{ |
| 183 |
m_responses.Add (p->GetSize ()); |
259 |
// |
|
|
260 |
// We expect there to be a file called ns3tcp-loss1-response-vectors.pcap" in |
| 261 |
// the source directory of this file. |
| 262 |
// |
| 263 |
m_pcapFilename = NS_TEST_SOURCEDIR + "ns3tcp-loss2-response-vectors.pcap"; |
| 264 |
|
| 265 |
if (m_writeVectors) |
| 266 |
{ |
| 267 |
m_pcapFile.Open (m_pcapFilename, std::ios::out|std::ios::binary); |
| 268 |
m_pcapFile.Init(PCAP_LINK_TYPE, PCAP_SNAPLEN); |
| 269 |
} |
| 270 |
else |
| 271 |
{ |
| 272 |
m_pcapFile.Open (m_pcapFilename, std::ios::in|std::ios::binary); |
| 273 |
NS_ABORT_MSG_UNLESS (m_pcapFile.GetDataLinkType () == PCAP_LINK_TYPE, "Wrong response vectors in directory"); |
| 274 |
} |
| 275 |
} |
| 276 |
|
| 277 |
void |
| 278 |
Ns3TcpLossTestCase2::DoTeardown (void) |
| 279 |
{ |
| 280 |
m_pcapFile.Close (); |
| 281 |
} |
| 282 |
|
| 283 |
void |
| 284 |
Ns3TcpLossTestCase2::Ipv4L3Tx (std::string context, Ptr<const Packet> packet, Ptr<Ipv4> ipv4, uint32_t interface) |
| 285 |
{ |
| 286 |
// |
| 287 |
// We're not testing IP so remove and toss the header. In order to do this, |
| 288 |
// though, we need to copy the packet since we have a const version. |
| 289 |
// |
| 290 |
Ptr<Packet> p = packet->Copy (); |
| 291 |
Ipv4Header ipHeader; |
| 292 |
p->RemoveHeader (ipHeader); |
| 293 |
|
| 294 |
// |
| 295 |
// What is left is the TCP header and any data that may be sent. We aren't |
| 296 |
// sending any TCP data, so we expect what remains is only TCP header, which |
| 297 |
// is a small thing to save. |
| 298 |
// |
| 299 |
if (m_writeVectors) |
| 300 |
{ |
| 301 |
// |
| 302 |
// Save the TCP under test response for later testing. |
| 303 |
// |
| 304 |
Time tNow = Simulator::Now (); |
| 305 |
int64_t tMicroSeconds = tNow.GetMicroSeconds (); |
| 306 |
m_pcapFile.Write (uint32_t (tMicroSeconds / 1000000), |
| 307 |
uint32_t (tMicroSeconds % 1000000), |
| 308 |
p->PeekData(), |
| 309 |
p->GetSize ()); |
| 310 |
} |
| 311 |
else |
| 312 |
{ |
| 313 |
// |
| 314 |
// Read the TCP under test expected response from the expected vector |
| 315 |
// file and see if it still does the right thing. |
| 316 |
// |
| 317 |
uint8_t expected[PCAP_SNAPLEN]; |
| 318 |
uint32_t tsSec, tsUsec, inclLen, origLen, readLen; |
| 319 |
m_pcapFile.Read (expected, sizeof(expected), tsSec, tsUsec, inclLen, origLen, readLen); |
| 320 |
|
| 321 |
uint8_t const *actual = p->PeekData(); |
| 322 |
|
| 323 |
uint32_t result = memcmp(actual, expected, readLen); |
| 324 |
|
| 325 |
// |
| 326 |
// Avoid streams of errors -- only report the first. |
| 327 |
// |
| 328 |
if (GetErrorStatus () == false) |
| 329 |
{ |
| 330 |
NS_TEST_EXPECT_MSG_EQ (result, 0, "Expected data comparison error"); |
| 331 |
} |
| 332 |
} |
| 184 |
} |
333 |
} |
| 185 |
|
334 |
|
| 186 |
bool |
335 |
bool |
|
|
| 225 |
apps.Start (Seconds (0.0)); |
374 |
apps.Start (Seconds (0.0)); |
| 226 |
apps.Stop (sinkStopTimeObj); |
375 |
apps.Stop (sinkStopTimeObj); |
| 227 |
|
376 |
|
| 228 |
Config::Connect ("/NodeList/*/ApplicationList/*/$ns3::PacketSink/Rx", |
377 |
Config::Connect ("/NodeList/0/$ns3::Ipv4L3Protocol/Tx", |
| 229 |
MakeCallback (&Ns3TcpLossTestCase2::SinkRx, this)); |
378 |
MakeCallback (&Ns3TcpLossTestCase2::Ipv4L3Tx, this)); |
| 230 |
|
379 |
|
| 231 |
Simulator::Schedule(Seconds (2), &SocketWriter::Connect, socketWriter); |
380 |
Simulator::Schedule(Seconds (2), &SocketWriter::Connect, socketWriter); |
| 232 |
Simulator::Schedule(Seconds (10), &SocketWriter::Write, socketWriter, 500); |
381 |
Simulator::Schedule(Seconds (10), &SocketWriter::Write, socketWriter, 500); |
| 233 |
m_inputs.Add (500); |
|
|
| 234 |
Simulator::Schedule(writerStopTimeObj, &SocketWriter::Close, socketWriter); |
382 |
Simulator::Schedule(writerStopTimeObj, &SocketWriter::Close, socketWriter); |
| 235 |
|
383 |
|
| 236 |
std::list<uint32_t> sampleList; |
384 |
std::list<uint32_t> sampleList; |
|
|
| 251 |
Simulator::Run (); |
399 |
Simulator::Run (); |
| 252 |
Simulator::Destroy (); |
400 |
Simulator::Destroy (); |
| 253 |
|
401 |
|
| 254 |
// Compare inputs and outputs |
|
|
| 255 |
NS_TEST_ASSERT_MSG_EQ (m_inputs.GetN (), m_responses.GetN (), "Incorrect number of expected receive events"); |
| 256 |
for (uint32_t i = 0; i < m_responses.GetN (); i++) |
| 257 |
{ |
| 258 |
uint32_t in = m_inputs.Get (i); |
| 259 |
uint32_t out = m_responses.Get (i); |
| 260 |
NS_TEST_ASSERT_MSG_EQ (in, out, "Mismatch: expected " << in << " bytes, got " << out << " bytes"); |
| 261 |
} |
| 262 |
|
| 263 |
return GetErrorStatus (); |
402 |
return GetErrorStatus (); |
| 264 |
} |
403 |
} |
| 265 |
|
404 |
|