A Discrete-Event Network Simulator
API
ipv4-l3-click-protocol.cc
Go to the documentation of this file.
1 //
2 // Copyright (c) 2006 Georgia Tech Research Corporation
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: George F. Riley <riley@ece.gatech.edu>
18 // Author: Lalith Suresh <suresh.lalith@gmail.com>
19 //
20 
21 #ifdef NS3_CLICK
22 
23 #include "ipv4-l3-click-protocol.h"
24 
25 #include "ns3/arp-l3-protocol.h"
26 #include "ns3/ethernet-header.h"
27 #include "ns3/icmpv4-l4-protocol.h"
28 #include "ns3/ip-l4-protocol.h"
29 #include "ns3/ipv4-click-routing.h"
30 #include "ns3/ipv4-raw-socket-impl.h"
31 #include "ns3/llc-snap-header.h"
32 #include "ns3/loopback-net-device.h"
33 #include "ns3/net-device.h"
34 #include "ns3/node.h"
35 #include "ns3/object-vector.h"
36 #include "ns3/socket.h"
37 #include "ns3/uinteger.h"
38 
39 namespace ns3
40 {
41 
42 NS_LOG_COMPONENT_DEFINE("Ipv4L3ClickProtocol");
43 
44 const uint16_t Ipv4L3ClickProtocol::PROT_NUMBER = 0x0800;
45 
46 NS_OBJECT_ENSURE_REGISTERED(Ipv4L3ClickProtocol);
47 
48 TypeId
50 {
51  static TypeId tid =
52  TypeId("ns3::Ipv4L3ClickProtocol")
53  .SetParent<Ipv4>()
54  .AddConstructor<Ipv4L3ClickProtocol>()
55  .SetGroupName("Click")
56  .AddAttribute(
57  "DefaultTtl",
58  "The TTL value set by default on all outgoing packets generated on this node.",
59  UintegerValue(64),
60  MakeUintegerAccessor(&Ipv4L3ClickProtocol::m_defaultTtl),
61  MakeUintegerChecker<uint8_t>())
62  .AddAttribute("InterfaceList",
63  "The set of Ipv4 interfaces associated to this Ipv4 stack.",
65  MakeObjectVectorAccessor(&Ipv4L3ClickProtocol::m_interfaces),
66  MakeObjectVectorChecker<Ipv4Interface>());
67  return tid;
68 }
69 
70 Ipv4L3ClickProtocol::Ipv4L3ClickProtocol()
71  : m_identification(0)
72 {
73 }
74 
75 Ipv4L3ClickProtocol::~Ipv4L3ClickProtocol()
76 {
77 }
78 
79 void
80 Ipv4L3ClickProtocol::DoDispose()
81 {
82  NS_LOG_FUNCTION(this);
83  for (L4List_t::iterator i = m_protocols.begin(); i != m_protocols.end(); ++i)
84  {
85  i->second = nullptr;
86  }
87  m_protocols.clear();
88 
89  for (Ipv4InterfaceList::iterator i = m_interfaces.begin(); i != m_interfaces.end(); ++i)
90  {
91  *i = nullptr;
92  }
93  m_interfaces.clear();
94  m_reverseInterfacesContainer.clear();
95 
96  m_sockets.clear();
97  m_node = nullptr;
98  m_routingProtocol = nullptr;
99  Object::DoDispose();
100 }
101 
102 void
103 Ipv4L3ClickProtocol::NotifyNewAggregate()
104 {
105  if (!m_node)
106  {
107  Ptr<Node> node = this->GetObject<Node>();
108  // verify that it's a valid node and that
109  // the node has not been set before
110  if (node)
111  {
112  this->SetNode(node);
113  }
114  }
115  Ipv4::NotifyNewAggregate();
116 }
117 
118 void
119 Ipv4L3ClickProtocol::SetRoutingProtocol(Ptr<Ipv4RoutingProtocol> routingProtocol)
120 {
121  NS_LOG_FUNCTION(this);
122  m_routingProtocol = routingProtocol;
123  m_routingProtocol->SetIpv4(this);
124 }
125 
126 Ptr<Ipv4RoutingProtocol>
127 Ipv4L3ClickProtocol::GetRoutingProtocol() const
128 {
129  return m_routingProtocol;
130 }
131 
132 Ptr<Ipv4Interface>
133 Ipv4L3ClickProtocol::GetInterface(uint32_t index) const
134 {
135  NS_LOG_FUNCTION(this << index);
136  if (index < m_interfaces.size())
137  {
138  return m_interfaces[index];
139  }
140  return nullptr;
141 }
142 
143 uint32_t
144 Ipv4L3ClickProtocol::GetNInterfaces() const
145 {
147  return m_interfaces.size();
148 }
149 
150 int32_t
151 Ipv4L3ClickProtocol::GetInterfaceForAddress(Ipv4Address address) const
152 {
153  NS_LOG_FUNCTION(this << address);
154 
155  int32_t interface = 0;
156  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin(); i != m_interfaces.end();
157  i++, interface++)
158  {
159  for (uint32_t j = 0; j < (*i)->GetNAddresses(); j++)
160  {
161  if ((*i)->GetAddress(j).GetLocal() == address)
162  {
163  return interface;
164  }
165  }
166  }
167 
168  return -1;
169 }
170 
171 int32_t
172 Ipv4L3ClickProtocol::GetInterfaceForPrefix(Ipv4Address address, Ipv4Mask mask) const
173 {
174  NS_LOG_FUNCTION(this << address << mask);
175 
176  int32_t interface = 0;
177  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin(); i != m_interfaces.end();
178  i++, interface++)
179  {
180  for (uint32_t j = 0; j < (*i)->GetNAddresses(); j++)
181  {
182  if ((*i)->GetAddress(j).GetLocal().CombineMask(mask) == address.CombineMask(mask))
183  {
184  return interface;
185  }
186  }
187  }
188 
189  return -1;
190 }
191 
192 int32_t
193 Ipv4L3ClickProtocol::GetInterfaceForDevice(Ptr<const NetDevice> device) const
194 {
195  NS_LOG_FUNCTION(this << device->GetIfIndex());
196 
197  Ipv4InterfaceReverseContainer::const_iterator iter = m_reverseInterfacesContainer.find(device);
198  if (iter != m_reverseInterfacesContainer.end())
199  {
200  return (*iter).second;
201  }
202 
203  return -1;
204 }
205 
206 bool
207 Ipv4L3ClickProtocol::IsDestinationAddress(Ipv4Address address, uint32_t iif) const
208 {
209  NS_LOG_FUNCTION(this << address << " " << iif);
210 
211  // First check the incoming interface for a unicast address match
212  for (uint32_t i = 0; i < GetNAddresses(iif); i++)
213  {
214  Ipv4InterfaceAddress iaddr = GetAddress(iif, i);
215  if (address == iaddr.GetLocal())
216  {
217  NS_LOG_LOGIC("For me (destination " << address << " match)");
218  return true;
219  }
220  if (address == iaddr.GetBroadcast())
221  {
222  NS_LOG_LOGIC("For me (interface broadcast address)");
223  return true;
224  }
225  }
226 
227  if (address.IsMulticast())
228  {
229 #ifdef NOTYET
230  if (MulticastCheckGroup(iif, address))
231 #endif
232  if (true)
233  {
234  NS_LOG_LOGIC("For me (Ipv4Addr multicast address");
235  return true;
236  }
237  }
238 
239  if (address.IsBroadcast())
240  {
241  NS_LOG_LOGIC("For me (Ipv4Addr broadcast address)");
242  return true;
243  }
244 
245  if (GetWeakEsModel()) // Check other interfaces
246  {
247  for (uint32_t j = 0; j < GetNInterfaces(); j++)
248  {
249  if (j == uint32_t(iif))
250  {
251  continue;
252  }
253  for (uint32_t i = 0; i < GetNAddresses(j); i++)
254  {
255  Ipv4InterfaceAddress iaddr = GetAddress(j, i);
256  if (address == iaddr.GetLocal())
257  {
258  NS_LOG_LOGIC("For me (destination " << address
259  << " match) on another interface");
260  return true;
261  }
262  // This is a small corner case: match another interface's broadcast address
263  if (address == iaddr.GetBroadcast())
264  {
265  NS_LOG_LOGIC("For me (interface broadcast address on another interface)");
266  return true;
267  }
268  }
269  }
270  }
271  return false;
272 }
273 
274 void
275 Ipv4L3ClickProtocol::SetIpForward(bool forward)
276 {
277  NS_LOG_FUNCTION(this << forward);
278  m_ipForward = forward;
279  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin(); i != m_interfaces.end(); i++)
280  {
281  (*i)->SetForwarding(forward);
282  }
283 }
284 
285 bool
286 Ipv4L3ClickProtocol::GetIpForward() const
287 {
288  return m_ipForward;
289 }
290 
291 void
292 Ipv4L3ClickProtocol::SetWeakEsModel(bool model)
293 {
294  m_weakEsModel = model;
295 }
296 
297 bool
298 Ipv4L3ClickProtocol::GetWeakEsModel() const
299 {
300  return m_weakEsModel;
301 }
302 
303 Ptr<NetDevice>
304 Ipv4L3ClickProtocol::GetNetDevice(uint32_t i)
305 {
306  NS_LOG_FUNCTION(this << i);
307  return GetInterface(i)->GetDevice();
308 }
309 
310 void
311 Ipv4L3ClickProtocol::SetDefaultTtl(uint8_t ttl)
312 {
314  m_defaultTtl = ttl;
315 }
316 
317 void
318 Ipv4L3ClickProtocol::SetupLoopback()
319 {
321 
322  Ptr<Ipv4Interface> interface = CreateObject<Ipv4Interface>();
323  Ptr<LoopbackNetDevice> device = nullptr;
324  // First check whether an existing LoopbackNetDevice exists on the node
325  for (uint32_t i = 0; i < m_node->GetNDevices(); i++)
326  {
327  if ((device = DynamicCast<LoopbackNetDevice>(m_node->GetDevice(i))))
328  {
329  break;
330  }
331  }
332  if (!device)
333  {
334  device = CreateObject<LoopbackNetDevice>();
335  m_node->AddDevice(device);
336  }
337  interface->SetDevice(device);
338  interface->SetNode(m_node);
339  Ipv4InterfaceAddress ifaceAddr =
340  Ipv4InterfaceAddress(Ipv4Address::GetLoopback(), Ipv4Mask::GetLoopback());
341  interface->AddAddress(ifaceAddr);
342  uint32_t index = AddIpv4Interface(interface);
343  Ptr<Node> node = GetObject<Node>();
344  node->RegisterProtocolHandler(MakeCallback(&Ipv4L3ClickProtocol::Receive, this),
345  Ipv4L3ClickProtocol::PROT_NUMBER,
346  device);
347  interface->SetUp();
348  if (m_routingProtocol)
349  {
350  m_routingProtocol->NotifyInterfaceUp(index);
351  }
352 }
353 
354 Ptr<Socket>
355 Ipv4L3ClickProtocol::CreateRawSocket()
356 {
357  NS_LOG_FUNCTION(this);
358  Ptr<Ipv4RawSocketImpl> socket = CreateObject<Ipv4RawSocketImpl>();
359  socket->SetNode(m_node);
360  m_sockets.push_back(socket);
361  return socket;
362 }
363 
364 void
365 Ipv4L3ClickProtocol::DeleteRawSocket(Ptr<Socket> socket)
366 {
367  NS_LOG_FUNCTION(this << socket);
368  for (SocketList::iterator i = m_sockets.begin(); i != m_sockets.end(); ++i)
369  {
370  if ((*i) == socket)
371  {
372  m_sockets.erase(i);
373  return;
374  }
375  }
376 }
377 
378 void
379 Ipv4L3ClickProtocol::SetNode(Ptr<Node> node)
380 {
381  m_node = node;
382  // Add a LoopbackNetDevice if needed, and an Ipv4Interface on top of it
383  SetupLoopback();
384 }
385 
386 bool
387 Ipv4L3ClickProtocol::AddAddress(uint32_t i, Ipv4InterfaceAddress address)
388 {
389  NS_LOG_FUNCTION(this << i << address);
390  Ptr<Ipv4Interface> interface = GetInterface(i);
391  bool retVal = interface->AddAddress(address);
392  if (m_routingProtocol)
393  {
394  m_routingProtocol->NotifyAddAddress(i, address);
395  }
396  return retVal;
397 }
398 
399 Ipv4InterfaceAddress
400 Ipv4L3ClickProtocol::GetAddress(uint32_t interfaceIndex, uint32_t addressIndex) const
401 {
402  NS_LOG_FUNCTION(this << interfaceIndex << addressIndex);
403  Ptr<Ipv4Interface> interface = GetInterface(interfaceIndex);
404  return interface->GetAddress(addressIndex);
405 }
406 
407 uint32_t
408 Ipv4L3ClickProtocol::GetNAddresses(uint32_t interface) const
409 {
410  NS_LOG_FUNCTION(this << interface);
411  Ptr<Ipv4Interface> iface = GetInterface(interface);
412  return iface->GetNAddresses();
413 }
414 
415 bool
416 Ipv4L3ClickProtocol::RemoveAddress(uint32_t i, uint32_t addressIndex)
417 {
418  NS_LOG_FUNCTION(this << i << addressIndex);
419  Ptr<Ipv4Interface> interface = GetInterface(i);
420  Ipv4InterfaceAddress address = interface->RemoveAddress(addressIndex);
421  if (address != Ipv4InterfaceAddress())
422  {
423  if (m_routingProtocol)
424  {
425  m_routingProtocol->NotifyRemoveAddress(i, address);
426  }
427  return true;
428  }
429  return false;
430 }
431 
432 bool
433 Ipv4L3ClickProtocol::RemoveAddress(uint32_t i, Ipv4Address address)
434 {
435  NS_LOG_FUNCTION(this << i << address);
436 
437  if (address == Ipv4Address::GetLoopback())
438  {
439  NS_LOG_WARN("Cannot remove loopback address.");
440  return false;
441  }
442  Ptr<Ipv4Interface> interface = GetInterface(i);
443  Ipv4InterfaceAddress ifAddr = interface->RemoveAddress(address);
444  if (ifAddr != Ipv4InterfaceAddress())
445  {
446  if (m_routingProtocol)
447  {
448  m_routingProtocol->NotifyRemoveAddress(i, ifAddr);
449  }
450  return true;
451  }
452  return false;
453 }
454 
455 Ipv4Address
456 Ipv4L3ClickProtocol::SourceAddressSelection(uint32_t interfaceIdx, Ipv4Address dest)
457 {
458  NS_LOG_FUNCTION(this << interfaceIdx << " " << dest);
459  if (GetNAddresses(interfaceIdx) == 1) // common case
460  {
461  return GetAddress(interfaceIdx, 0).GetLocal();
462  }
463  // no way to determine the scope of the destination, so adopt the
464  // following rule: pick the first available address (index 0) unless
465  // a subsequent address is on link (in which case, pick the primary
466  // address if there are multiple)
467  Ipv4Address candidate = GetAddress(interfaceIdx, 0).GetLocal();
468  for (uint32_t i = 0; i < GetNAddresses(interfaceIdx); i++)
469  {
470  Ipv4InterfaceAddress test = GetAddress(interfaceIdx, i);
471  if (test.GetLocal().CombineMask(test.GetMask()) == dest.CombineMask(test.GetMask()))
472  {
473  if (test.IsSecondary() == false)
474  {
475  return test.GetLocal();
476  }
477  }
478  }
479  return candidate;
480 }
481 
482 Ipv4Address
483 Ipv4L3ClickProtocol::SelectSourceAddress(Ptr<const NetDevice> device,
484  Ipv4Address dst,
485  Ipv4InterfaceAddress::InterfaceAddressScope_e scope)
486 {
487  NS_LOG_FUNCTION(device << dst << scope);
488  Ipv4Address addr("0.0.0.0");
489  Ipv4InterfaceAddress iaddr;
490  bool found = false;
491 
492  if (device)
493  {
494  int32_t i = GetInterfaceForDevice(device);
495  NS_ASSERT_MSG(i >= 0, "No device found on node");
496  for (uint32_t j = 0; j < GetNAddresses(i); j++)
497  {
498  iaddr = GetAddress(i, j);
499  if (iaddr.IsSecondary())
500  {
501  continue;
502  }
503  if (iaddr.GetScope() > scope)
504  {
505  continue;
506  }
507  if (dst.CombineMask(iaddr.GetMask()) == iaddr.GetLocal().CombineMask(iaddr.GetMask()))
508  {
509  return iaddr.GetLocal();
510  }
511  if (!found)
512  {
513  addr = iaddr.GetLocal();
514  found = true;
515  }
516  }
517  }
518  if (found)
519  {
520  return addr;
521  }
522 
523  // Iterate among all interfaces
524  for (uint32_t i = 0; i < GetNInterfaces(); i++)
525  {
526  for (uint32_t j = 0; j < GetNAddresses(i); j++)
527  {
528  iaddr = GetAddress(i, j);
529  if (iaddr.IsSecondary())
530  {
531  continue;
532  }
533  if (iaddr.GetScope() != Ipv4InterfaceAddress::LINK && iaddr.GetScope() <= scope)
534  {
535  return iaddr.GetLocal();
536  }
537  }
538  }
539  NS_LOG_WARN("Could not find source address for " << dst << " and scope " << scope
540  << ", returning 0");
541  return addr;
542 }
543 
544 void
545 Ipv4L3ClickProtocol::SetMetric(uint32_t i, uint16_t metric)
546 {
547  NS_LOG_FUNCTION(i << metric);
548  Ptr<Ipv4Interface> interface = GetInterface(i);
549  interface->SetMetric(metric);
550 }
551 
552 uint16_t
553 Ipv4L3ClickProtocol::GetMetric(uint32_t i) const
554 {
555  NS_LOG_FUNCTION(i);
556  Ptr<Ipv4Interface> interface = GetInterface(i);
557  return interface->GetMetric();
558 }
559 
560 uint16_t
561 Ipv4L3ClickProtocol::GetMtu(uint32_t i) const
562 {
563  NS_LOG_FUNCTION(this << i);
564  Ptr<Ipv4Interface> interface = GetInterface(i);
565  return interface->GetDevice()->GetMtu();
566 }
567 
568 bool
569 Ipv4L3ClickProtocol::IsUp(uint32_t i) const
570 {
571  NS_LOG_FUNCTION(this << i);
572  Ptr<Ipv4Interface> interface = GetInterface(i);
573  return interface->IsUp();
574 }
575 
576 void
577 Ipv4L3ClickProtocol::SetUp(uint32_t i)
578 {
579  NS_LOG_FUNCTION(this << i);
580  Ptr<Ipv4Interface> interface = GetInterface(i);
581  interface->SetUp();
582 
583  if (m_routingProtocol)
584  {
585  m_routingProtocol->NotifyInterfaceUp(i);
586  }
587 }
588 
589 void
590 Ipv4L3ClickProtocol::SetDown(uint32_t ifaceIndex)
591 {
592  NS_LOG_FUNCTION(this << ifaceIndex);
593  Ptr<Ipv4Interface> interface = GetInterface(ifaceIndex);
594  interface->SetDown();
595 
596  if (m_routingProtocol)
597  {
598  m_routingProtocol->NotifyInterfaceDown(ifaceIndex);
599  }
600 }
601 
602 bool
603 Ipv4L3ClickProtocol::IsForwarding(uint32_t i) const
604 {
605  NS_LOG_FUNCTION(this << i);
606  Ptr<Ipv4Interface> interface = GetInterface(i);
607  NS_LOG_LOGIC("Forwarding state: " << interface->IsForwarding());
608  return interface->IsForwarding();
609 }
610 
611 void
612 Ipv4L3ClickProtocol::SetForwarding(uint32_t i, bool val)
613 {
614  NS_LOG_FUNCTION(this << i);
615  Ptr<Ipv4Interface> interface = GetInterface(i);
616  interface->SetForwarding(val);
617 }
618 
619 void
620 Ipv4L3ClickProtocol::SetPromisc(uint32_t i)
621 {
622  NS_ASSERT(i <= m_node->GetNDevices());
623  Ptr<NetDevice> netdev = GetNetDevice(i);
624  NS_ASSERT(netdev);
625  Ptr<Node> node = GetObject<Node>();
626  NS_ASSERT(node);
627  node->RegisterProtocolHandler(MakeCallback(&Ipv4L3ClickProtocol::Receive, this),
628  0,
629  netdev,
630  true);
631 }
632 
633 uint32_t
634 Ipv4L3ClickProtocol::AddInterface(Ptr<NetDevice> device)
635 {
636  NS_LOG_FUNCTION(this << &device);
637  Ptr<Node> node = GetObject<Node>();
638  node->RegisterProtocolHandler(MakeCallback(&Ipv4L3ClickProtocol::Receive, this),
639  Ipv4L3ClickProtocol::PROT_NUMBER,
640  device);
641  node->RegisterProtocolHandler(MakeCallback(&Ipv4L3ClickProtocol::Receive, this),
642  ArpL3Protocol::PROT_NUMBER,
643  device);
644 
645  Ptr<Ipv4Interface> interface = CreateObject<Ipv4Interface>();
646  interface->SetNode(m_node);
647  interface->SetDevice(device);
648  interface->SetForwarding(m_ipForward);
649  return AddIpv4Interface(interface);
650 }
651 
652 uint32_t
653 Ipv4L3ClickProtocol::AddIpv4Interface(Ptr<Ipv4Interface> interface)
654 {
655  NS_LOG_FUNCTION(this << interface);
656  uint32_t index = m_interfaces.size();
657  m_interfaces.push_back(interface);
658  m_reverseInterfacesContainer[interface->GetDevice()] = index;
659  return index;
660 }
661 
665 Ipv4Header
666 Ipv4L3ClickProtocol::BuildHeader(Ipv4Address source,
667  Ipv4Address destination,
668  uint8_t protocol,
669  uint16_t payloadSize,
670  uint8_t ttl,
671  bool mayFragment)
672 {
674  Ipv4Header ipHeader;
675  ipHeader.SetSource(source);
676  ipHeader.SetDestination(destination);
677  ipHeader.SetProtocol(protocol);
678  ipHeader.SetPayloadSize(payloadSize);
679  ipHeader.SetTtl(ttl);
680  if (mayFragment == true)
681  {
682  ipHeader.SetMayFragment();
683  ipHeader.SetIdentification(m_identification);
684  m_identification++;
685  }
686  else
687  {
688  ipHeader.SetDontFragment();
689  // TBD: set to zero here; will cause traces to change
690  ipHeader.SetIdentification(m_identification);
691  m_identification++;
692  }
693  if (Node::ChecksumEnabled())
694  {
695  ipHeader.EnableChecksum();
696  }
697  return ipHeader;
698 }
699 
700 void
701 Ipv4L3ClickProtocol::Send(Ptr<Packet> packet,
702  Ipv4Address source,
703  Ipv4Address destination,
704  uint8_t protocol,
705  Ptr<Ipv4Route> route)
706 {
707  NS_LOG_FUNCTION(this << packet << source << destination << uint32_t(protocol) << route);
708 
709  Ipv4Header ipHeader;
710  bool mayFragment = true;
711  uint8_t ttl = m_defaultTtl;
712  SocketIpTtlTag tag;
713  bool found = packet->RemovePacketTag(tag);
714  if (found)
715  {
716  ttl = tag.GetTtl();
717  }
718 
719  ipHeader = BuildHeader(source, destination, protocol, packet->GetSize(), ttl, mayFragment);
720  Ptr<Ipv4ClickRouting> click = DynamicCast<Ipv4ClickRouting>(m_routingProtocol);
721  if (Node::ChecksumEnabled())
722  {
723  ipHeader.EnableChecksum();
724  }
725  packet->AddHeader(ipHeader);
726  click->Send(packet->Copy(), source, destination);
727 }
728 
729 void
730 Ipv4L3ClickProtocol::SendWithHeader(Ptr<Packet> packet, Ipv4Header ipHeader, Ptr<Ipv4Route> route)
731 {
732  NS_LOG_FUNCTION(this << packet << ipHeader << route);
733 
734  Ptr<Ipv4ClickRouting> click = DynamicCast<Ipv4ClickRouting>(m_routingProtocol);
735  if (Node::ChecksumEnabled())
736  {
737  ipHeader.EnableChecksum();
738  }
739  packet->AddHeader(ipHeader);
740  click->Send(packet->Copy(), ipHeader.GetSource(), ipHeader.GetDestination());
741 }
742 
743 void
744 Ipv4L3ClickProtocol::SendDown(Ptr<Packet> p, int ifid)
745 {
746  // Called by Ipv4ClickRouting.
747 
748  // NetDevice::Send () attaches ethernet headers,
749  // so the one that Click attaches isn't required
750  // but we need the destination address and
751  // protocol values from the header.
752 
753  Ptr<NetDevice> netdev = GetNetDevice(ifid);
754 
755  EthernetHeader header;
756  p->RemoveHeader(header);
757 
758  uint16_t protocol;
759 
760  if (header.GetLengthType() <= 1500)
761  {
762  LlcSnapHeader llc;
763  p->RemoveHeader(llc);
764  protocol = llc.GetType();
765  }
766  else
767  {
768  protocol = header.GetLengthType();
769  }
770 
771  // Use the destination address and protocol obtained
772  // from above to send the packet.
773  netdev->Send(p, header.GetDestination(), protocol);
774 }
775 
776 void
777 Ipv4L3ClickProtocol::Receive(Ptr<NetDevice> device,
778  Ptr<const Packet> p,
779  uint16_t protocol,
780  const Address& from,
781  const Address& to,
782  NetDevice::PacketType packetType)
783 {
784  NS_LOG_FUNCTION(this << device << p << from << to);
785 
786  NS_LOG_LOGIC("Packet from " << from << " received on node " << m_node->GetId());
787 
788  // Forward packet to raw sockets, if any
789  if (protocol == Ipv4L3ClickProtocol::PROT_NUMBER && m_sockets.size() > 0)
790  {
791  Ptr<Packet> packetForRawSocket = p->Copy();
792  int32_t interface = GetInterfaceForDevice(device);
793  NS_ASSERT_MSG(interface != -1,
794  "Received a packet from an interface that is not known to IPv4");
795  Ptr<Ipv4Interface> ipv4Interface = m_interfaces[interface];
796  if (!ipv4Interface->IsUp())
797  {
798  NS_LOG_LOGIC("Dropping received packet -- interface is down");
799  return;
800  }
801 
802  Ipv4Header ipHeader;
803  if (Node::ChecksumEnabled())
804  {
805  ipHeader.EnableChecksum();
806  }
807  packetForRawSocket->RemoveHeader(ipHeader);
808 
809  for (SocketList::iterator i = m_sockets.begin(); i != m_sockets.end(); ++i)
810  {
811  NS_LOG_LOGIC("Forwarding to raw socket");
812  Ptr<Ipv4RawSocketImpl> socket = *i;
813  socket->ForwardUp(packetForRawSocket, ipHeader, ipv4Interface);
814  }
815  }
816 
817  Ptr<Packet> packet = p->Copy();
818 
819  // Add an ethernet frame. This allows
820  // Click to work with csma and wifi
821  EthernetHeader hdr;
822  hdr.SetSource(Mac48Address::ConvertFrom(from));
823  hdr.SetDestination(Mac48Address::ConvertFrom(to));
824  hdr.SetLengthType(protocol);
825  packet->AddHeader(hdr);
826 
827  Ptr<Ipv4ClickRouting> click = DynamicCast<Ipv4ClickRouting>(GetRoutingProtocol());
828  click->Receive(packet->Copy(),
829  Mac48Address::ConvertFrom(device->GetAddress()),
830  Mac48Address::ConvertFrom(to));
831 }
832 
833 void
834 Ipv4L3ClickProtocol::LocalDeliver(Ptr<const Packet> packet, const Ipv4Header& ip, uint32_t iif)
835 {
836  NS_LOG_FUNCTION(this << packet << &ip);
837  Ptr<Packet> p = packet->Copy(); // need to pass a non-const packet up
838 
839  m_localDeliverTrace(ip, packet, iif);
840 
841  Ptr<IpL4Protocol> protocol = GetProtocol(ip.GetProtocol());
842  if (protocol)
843  {
844  // we need to make a copy in the unlikely event we hit the
845  // RX_ENDPOINT_UNREACH codepath
846  Ptr<Packet> copy = p->Copy();
847  enum IpL4Protocol::RxStatus status = protocol->Receive(p, ip, GetInterface(iif));
848  switch (status)
849  {
850  case IpL4Protocol::RX_OK:
851  // fall through
852  case IpL4Protocol::RX_ENDPOINT_CLOSED:
853  // fall through
854  case IpL4Protocol::RX_CSUM_FAILED:
855  break;
856  case IpL4Protocol::RX_ENDPOINT_UNREACH:
857  if (ip.GetDestination().IsBroadcast() == true ||
858  ip.GetDestination().IsMulticast() == true)
859  {
860  break; // Do not reply to broadcast or multicast
861  }
862  // Another case to suppress ICMP is a subnet-directed broadcast
863  bool subnetDirected = false;
864  for (uint32_t i = 0; i < GetNAddresses(iif); i++)
865  {
866  Ipv4InterfaceAddress addr = GetAddress(iif, i);
867  if (addr.GetLocal().CombineMask(addr.GetMask()) ==
868  ip.GetDestination().CombineMask(addr.GetMask()) &&
869  ip.GetDestination().IsSubnetDirectedBroadcast(addr.GetMask()))
870  {
871  subnetDirected = true;
872  }
873  }
874  if (subnetDirected == false)
875  {
876  GetIcmp()->SendDestUnreachPort(ip, copy);
877  }
878  }
879  }
880 }
881 
882 Ptr<Icmpv4L4Protocol>
883 Ipv4L3ClickProtocol::GetIcmp() const
884 {
885  Ptr<IpL4Protocol> prot = GetProtocol(Icmpv4L4Protocol::GetStaticProtocolNumber());
886  if (prot)
887  {
888  return prot->GetObject<Icmpv4L4Protocol>();
889  }
890  else
891  {
892  return nullptr;
893  }
894 }
895 
896 void
897 Ipv4L3ClickProtocol::Insert(Ptr<IpL4Protocol> protocol)
898 {
899  NS_LOG_FUNCTION(this << protocol);
900  L4ListKey_t key = std::make_pair(protocol->GetProtocolNumber(), -1);
901  if (m_protocols.find(key) != m_protocols.end())
902  {
903  NS_LOG_WARN("Overwriting default protocol " << int(protocol->GetProtocolNumber()));
904  }
905  m_protocols[key] = protocol;
906 }
907 
908 void
909 Ipv4L3ClickProtocol::Insert(Ptr<IpL4Protocol> protocol, uint32_t interfaceIndex)
910 {
911  NS_LOG_FUNCTION(this << protocol << interfaceIndex);
912 
913  L4ListKey_t key = std::make_pair(protocol->GetProtocolNumber(), interfaceIndex);
914  if (m_protocols.find(key) != m_protocols.end())
915  {
916  NS_LOG_WARN("Overwriting protocol " << int(protocol->GetProtocolNumber())
917  << " on interface " << int(interfaceIndex));
918  }
919  m_protocols[key] = protocol;
920 }
921 
922 void
923 Ipv4L3ClickProtocol::Remove(Ptr<IpL4Protocol> protocol)
924 {
925  NS_LOG_FUNCTION(this << protocol);
926 
927  L4ListKey_t key = std::make_pair(protocol->GetProtocolNumber(), -1);
928  L4List_t::iterator iter = m_protocols.find(key);
929  if (iter == m_protocols.end())
930  {
931  NS_LOG_WARN("Trying to remove an non-existent default protocol "
932  << int(protocol->GetProtocolNumber()));
933  }
934  else
935  {
936  m_protocols.erase(key);
937  }
938 }
939 
940 void
941 Ipv4L3ClickProtocol::Remove(Ptr<IpL4Protocol> protocol, uint32_t interfaceIndex)
942 {
943  NS_LOG_FUNCTION(this << protocol << interfaceIndex);
944 
945  L4ListKey_t key = std::make_pair(protocol->GetProtocolNumber(), interfaceIndex);
946  L4List_t::iterator iter = m_protocols.find(key);
947  if (iter == m_protocols.end())
948  {
949  NS_LOG_WARN("Trying to remove an non-existent protocol "
950  << int(protocol->GetProtocolNumber()) << " on interface "
951  << int(interfaceIndex));
952  }
953  else
954  {
955  m_protocols.erase(key);
956  }
957 }
958 
959 Ptr<IpL4Protocol>
960 Ipv4L3ClickProtocol::GetProtocol(int protocolNumber) const
961 {
962  NS_LOG_FUNCTION(this << protocolNumber);
963 
964  return GetProtocol(protocolNumber, -1);
965 }
966 
967 Ptr<IpL4Protocol>
968 Ipv4L3ClickProtocol::GetProtocol(int protocolNumber, int32_t interfaceIndex) const
969 {
970  NS_LOG_FUNCTION(this << protocolNumber << interfaceIndex);
971 
972  L4ListKey_t key;
973  L4List_t::const_iterator i;
974  if (interfaceIndex >= 0)
975  {
976  // try the interface-specific protocol.
977  key = std::make_pair(protocolNumber, interfaceIndex);
978  i = m_protocols.find(key);
979  if (i != m_protocols.end())
980  {
981  return i->second;
982  }
983  }
984  // try the generic protocol.
985  key = std::make_pair(protocolNumber, -1);
986  i = m_protocols.find(key);
987  if (i != m_protocols.end())
988  {
989  return i->second;
990  }
991 
992  return nullptr;
993 }
994 
995 } // namespace ns3
996 
997 #endif // NS3_CLICK
Ipv4()
Definition: ipv4.cc:64
static TypeId GetTypeId()
Get the type ID.
Definition: ipv4.cc:35
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
static void Send(Ptr< NetDevice > dev, int level, std::string emuMode)
Definition: fd-emu-send.cc:54
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
ObjectPtrContainerValue ObjectVectorValue
ObjectVectorValue is an alias for ObjectPtrContainerValue.
Definition: object-vector.h:40
Ptr< const AttributeAccessor > MakeObjectVectorAccessor(U T::*memberVariable)
MakeAccessorHelper implementation for ObjectVector.
Definition: object-vector.h:76
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: uinteger.h:46
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:261
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition: object.h:579
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
address
Definition: first.py:40
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:707
void SetUp(char *deviceName)