A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
sixlowpan-fragmentation-test.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2013 Universita' di Firenze, Italy
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Tommaso Pecorella <tommaso.pecorella@unifi.it>
7 */
8#include "ns3/boolean.h"
9#include "ns3/config.h"
10#include "ns3/error-channel.h"
11#include "ns3/icmpv6-l4-protocol.h"
12#include "ns3/inet-socket-address.h"
13#include "ns3/internet-stack-helper.h"
14#include "ns3/ipv6-raw-socket-factory.h"
15#include "ns3/log.h"
16#include "ns3/node.h"
17#include "ns3/simple-net-device.h"
18#include "ns3/simulator.h"
19#include "ns3/sixlowpan-net-device.h"
20#include "ns3/socket-factory.h"
21#include "ns3/socket.h"
22#include "ns3/test.h"
23#include "ns3/udp-socket-factory.h"
24#include "ns3/udp-socket.h"
25#include "ns3/uinteger.h"
26
27#ifdef __WIN32__
28#include "ns3/win32-internet.h"
29#else
30#include <netinet/in.h>
31#endif
32
33#include <limits>
34#include <string>
35
36using namespace ns3;
37
38/**
39 * \ingroup sixlowpan-tests
40 *
41 * \brief 6LoWPAN Fragmentation Test
42 */
44{
45 Ptr<Packet> m_sentPacketClient; //!< Packet sent by client.
46 Ptr<Packet> m_receivedPacketClient; //!< Packet received by the client.
47 Ptr<Packet> m_receivedPacketServer; //!< packet received by the server.
48
49 Ptr<Socket> m_socketServer; //!< Socket on the server.
50 Ptr<Socket> m_socketClient; //!< Socket on the client.
51 uint32_t m_dataSize; //!< Size of the data (if any).
52 uint8_t* m_data; //!< Data to be carried in the packet
53 uint32_t m_size; //!< Size of the packet if no data has been provided.
54 uint8_t m_icmpType; //!< ICMP type.
55 uint8_t m_icmpCode; //!< ICMP code.
56
57 public:
58 void DoRun() override;
61
62 // server part
63
64 /**
65 * Start the server node.
66 * \param serverNode The server node.
67 */
68 void StartServer(Ptr<Node> serverNode);
69 /**
70 * Handles incoming packets in the server.
71 * \param socket The receiving socket.
72 */
73 void HandleReadServer(Ptr<Socket> socket);
74
75 // client part
76
77 /**
78 * Start the client node.
79 * \param clientNode The client node.
80 */
81 void StartClient(Ptr<Node> clientNode);
82 /**
83 * Handles incoming packets in the client.
84 * \param socket The receiving socket.
85 */
86 void HandleReadClient(Ptr<Socket> socket);
87 /**
88 * Handles incoming ICMP packets in the client.
89 * \param icmpSource ICMP sender address.
90 * \param icmpTtl ICMP TTL.
91 * \param icmpType ICMP type.
92 * \param icmpCode ICMP code.
93 * \param icmpInfo ICMP info.
94 */
95 void HandleReadIcmpClient(Ipv6Address icmpSource,
96 uint8_t icmpTtl,
97 uint8_t icmpType,
98 uint8_t icmpCode,
99 uint32_t icmpInfo);
100 /**
101 * Set the packet optional content.
102 * \param fill Pointer to an array of data.
103 * \param fillSize Size of the array of data.
104 * \param dataSize Size of the packet - if fillSize is less than dataSize, the data is repeated.
105 */
106 void SetFill(uint8_t* fill, uint32_t fillSize, uint32_t dataSize);
107 /**
108 * Send a packet to the server.
109 * \returns The packet sent.
110 */
112};
113
115 : TestCase("Verify the 6LoWPAN protocol fragmentation and reassembly")
116{
117 m_socketServer = nullptr;
118 m_data = nullptr;
119 m_dataSize = 0;
120 m_size = 0;
121 m_icmpType = 0;
122 m_icmpCode = 0;
123}
124
126{
127 if (m_data)
128 {
129 delete[] m_data;
130 }
131 m_data = nullptr;
132 m_dataSize = 0;
133}
134
135void
150
151void
153{
154 Ptr<Packet> packet;
155 Address from;
156 while ((packet = socket->RecvFrom(from)))
157 {
159 {
160 packet->RemoveAllPacketTags();
161 packet->RemoveAllByteTags();
162
163 m_receivedPacketServer = packet->Copy();
164 }
165 }
166}
167
168void
185
186void
188{
189 Ptr<Packet> packet;
190 Address from;
191 while ((packet = socket->RecvFrom(from)))
192 {
194 {
195 m_receivedPacketClient = packet->Copy();
196 }
197 }
198}
199
200void
202 uint8_t icmpTtl,
203 uint8_t icmpType,
204 uint8_t icmpCode,
205 uint32_t icmpInfo)
206{
207 m_icmpType = icmpType;
208 m_icmpCode = icmpCode;
209}
210
211void
212SixlowpanFragmentationTest::SetFill(uint8_t* fill, uint32_t fillSize, uint32_t dataSize)
213{
214 if (dataSize != m_dataSize)
215 {
216 delete[] m_data;
217 m_data = new uint8_t[dataSize];
218 m_dataSize = dataSize;
219 }
220
221 if (fillSize >= dataSize)
222 {
223 memcpy(m_data, fill, dataSize);
224 return;
225 }
226
227 uint32_t filled = 0;
228 while (filled + fillSize < dataSize)
229 {
230 memcpy(&m_data[filled], fill, fillSize);
231 filled += fillSize;
232 }
233
234 memcpy(&m_data[filled], fill, dataSize - filled);
235
236 m_size = dataSize;
237}
238
241{
242 Ptr<Packet> p;
243 if (m_dataSize)
244 {
246 }
247 else
248 {
250 }
252
253 return p;
254}
255
256void
258{
259 // Create topology
260 InternetStackHelper internet;
261 internet.SetIpv4StackInstall(false);
263
264 // Receiver Node
265 Ptr<Node> serverNode = CreateObject<Node>();
266 internet.Install(serverNode);
267 Ptr<SimpleNetDevice> serverDev;
269 {
270 Ptr<Icmpv6L4Protocol> icmpv6l4 = serverNode->GetObject<Icmpv6L4Protocol>();
271 icmpv6l4->SetAttribute("DAD", BooleanValue(false));
272
273 serverDev = CreateObject<SimpleNetDevice>();
274 serverDev->SetAddress(Mac48Address::ConvertFrom(Mac48Address::Allocate()));
275 serverDev->SetMtu(1500);
276 serverDev->SetReceiveErrorModel(serverDevErrorModel);
277 serverDevErrorModel->Disable();
278 serverNode->AddDevice(serverDev);
279
281 serverNode->AddDevice(serverSix);
282 serverSix->SetNetDevice(serverDev);
283
284 Ptr<Ipv6> ipv6 = serverNode->GetObject<Ipv6>();
285 ipv6->AddInterface(serverDev);
286 uint32_t netdev_idx = ipv6->AddInterface(serverSix);
287 Ipv6InterfaceAddress ipv6Addr =
288 Ipv6InterfaceAddress(Ipv6Address("2001:0100::1"), Ipv6Prefix(64));
289 ipv6->AddAddress(netdev_idx, ipv6Addr);
290 ipv6->SetUp(netdev_idx);
291 }
292 StartServer(serverNode);
293
294 // Sender Node
295 Ptr<Node> clientNode = CreateObject<Node>();
296 internet.Install(clientNode);
297 Ptr<SimpleNetDevice> clientDev;
299 {
300 Ptr<Icmpv6L4Protocol> icmpv6l4 = clientNode->GetObject<Icmpv6L4Protocol>();
301 icmpv6l4->SetAttribute("DAD", BooleanValue(false));
302
303 clientDev = CreateObject<SimpleNetDevice>();
304 clientDev->SetAddress(Mac48Address::ConvertFrom(Mac48Address::Allocate()));
305 clientDev->SetMtu(150);
306 clientDev->SetReceiveErrorModel(clientDevErrorModel);
307 clientDevErrorModel->Disable();
308 clientNode->AddDevice(clientDev);
309
311 clientNode->AddDevice(clientSix);
312 clientSix->SetNetDevice(clientDev);
313
314 Ptr<Ipv6> ipv6 = clientNode->GetObject<Ipv6>();
315 ipv6->AddInterface(clientDev);
316 uint32_t netdev_idx = ipv6->AddInterface(clientSix);
317 Ipv6InterfaceAddress ipv6Addr =
318 Ipv6InterfaceAddress(Ipv6Address("2001:0100::2"), Ipv6Prefix(64));
319 ipv6->AddAddress(netdev_idx, ipv6Addr);
320 ipv6->SetUp(netdev_idx);
321 }
322 StartClient(clientNode);
323
324 // link the two nodes
326 serverDev->SetChannel(channel);
327 clientDev->SetChannel(channel);
328
329 // some small packets, some rather big ones
330 uint32_t packetSizes[5] = {200, 300, 400, 500, 600};
331
332 // using the alphabet
333 uint8_t fillData[78];
334 for (uint32_t k = 48; k <= 125; k++)
335 {
336 fillData[k - 48] = k;
337 }
338
339 // First test: normal channel, no errors, no delays
340 for (int i = 0; i < 5; i++)
341 {
342 uint32_t packetSize = packetSizes[i];
343
344 SetFill(fillData, 78, packetSize);
345
348 Seconds(0),
350 this);
352
353 uint8_t recvBuffer[65000];
354
355 uint16_t recvSize = m_receivedPacketServer->GetSize();
356
357 NS_TEST_EXPECT_MSG_EQ(recvSize,
358 packetSizes[i],
359 "Packet size not correct: recvSize: "
360 << recvSize << " packetSizes[" << i << "]: " << packetSizes[i]);
361
362 m_receivedPacketServer->CopyData(recvBuffer, 65000);
364 0,
365 "Packet content differs");
366 }
367
368 // Second test: normal channel, no errors, delays each 2 packets.
369 // Each other fragment will arrive out-of-order.
370 // The packets should be received correctly since reassembly will reorder the fragments.
371 channel->SetJumpingMode(true);
372 for (int i = 0; i < 5; i++)
373 {
374 uint32_t packetSize = packetSizes[i];
375
376 SetFill(fillData, 78, packetSize);
377
380 Seconds(0),
382 this);
384
385 uint8_t recvBuffer[65000];
386
387 uint16_t recvSize = m_receivedPacketServer->GetSize();
388
389 NS_TEST_EXPECT_MSG_EQ(recvSize,
390 packetSizes[i],
391 "Packet size not correct: recvSize: "
392 << recvSize << " packetSizes[" << i << "]: " << packetSizes[i]);
393
394 m_receivedPacketServer->CopyData(recvBuffer, 65000);
396 0,
397 "Packet content differs");
398 }
399 channel->SetJumpingMode(false);
400
401 // Third test: normal channel, some packets are duplicate.
402 // The duplicate fragments should be discarded, so no error should be fired.
403 channel->SetDuplicateMode(true);
404 for (int i = 1; i < 5; i++)
405 {
406 uint32_t packetSize = packetSizes[i];
407
408 SetFill(fillData, 78, packetSize);
409
410 // reset the model, we want to receive the very first fragment.
411 serverDevErrorModel->Reset();
412
414 m_icmpType = 0;
415 m_icmpCode = 0;
417 Seconds(0),
419 this);
421
422 uint8_t recvBuffer[65000];
423
424 uint16_t recvSize = m_receivedPacketServer->GetSize();
425
426 NS_TEST_EXPECT_MSG_EQ(recvSize,
427 packetSizes[i],
428 "Packet size not correct: recvSize: "
429 << recvSize << " packetSizes[" << i << "]: " << packetSizes[i]);
430
431 m_receivedPacketServer->CopyData(recvBuffer, 65000);
433 0,
434 "Packet content differs");
435 }
436 channel->SetDuplicateMode(false);
437
438 // Fourth test: normal channel, some errors, no delays.
439 // The reassembly procedure does NOT fire any ICMP, so we do not expect any reply from the
440 // server. Client -> Server : errors enabled Server -> Client : errors disabled
441 clientDevErrorModel->Disable();
442 serverDevErrorModel->Enable();
443 for (int i = 1; i < 5; i++)
444 {
445 uint32_t packetSize = packetSizes[i];
446
447 SetFill(fillData, 78, packetSize);
448
449 // reset the model, we want to receive the very first fragment.
450 serverDevErrorModel->Reset();
451
453 m_icmpType = 0;
454 m_icmpCode = 0;
456 Seconds(0),
458 this);
460
461 uint16_t recvSize = m_receivedPacketServer->GetSize();
462
463 NS_TEST_EXPECT_MSG_EQ((recvSize == 0), true, "Server got a packet, something wrong");
464 // Note that a 6LoWPAN fragment timeout does NOT send any ICMPv6.
465 }
466
468}
469
470/**
471 * \ingroup sixlowpan-tests
472 *
473 * \brief 6LoWPAN Fragmentation TestSuite
474 */
476{
477 public:
479
480 private:
481};
482
484 : TestSuite("sixlowpan-fragmentation", Type::UNIT)
485{
486 AddTestCase(new SixlowpanFragmentationTest(), TestCase::Duration::QUICK);
487}
488
490 g_sixlowpanFragmentationTestSuite; //!< Static variable for test initialization
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()
Send a packet to the server.
uint32_t m_size
Size of the packet if no data has been provided.
void DoRun() override
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:90
AttributeValue implementation for Boolean.
Definition boolean.h:26
AttributeValue implementation for Callback.
Definition callback.h:786
An implementation of the ICMPv6 protocol.
An Inet6 address class.
static bool IsMatchingType(const Address &addr)
If the address match.
aggregate IP/TCP/UDP functionality to existing Nodes.
Describes an IPv6 address.
static Ipv6Address GetAny()
Get the "any" (::) Ipv6Address.
Access to the IPv6 forwarding table, interfaces, and configuration.
Definition ipv6.h:71
IPv6 address associated with an interface.
Describes an IPv6 prefix.
static Mac48Address ConvertFrom(const Address &address)
static Mac48Address Allocate()
Allocate a new Mac48Address.
uint32_t GetId() const
Definition node.cc:106
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition packet.h:850
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition packet.cc:389
static void EnablePrinting()
Enable printing packets metadata.
Definition packet.cc:585
Smart pointer class similar to boost::intrusive_ptr.
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition simulator.cc:131
static void ScheduleWithContext(uint32_t context, const Time &delay, FUNC f, Ts &&... args)
Schedule an event with the given context.
Definition simulator.h:577
static void Run()
Run the simulation.
Definition simulator.cc:167
virtual int Send(Ptr< Packet > p, uint32_t flags)=0
Send data (or dummy data) to the remote host.
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:117
static Ptr< Socket > CreateSocket(Ptr< Node > node, TypeId tid)
This method wraps the creation of sockets that is performed on a given node by a SocketFactory specif...
Definition socket.cc:61
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
virtual Ptr< Node > GetNode() const =0
Return the node this socket is associated with.
encapsulates test code
Definition test.h:1050
void AddTestCase(TestCase *testCase, Duration duration=Duration::QUICK)
Add an individual child TestCase to this test suite.
Definition test.cc:292
A suite of tests to run.
Definition test.h:1267
Type
Type of test.
Definition test.h:1274
a unique identifier for an interface.
Definition type-id.h:48
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition type-id.cc:872
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
#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:241
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1308
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition callback.h:684
Ptr< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:580
static SixlowpanFragmentationTestSuite g_sixlowpanFragmentationTestSuite
Static variable for test initialization.
static const uint32_t packetSize
Packet size generated at the AP.