A Discrete-Event Network Simulator
API
sixlowpan-fragmentation-test.cc
Go to the documentation of this file.
1/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2013 Universita' di Firenze, Italy
4 *
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
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
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
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Tommaso Pecorella <tommaso.pecorella@unifi.it>
19 */
20#include "ns3/test.h"
21#include "ns3/config.h"
22#include "ns3/uinteger.h"
23#include "ns3/socket-factory.h"
24#include "ns3/ipv6-raw-socket-factory.h"
25#include "ns3/udp-socket-factory.h"
26#include "ns3/simulator.h"
27#include "ns3/simple-net-device.h"
28#include "ns3/socket.h"
29#include "ns3/udp-socket.h"
30
31#include "ns3/log.h"
32#include "ns3/node.h"
33#include "ns3/inet-socket-address.h"
34#include "ns3/boolean.h"
35
36#include "ns3/sixlowpan-net-device.h"
37#include "ns3/internet-stack-helper.h"
38#include "ns3/icmpv6-l4-protocol.h"
39#include "ns3/error-channel.h"
40
41#include <string>
42#include <limits>
43#include <netinet/in.h>
44
45using namespace ns3;
46
53{
57
61 uint8_t *m_data;
63 uint8_t m_icmpType;
64 uint8_t m_icmpCode;
65
66public:
67 virtual void DoRun (void);
70
71 // server part
72
77 void StartServer (Ptr<Node> serverNode);
82 void HandleReadServer (Ptr<Socket> socket);
83
84 // client part
85
90 void StartClient (Ptr<Node> clientNode);
95 void HandleReadClient (Ptr<Socket> socket);
104 void HandleReadIcmpClient (Ipv6Address icmpSource, uint8_t icmpTtl, uint8_t icmpType,
105 uint8_t icmpCode, uint32_t icmpInfo);
112 void SetFill (uint8_t *fill, uint32_t fillSize, uint32_t dataSize);
117 Ptr<Packet> SendClient (void);
118
119};
120
121
123 : TestCase ("Verify the 6LoWPAN protocol fragmentation and reassembly")
124{
125 m_socketServer = 0;
126 m_data = 0;
127 m_dataSize = 0;
128 m_size = 0;
129 m_icmpType = 0;
130 m_icmpCode = 0;
131}
132
134{
135 if ( m_data )
136 {
137 delete[] m_data;
138 }
139 m_data = 0;
140 m_dataSize = 0;
141}
142
143
144void
146{
147
148 if (m_socketServer == 0)
149 {
150 TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
151 m_socketServer = Socket::CreateSocket (serverNode, tid);
152 Inet6SocketAddress local = Inet6SocketAddress (Ipv6Address ("2001:0100::1"), 9);
153 m_socketServer->Bind (local);
154 Ptr<UdpSocket> udpSocket = DynamicCast<UdpSocket> (m_socketServer);
155 }
156
158}
159
160void
162{
163 Ptr<Packet> packet;
164 Address from;
165 while ((packet = socket->RecvFrom (from)))
166 {
167 if (Inet6SocketAddress::IsMatchingType (from))
168 {
169 packet->RemoveAllPacketTags ();
170 packet->RemoveAllByteTags ();
171
172 m_receivedPacketServer = packet->Copy ();
173 }
174 }
175}
176
177void
179{
180
181 if (m_socketClient == 0)
182 {
183 TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
184 m_socketClient = Socket::CreateSocket (clientNode, tid);
185 m_socketClient->Bind (Inet6SocketAddress (Ipv6Address::GetAny (), 9));
186 m_socketClient->Connect (Inet6SocketAddress (Ipv6Address ("2001:0100::1"), 9));
188 m_socketClient->SetAttribute ("IcmpCallback6", cbValue);
189 }
190
192}
193
194void
196{
197 Ptr<Packet> packet;
198 Address from;
199 while ((packet = socket->RecvFrom (from)))
200 {
201 if (Inet6SocketAddress::IsMatchingType (from))
202 {
203 m_receivedPacketClient = packet->Copy ();
204 }
205 }
206}
207
208void
210 uint8_t icmpTtl, uint8_t icmpType,
211 uint8_t icmpCode, uint32_t icmpInfo)
212{
213 m_icmpType = icmpType;
214 m_icmpCode = icmpCode;
215}
216
217void
218SixlowpanFragmentationTest::SetFill (uint8_t *fill, uint32_t fillSize, uint32_t dataSize)
219{
220 if (dataSize != m_dataSize)
221 {
222 delete [] m_data;
223 m_data = new uint8_t [dataSize];
224 m_dataSize = dataSize;
225 }
226
227 if (fillSize >= dataSize)
228 {
229 memcpy (m_data, fill, dataSize);
230 return;
231 }
232
233 uint32_t filled = 0;
234 while (filled + fillSize < dataSize)
235 {
236 memcpy (&m_data[filled], fill, fillSize);
237 filled += fillSize;
238 }
239
240 memcpy (&m_data[filled], fill, dataSize - filled);
241
242 m_size = dataSize;
243}
244
246{
247 Ptr<Packet> p;
248 if (m_dataSize)
249 {
250 p = Create<Packet> (m_data, m_dataSize);
251 }
252 else
253 {
254 p = Create<Packet> (m_size);
255 }
256 m_socketClient->Send (p);
257
258 return p;
259}
260
261void
263{
264 // Create topology
265 InternetStackHelper internet;
266 internet.SetIpv4StackInstall (false);
267 Packet::EnablePrinting ();
268
269 // Receiver Node
270 Ptr<Node> serverNode = CreateObject<Node> ();
271 internet.Install (serverNode);
272 Ptr<SimpleNetDevice> serverDev;
273 Ptr<BinaryErrorModel> serverDevErrorModel = CreateObject<BinaryErrorModel> ();
274 {
275 Ptr<Icmpv6L4Protocol> icmpv6l4 = serverNode->GetObject<Icmpv6L4Protocol> ();
276 icmpv6l4->SetAttribute ("DAD", BooleanValue (false));
277
278 serverDev = CreateObject<SimpleNetDevice> ();
279 serverDev->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ()));
280 serverDev->SetMtu (1500);
281 serverDev->SetReceiveErrorModel (serverDevErrorModel);
282 serverDevErrorModel->Disable ();
283 serverNode->AddDevice (serverDev);
284
285 Ptr<SixLowPanNetDevice> serverSix = CreateObject<SixLowPanNetDevice> ();
286 serverSix->SetAttribute ("ForceEtherType", BooleanValue (true) );
287 serverNode->AddDevice (serverSix);
288 serverSix->SetNetDevice (serverDev);
289
290 Ptr<Ipv6> ipv6 = serverNode->GetObject<Ipv6> ();
291 ipv6->AddInterface (serverDev);
292 uint32_t netdev_idx = ipv6->AddInterface (serverSix);
293 Ipv6InterfaceAddress ipv6Addr = Ipv6InterfaceAddress (Ipv6Address ("2001:0100::1"), Ipv6Prefix (64));
294 ipv6->AddAddress (netdev_idx, ipv6Addr);
295 ipv6->SetUp (netdev_idx);
296
297 }
298 StartServer (serverNode);
299
300 // Sender Node
301 Ptr<Node> clientNode = CreateObject<Node> ();
302 internet.Install (clientNode);
303 Ptr<SimpleNetDevice> clientDev;
304 Ptr<BinaryErrorModel> clientDevErrorModel = CreateObject<BinaryErrorModel> ();
305 {
306 Ptr<Icmpv6L4Protocol> icmpv6l4 = clientNode->GetObject<Icmpv6L4Protocol> ();
307 icmpv6l4->SetAttribute ("DAD", BooleanValue (false));
308
309 clientDev = CreateObject<SimpleNetDevice> ();
310 clientDev->SetAddress (Mac48Address::ConvertFrom (Mac48Address::Allocate ()));
311 clientDev->SetMtu (150);
312 clientDev->SetReceiveErrorModel (clientDevErrorModel);
313 clientDevErrorModel->Disable ();
314 clientNode->AddDevice (clientDev);
315
316 Ptr<SixLowPanNetDevice> clientSix = CreateObject<SixLowPanNetDevice> ();
317 clientSix->SetAttribute ("ForceEtherType", BooleanValue (true) );
318 clientNode->AddDevice (clientSix);
319 clientSix->SetNetDevice (clientDev);
320
321 Ptr<Ipv6> ipv6 = clientNode->GetObject<Ipv6> ();
322 ipv6->AddInterface (clientDev);
323 uint32_t netdev_idx = ipv6->AddInterface (clientSix);
324 Ipv6InterfaceAddress ipv6Addr = Ipv6InterfaceAddress (Ipv6Address ("2001:0100::2"), Ipv6Prefix (64));
325 ipv6->AddAddress (netdev_idx, ipv6Addr);
326 ipv6->SetUp (netdev_idx);
327 }
328 StartClient (clientNode);
329
330 // link the two nodes
331 Ptr<ErrorChannel> channel = CreateObject<ErrorChannel> ();
332 serverDev->SetChannel (channel);
333 clientDev->SetChannel (channel);
334
335
336 // some small packets, some rather big ones
337 uint32_t packetSizes[5] = {200, 300, 400, 500, 600};
338
339 // using the alphabet
340 uint8_t fillData[78];
341 for ( uint32_t k = 48; k <= 125; k++ )
342 {
343 fillData[k - 48] = k;
344 }
345
346 // First test: normal channel, no errors, no delays
347 for ( int i = 0; i < 5; i++)
348 {
349 uint32_t packetSize = packetSizes[i];
350
351 SetFill (fillData, 78, packetSize);
352
353 m_receivedPacketServer = Create<Packet> ();
354 Simulator::ScheduleWithContext (m_socketClient->GetNode ()->GetId (), Seconds (0),
357
358 uint8_t recvBuffer[65000];
359
360 uint16_t recvSize = m_receivedPacketServer->GetSize ();
361
362 NS_TEST_EXPECT_MSG_EQ (recvSize, packetSizes[i],
363 "Packet size not correct: recvSize: " << recvSize << " packetSizes[" << i << "]: " << packetSizes[i] );
364
365 m_receivedPacketServer->CopyData (recvBuffer, 65000);
367 0, "Packet content differs");
368 }
369
370 // Second test: normal channel, no errors, delays each 2 packets.
371 // Each other fragment will arrive out-of-order.
372 // The packets should be received correctly since reassembly will reorder the fragments.
373 channel->SetJumpingMode (true);
374 for ( int i = 0; i < 5; i++)
375 {
376 uint32_t packetSize = packetSizes[i];
377
378 SetFill (fillData, 78, packetSize);
379
380 m_receivedPacketServer = Create<Packet> ();
381 Simulator::ScheduleWithContext (m_socketClient->GetNode ()->GetId (), Seconds (0),
384
385 uint8_t recvBuffer[65000];
386
387 uint16_t recvSize = m_receivedPacketServer->GetSize ();
388
389 NS_TEST_EXPECT_MSG_EQ (recvSize, packetSizes[i],
390 "Packet size not correct: recvSize: " << recvSize << " packetSizes[" << i << "]: " << packetSizes[i] );
391
392 m_receivedPacketServer->CopyData (recvBuffer, 65000);
394 0, "Packet content differs");
395 }
396 channel->SetJumpingMode (false);
397
398
399 // Third test: normal channel, some packets are duplicate.
400 // The duplicate fragments should be discarded, so no error should be fired.
401 channel->SetDuplicateMode (true);
402 for ( int i = 1; i < 5; i++)
403 {
404 uint32_t packetSize = packetSizes[i];
405
406 SetFill (fillData, 78, packetSize);
407
408 // reset the model, we want to receive the very first fragment.
409 serverDevErrorModel->Reset ();
410
411 m_receivedPacketServer = Create<Packet> ();
412 m_icmpType = 0;
413 m_icmpCode = 0;
414 Simulator::ScheduleWithContext (m_socketClient->GetNode ()->GetId (), Seconds (0),
417
418 uint8_t recvBuffer[65000];
419
420 uint16_t recvSize = m_receivedPacketServer->GetSize ();
421
422 NS_TEST_EXPECT_MSG_EQ (recvSize, packetSizes[i],
423 "Packet size not correct: recvSize: " << recvSize << " packetSizes[" << i << "]: " << packetSizes[i] );
424
425 m_receivedPacketServer->CopyData (recvBuffer, 65000);
427 0, "Packet content differs");
428 }
429 channel->SetDuplicateMode (false);
430
431 // Fourth test: normal channel, some errors, no delays.
432 // The reassembly procedure does NOT fire any ICMP, so we do not expect any reply from the server.
433 // Client -> Server : errors enabled
434 // Server -> Client : errors disabled
435 clientDevErrorModel->Disable ();
436 serverDevErrorModel->Enable ();
437 for ( int i = 1; i < 5; i++)
438 {
439 uint32_t packetSize = packetSizes[i];
440
441 SetFill (fillData, 78, packetSize);
442
443 // reset the model, we want to receive the very first fragment.
444 serverDevErrorModel->Reset ();
445
446 m_receivedPacketServer = Create<Packet> ();
447 m_icmpType = 0;
448 m_icmpCode = 0;
449 Simulator::ScheduleWithContext (m_socketClient->GetNode ()->GetId (), Seconds (0),
452
453 uint16_t recvSize = m_receivedPacketServer->GetSize ();
454
455 NS_TEST_EXPECT_MSG_EQ ((recvSize == 0), true, "Server got a packet, something wrong");
456 // Note that a 6LoWPAN fragment timeout does NOT send any ICMPv6.
457 }
458
459 Simulator::Destroy ();
460}
461
462
469{
470public:
472private:
473};
474
476 : TestSuite ("sixlowpan-fragmentation", UNIT)
477{
478 AddTestCase (new SixlowpanFragmentationTest (), TestCase::QUICK);
479}
480
void Run(ObjectFactory &factory, uint32_t pop, uint32_t total, uint32_t runs, Ptr< RandomVariableStream > eventStream, bool calRev)
Perform the runs for a single scheduler type.
Ptr< Packet > m_sentPacketClient
Packet sent by client.
void StartClient(Ptr< Node > clientNode)
Start the client node.
void StartServer(Ptr< Node > serverNode)
Start the server node.
Ptr< Socket > m_socketServer
Socket on the server.
Ptr< Socket > m_socketClient
Socket on the client.
void SetFill(uint8_t *fill, uint32_t fillSize, uint32_t dataSize)
Set the packet optional content.
void HandleReadIcmpClient(Ipv6Address icmpSource, uint8_t icmpTtl, uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo)
Handles incoming ICMP packets in the client.
Ptr< Packet > m_receivedPacketServer
packet received by the server.
void HandleReadServer(Ptr< Socket > socket)
Handles incoming packets in the server.
uint32_t m_dataSize
Size of the data (if any).
void HandleReadClient(Ptr< Socket > socket)
Handles incoming packets in the client.
Ptr< Packet > SendClient(void)
Send a packet to the server.
uint32_t m_size
Size of the packet if no data has been provided.
virtual void DoRun(void)
Implementation to actually run this TestCase.
Ptr< Packet > m_receivedPacketClient
Packet received by the client.
uint8_t * m_data
Data to be carried in the packet.
a polymophic address class
Definition: address.h:91
AttributeValue implementation for Boolean.
Definition: boolean.h:37
AttributeValue implementation for Callback.
Definition: callback.h:1944
An implementation of the ICMPv6 protocol.
An Inet6 address class.
aggregate IP/TCP/UDP functionality to existing Nodes.
void SetIpv4StackInstall(bool enable)
Enable/disable IPv4 stack install.
void Install(std::string nodeName) const
Aggregate implementations of the ns3::Ipv4, ns3::Ipv6, ns3::Udp, and ns3::Tcp classes onto the provid...
Describes an IPv6 address.
Definition: ipv6-address.h:50
Access to the IPv6 forwarding table, interfaces, and configuration.
Definition: ipv6.h:82
IPv6 address associated with an interface.
Describes an IPv6 prefix.
Definition: ipv6-address.h:456
uint32_t GetId(void) const
Definition: node.cc:109
uint32_t AddDevice(Ptr< NetDevice > device)
Associate a NetDevice to this node.
Definition: node.cc:130
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:256
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
void RemoveAllByteTags(void)
Remove all byte tags stored in this packet.
Definition: packet.cc:371
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:378
void RemoveAllPacketTags(void)
Remove all packet tags.
Definition: packet.cc:984
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:856
virtual int Send(Ptr< Packet > p, uint32_t flags)=0
Send data (or dummy data) to the remote host.
virtual Ptr< Packet > RecvFrom(uint32_t maxSize, uint32_t flags, Address &fromAddress)=0
Read a single packet from the socket and retrieve the sender address.
virtual Ptr< Node > GetNode(void) const =0
Return the node this socket is associated with.
virtual int Connect(const Address &address)=0
Initiate a connection to a remote host.
void SetRecvCallback(Callback< void, Ptr< Socket > > receivedData)
Notify application when new data is available to be read.
Definition: socket.cc:128
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
encapsulates test code
Definition: test.h:994
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
A suite of tests to run.
Definition: test.h:1188
a unique identifier for an interface.
Definition: type-id.h:59
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
Definition: test.h:240
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1245
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1648
channel
Definition: third.py:83
static SixlowpanFragmentationTestSuite g_sixlowpanFragmentationTestSuite
Static variable for test initialization.
static const uint32_t packetSize
Packet size generated at the AP.