|
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 |
|