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