A Discrete-Event Network Simulator
QKDNetSim v2.0 (NS-3 v3.41) @ (+)
API
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
ipv4-fragmentation-test.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011 Universita' di Firenze, Italy
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Tommaso Pecorella <tommaso.pecorella@unifi.it>
18  */
23 #include "ns3/arp-l3-protocol.h"
24 #include "ns3/boolean.h"
25 #include "ns3/config.h"
26 #include "ns3/error-channel.h"
27 #include "ns3/icmpv4-l4-protocol.h"
28 #include "ns3/inet-socket-address.h"
29 #include "ns3/internet-stack-helper.h"
30 #include "ns3/ipv4-l3-protocol.h"
31 #include "ns3/ipv4-list-routing.h"
32 #include "ns3/ipv4-raw-socket-factory.h"
33 #include "ns3/ipv4-static-routing.h"
34 #include "ns3/log.h"
35 #include "ns3/node.h"
36 #include "ns3/simple-net-device-helper.h"
37 #include "ns3/simple-net-device.h"
38 #include "ns3/simulator.h"
39 #include "ns3/socket-factory.h"
40 #include "ns3/socket.h"
41 #include "ns3/test.h"
42 #include "ns3/udp-l4-protocol.h"
43 #include "ns3/udp-socket-factory.h"
44 #include "ns3/udp-socket.h"
45 #include "ns3/uinteger.h"
46 
47 #ifdef __WIN32__
48 #include "ns3/win32-internet.h"
49 #else
50 #include <netinet/in.h>
51 #endif
52 
53 #include <limits>
54 #include <string>
55 
56 using namespace ns3;
57 
58 class UdpSocketImpl;
59 
65 class IPv4TestTag : public Tag
66 {
67  private:
68  uint64_t token;
69  public:
74  static TypeId GetTypeId()
75  {
76  static TypeId tid =
77  TypeId("ns3::IPv4TestTag").SetParent<Tag>().AddConstructor<IPv4TestTag>();
78  return tid;
79  }
80 
81  TypeId GetInstanceTypeId() const override
82  {
83  return GetTypeId();
84  }
85 
86  uint32_t GetSerializedSize() const override
87  {
88  return sizeof(token);
89  }
90 
91  void Serialize(TagBuffer buffer) const override
92  {
93  buffer.WriteU64(token);
94  }
95 
96  void Deserialize(TagBuffer buffer) override
97  {
98  token = buffer.ReadU64();
99  }
100 
101  void Print(std::ostream& os) const override
102  {
103  os << "token=" << token;
104  }
105 
110  void SetToken(uint64_t token)
111  {
112  this->token = token;
113  }
114 
119  uint64_t GetToken() const
120  {
121  return token;
122  }
123 };
124 
131 {
135 
138  uint32_t m_dataSize;
139  uint8_t* m_data;
140  uint32_t m_size;
141  uint8_t m_icmpType;
142  bool m_broadcast;
143 
144  public:
145  void DoRun() override;
150  Ipv4FragmentationTest(bool broadcast);
151  ~Ipv4FragmentationTest() override;
152 
153  // server part
154 
159  void StartServer(Ptr<Node> ServerNode);
164  void HandleReadServer(Ptr<Socket> socket);
165 
166  // client part
167 
172  void StartClient(Ptr<Node> ClientNode);
177  void HandleReadClient(Ptr<Socket> socket);
186  void HandleReadIcmpClient(Ipv4Address icmpSource,
187  uint8_t icmpTtl,
188  uint8_t icmpType,
189  uint8_t icmpCode,
190  uint32_t icmpInfo);
191 
198  void SetFill(uint8_t* fill, uint32_t fillSize, uint32_t dataSize);
199 
204  Ptr<Packet> SendClient();
205 };
206 
208  : TestCase(std::string("Verify the IPv4 layer 3 protocol fragmentation and reassembly: ") +
209  (broadcast ? "broadcast" : "unicast"))
210 {
211  m_socketServer = nullptr;
212  m_data = nullptr;
213  m_dataSize = 0;
214  m_size = 0;
215  m_icmpType = 0;
216  m_broadcast = broadcast;
217 }
218 
220 {
221  if (m_data)
222  {
223  delete[] m_data;
224  }
225  m_data = nullptr;
226  m_dataSize = 0;
227 }
228 
229 void
231 {
232  if (!m_socketServer)
233  {
234  TypeId tid = TypeId::LookupByName("ns3::UdpSocketFactory");
235  m_socketServer = Socket::CreateSocket(ServerNode, tid);
236  InetSocketAddress local = InetSocketAddress(Ipv4Address::GetAny(), 9);
237  m_socketServer->Bind(local);
238  Ptr<UdpSocket> udpSocket = DynamicCast<UdpSocket>(m_socketServer);
239  if (udpSocket)
240  {
241  // equivalent to setsockopt (MCAST_JOIN_GROUP)
242  udpSocket->MulticastJoinGroup(0, Ipv4Address("10.0.0.1"));
243  }
244  }
245 
247 }
248 
249 void
251 {
252  Ptr<Packet> packet;
253  Address from;
254  while ((packet = socket->RecvFrom(from)))
255  {
256  if (InetSocketAddress::IsMatchingType(from))
257  {
258  m_receivedPacketServer = packet->Copy();
259  }
260  }
261 }
262 
263 void
265 {
266  if (!m_socketClient)
267  {
268  TypeId tid = TypeId::LookupByName("ns3::UdpSocketFactory");
269  m_socketClient = Socket::CreateSocket(ClientNode, tid);
270  m_socketClient->Bind();
273  m_socketClient->SetAttribute("IcmpCallback", cbValue);
275  }
276 
278 }
279 
280 void
282 {
283  Ptr<Packet> packet;
284  Address from;
285  while ((packet = socket->RecvFrom(from)))
286  {
287  if (InetSocketAddress::IsMatchingType(from))
288  {
289  m_receivedPacketClient = packet->Copy();
290  }
291  }
292 }
293 
294 void
296  uint8_t icmpTtl,
297  uint8_t icmpType,
298  uint8_t icmpCode,
299  uint32_t icmpInfo)
300 {
301  m_icmpType = icmpType;
302 }
303 
304 void
305 Ipv4FragmentationTest::SetFill(uint8_t* fill, uint32_t fillSize, uint32_t dataSize)
306 {
307  if (dataSize != m_dataSize)
308  {
309  delete[] m_data;
310  m_data = new uint8_t[dataSize];
311  m_dataSize = dataSize;
312  }
313 
314  if (fillSize >= dataSize)
315  {
316  memcpy(m_data, fill, dataSize);
317  return;
318  }
319 
320  uint32_t filled = 0;
321  while (filled + fillSize < dataSize)
322  {
323  memcpy(&m_data[filled], fill, fillSize);
324  filled += fillSize;
325  }
326 
327  memcpy(&m_data[filled], fill, dataSize - filled);
328 
329  m_size = dataSize;
330 }
331 
334 {
335  Ptr<Packet> p;
336  if (m_dataSize)
337  {
338  p = Create<Packet>(m_data, m_dataSize);
339  }
340  else
341  {
342  p = Create<Packet>(m_size);
343  }
344  IPv4TestTag tag;
345  tag.SetToken(42);
346  p->AddPacketTag(tag);
347  p->AddByteTag(tag);
348 
349  if (m_broadcast)
350  {
353  InetSocketAddress saddress = InetSocketAddress::ConvertFrom(address);
354  saddress.SetIpv4(Ipv4Address::GetBroadcast());
355  m_socketClient->SendTo(p, 0, saddress);
356  }
357  else
358  {
359  m_socketClient->Send(p);
360  }
361 
362  return p;
363 }
364 
365 void
367 {
368  // set the arp cache to something quite high
369  // we shouldn't need because the NetDevice used doesn't need arp, but still
370  Config::SetDefault("ns3::ArpCache::PendingQueueSize", UintegerValue(100));
371 
372  // Create topology
373 
374  // Receiver Node
375  Ptr<Node> serverNode = CreateObject<Node>();
376  // Sender Node
377  Ptr<Node> clientNode = CreateObject<Node>();
378 
379  NodeContainer nodes(serverNode, clientNode);
380 
381  Ptr<ErrorChannel> channel = CreateObject<ErrorChannel>();
382  channel->SetJumpingTime(Seconds(0.5));
383 
384  SimpleNetDeviceHelper helperChannel;
385  helperChannel.SetNetDevicePointToPointMode(true);
386  NetDeviceContainer net = helperChannel.Install(nodes, channel);
387 
389  internet.Install(nodes);
390 
391  Ptr<Ipv4> ipv4;
392  uint32_t netdev_idx;
393  Ipv4InterfaceAddress ipv4Addr;
394 
395  // Receiver Node
396  ipv4 = serverNode->GetObject<Ipv4>();
397  netdev_idx = ipv4->AddInterface(net.Get(0));
398  ipv4Addr = Ipv4InterfaceAddress(Ipv4Address("10.0.0.1"), Ipv4Mask(0xffff0000U));
399  ipv4->AddAddress(netdev_idx, ipv4Addr);
400  ipv4->SetUp(netdev_idx);
401  Ptr<BinaryErrorModel> serverDevErrorModel = CreateObject<BinaryErrorModel>();
402  Ptr<SimpleNetDevice> serverDev = DynamicCast<SimpleNetDevice>(net.Get(0));
403  serverDevErrorModel->Disable();
404  serverDev->SetMtu(1500);
405  serverDev->SetReceiveErrorModel(serverDevErrorModel);
406  StartServer(serverNode);
407 
408  // Sender Node
409  ipv4 = clientNode->GetObject<Ipv4>();
410  netdev_idx = ipv4->AddInterface(net.Get(1));
411  ipv4Addr = Ipv4InterfaceAddress(Ipv4Address("10.0.0.2"), Ipv4Mask(0xffff0000U));
412  ipv4->AddAddress(netdev_idx, ipv4Addr);
413  ipv4->SetUp(netdev_idx);
414  Ptr<BinaryErrorModel> clientDevErrorModel = CreateObject<BinaryErrorModel>();
415  Ptr<SimpleNetDevice> clientDev = DynamicCast<SimpleNetDevice>(net.Get(1));
416  clientDevErrorModel->Disable();
417  clientDev->SetMtu(1500);
418  clientDev->SetReceiveErrorModel(clientDevErrorModel);
419  StartClient(clientNode);
420 
421  // some small packets, some rather big ones
422  uint32_t packetSizes[5] = {1000, 2000, 5000, 10000, 65000};
423 
424  // using the alphabet
425  uint8_t fillData[78];
426  for (uint32_t k = 48; k <= 125; k++)
427  {
428  fillData[k - 48] = k;
429  }
430 
431  // First test: normal channel, no errors, no delays
432  for (int i = 0; i < 5; i++)
433  {
434  uint32_t packetSize = packetSizes[i];
435 
436  SetFill(fillData, 78, packetSize);
437 
438  m_receivedPacketServer = Create<Packet>();
439  Simulator::ScheduleWithContext(m_socketClient->GetNode()->GetId(),
440  Seconds(0),
442  this);
443  Simulator::Run();
444 
445  uint8_t recvBuffer[65000];
446 
447  uint16_t recvSize = m_receivedPacketServer->GetSize();
448 
449  NS_TEST_EXPECT_MSG_EQ(recvSize, packetSizes[i], "Packet size not correct");
450 
451  m_receivedPacketServer->CopyData(recvBuffer, 65000);
453  0,
454  "Packet content differs");
455  }
456 
457  // Second test: normal channel, no errors, delays each 2 packets.
458  // Each other fragment will arrive out-of-order.
459  // The packets should be received correctly since reassembly will reorder the fragments.
460  channel->SetJumpingMode(true);
461  for (int i = 0; i < 5; i++)
462  {
463  uint32_t packetSize = packetSizes[i];
464 
465  SetFill(fillData, 78, packetSize);
466 
467  m_receivedPacketServer = Create<Packet>();
468  Simulator::ScheduleWithContext(m_socketClient->GetNode()->GetId(),
469  Seconds(0),
471  this);
472  Simulator::Run();
473 
474  uint8_t recvBuffer[65000];
475 
476  uint16_t recvSize = m_receivedPacketServer->GetSize();
477 
478  NS_TEST_EXPECT_MSG_EQ(recvSize, packetSizes[i], "Packet size not correct");
479 
480  m_receivedPacketServer->CopyData(recvBuffer, 65000);
482  0,
483  "Packet content differs");
484  }
485  channel->SetJumpingMode(false);
486 
487  // Third test: normal channel, some errors, no delays.
488  // The reassembly procedure should fire a timeout after 30 seconds (as specified in the RFCs).
489  // Upon the timeout, the fragments received so far are discarded and an ICMP should be sent back
490  // to the sender (if the first fragment has been received).
491  // In this test case the first fragment is received, so we do expect an ICMP.
492  // Client -> Server : errors enabled
493  // Server -> Client : errors disabled (we want to have back the ICMP)
494  clientDevErrorModel->Disable();
495  serverDevErrorModel->Enable();
496  for (int i = 1; i < 5; i++)
497  {
498  uint32_t packetSize = packetSizes[i];
499 
500  SetFill(fillData, 78, packetSize);
501 
502  // reset the model, we want to receive the very first fragment.
503  serverDevErrorModel->Reset();
504 
505  m_receivedPacketServer = Create<Packet>();
506  m_icmpType = 0;
507  Simulator::ScheduleWithContext(m_socketClient->GetNode()->GetId(),
508  Seconds(0),
510  this);
511  Simulator::Run();
512 
513  uint16_t recvSize = m_receivedPacketServer->GetSize();
514 
515  NS_TEST_EXPECT_MSG_EQ((recvSize == 0), true, "Server got a packet, something wrong");
517  true,
518  "Client did not receive ICMP::TIME_EXCEEDED");
519  }
520 
521  // Fourth test: normal channel, no errors, no delays.
522  // We check tags
523  clientDevErrorModel->Disable();
524  serverDevErrorModel->Disable();
525  for (int i = 0; i < 5; i++)
526  {
527  uint32_t packetSize = packetSizes[i];
528 
529  SetFill(fillData, 78, packetSize);
530 
531  m_receivedPacketServer = Create<Packet>();
532  Simulator::ScheduleWithContext(m_socketClient->GetNode()->GetId(),
533  Seconds(0),
535  this);
536  Simulator::Run();
537 
538  IPv4TestTag packetTag;
539  bool found = m_receivedPacketServer->PeekPacketTag(packetTag);
540 
541  NS_TEST_EXPECT_MSG_EQ(found, true, "PacketTag not found");
542  NS_TEST_EXPECT_MSG_EQ(packetTag.GetToken(), 42, "PacketTag value not correct");
543 
545 
546  uint32_t end = 0;
547  uint32_t tagStart = 0;
548  uint32_t tagEnd = 0;
549  while (iter.HasNext())
550  {
551  ByteTagIterator::Item item = iter.Next();
553  "ns3::IPv4TestTag",
554  "ByteTag name not correct");
555  tagStart = item.GetStart();
556  tagEnd = item.GetEnd();
557  if (end == 0)
558  {
559  NS_TEST_EXPECT_MSG_EQ(tagStart, 0, "First ByteTag Start not correct");
560  }
561  if (end != 0)
562  {
563  NS_TEST_EXPECT_MSG_EQ(tagStart, end, "ByteTag End not correct");
564  }
565  end = tagEnd;
566  IPv4TestTag* byteTag = dynamic_cast<IPv4TestTag*>(item.GetTypeId().GetConstructor()());
567  NS_TEST_EXPECT_MSG_NE(byteTag, 0, "ByteTag not found");
568  item.GetTag(*byteTag);
569  NS_TEST_EXPECT_MSG_EQ(byteTag->GetToken(), 42, "ByteTag value not correct");
570  delete byteTag;
571  }
573  }
574 
575  Simulator::Destroy();
576 }
577 
584 {
585  public:
587 };
588 
590  : TestSuite("ipv4-fragmentation", UNIT)
591 {
592  AddTestCase(new Ipv4FragmentationTest(false), TestCase::QUICK);
593  AddTestCase(new Ipv4FragmentationTest(true), TestCase::QUICK);
594 }
595 
Tag used in IPv4 Fragmentation Test.
static TypeId GetTypeId()
Get the type ID.
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
uint32_t GetSerializedSize() const override
void SetToken(uint64_t token)
Set the token.
void Deserialize(TagBuffer buffer) override
uint64_t token
Token carried by the tag.
void Serialize(TagBuffer buffer) const override
uint64_t GetToken() const
Get the token.
void Print(std::ostream &os) const override
IPv4 Fragmentation Test.
Ptr< Packet > m_receivedPacketClient
Packet received by client.
Ptr< Packet > m_receivedPacketServer
Packet received by server.
Ptr< Packet > m_sentPacketClient
Packet sent by client.
Ptr< Packet > SendClient()
Send a packet.
Ptr< Socket > m_socketServer
Server socket.
void StartClient(Ptr< Node > ClientNode)
Start the client.
Ptr< Socket > m_socketClient
Client socket.
void StartServer(Ptr< Node > ServerNode)
Start the server.
void HandleReadIcmpClient(Ipv4Address icmpSource, uint8_t icmpTtl, uint8_t icmpType, uint8_t icmpCode, uint32_t icmpInfo)
Handle incoming ICMP packets.
void HandleReadClient(Ptr< Socket > socket)
Handle incoming packets.
Ipv4FragmentationTest(bool broadcast)
Constructor.
void DoRun() override
Implementation to actually run this TestCase.
void HandleReadServer(Ptr< Socket > socket)
Handle incoming packets.
void SetFill(uint8_t *fill, uint32_t fillSize, uint32_t dataSize)
Set the packet fill.
bool m_broadcast
broadcast packets
IPv4 Fragmentation TestSuite.
a polymophic address class
Definition: address.h:101
Identifies a byte tag and a set of bytes within a packet to which the tag applies.
Definition: packet.h:63
uint32_t GetEnd() const
The index is an offset from the start of the packet.
Definition: packet.cc:48
void GetTag(Tag &tag) const
Read the requested tag and store it in the user-provided tag instance.
Definition: packet.cc:54
uint32_t GetStart() const
The index is an offset from the start of the packet.
Definition: packet.cc:42
TypeId GetTypeId() const
Definition: packet.cc:36
Iterator over the set of byte tags in a packet.
Definition: packet.h:56
bool HasNext() const
Definition: packet.cc:72
an Inet address class
void SetIpv4(Ipv4Address address)
aggregate IP/TCP/UDP functionality to existing Nodes.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:42
Access to the IPv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:80
a class to store IPv4 address information on an interface
a class to represent an Ipv4 address mask
Definition: ipv4-address.h:257
holds a vector of ns3::NetDevice pointers
Ptr< NetDevice > Get(uint32_t i) const
Get the Ptr<NetDevice> stored in this container at a given index.
keep track of a set of node pointers.
uint32_t GetId() const
Definition: node.cc:117
void SetAttribute(std::string name, const AttributeValue &value)
Set a single attribute, raising fatal errors if unsuccessful.
Definition: object-base.cc:204
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:861
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:400
Ptr< Packet > Copy() const
performs a COW copy of the packet.
Definition: packet.cc:131
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:960
void AddByteTag(const Tag &tag) const
Tag each byte included in this packet with a new byte tag.
Definition: packet.cc:915
bool PeekPacketTag(Tag &tag) const
Search a matching tag and call Tag::Deserialize if it is found.
Definition: packet.cc:983
ByteTagIterator GetByteTagIterator() const
Returns an iterator over the set of byte tags included in this packet.
Definition: packet.cc:937
build a set of SimpleNetDevice objects
void SetNetDevicePointToPointMode(bool pointToPointMode)
SimpleNetDevice is Broadcast capable and ARP needing.
NetDeviceContainer Install(Ptr< Node > node) const
This method creates an ns3::SimpleChannel with the attributes configured by SimpleNetDeviceHelper::Se...
virtual int Send(Ptr< Packet > p, uint32_t flags)=0
Send data (or dummy data) to the remote host.
virtual bool SetAllowBroadcast(bool allowBroadcast)=0
Configure whether broadcast datagram transmissions are allowed.
void SetRecvCallback(Callback< void, Ptr< Socket >> receivedData)
Notify application when new data is available to be read.
Definition: socket.cc:128
virtual int GetPeerName(Address &address) const =0
Get the peer address of a connected socket.
virtual int Connect(const Address &address)=0
Initiate a connection to a remote host.
virtual Ptr< Node > GetNode() const =0
Return the node this socket is associated with.
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
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 int SendTo(Ptr< Packet > p, uint32_t flags, const Address &toAddress)=0
Send data to a specified peer.
read and write tag data
Definition: tag-buffer.h:52
void WriteU64(uint64_t v)
Definition: tag-buffer.cc:104
uint64_t ReadU64()
Definition: tag-buffer.cc:139
tag a set of bytes in a packet
Definition: tag.h:39
encapsulates test code
Definition: test.h:1060
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
A suite of tests to run.
Definition: test.h:1256
a unique identifier for an interface.
Definition: type-id.h:59
Callback< ObjectBase * > GetConstructor() const
Get the constructor callback.
Definition: type-id.cc:1084
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
std::string GetName() const
Get the name.
Definition: type-id.cc:991
A sockets interface to UDP.
Hold an unsigned integer type.
Definition: uinteger.h:45
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:890
#define NS_TEST_EXPECT_MSG_NE(actual, limit, msg)
Test that an actual and expected (limit) value are not equal and report if not.
Definition: test.h:666
#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:251
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
static Ipv4FragmentationTestSuite g_ipv4fragmentationTestSuite
Static variable for test initialization.
NodeContainer nodes
address
Definition: first.py:47
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:704
channel
Definition: third.py:88
static const uint32_t packetSize
Packet size generated at the AP.