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
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
40namespace ns3 {
41
42NS_LOG_COMPONENT_DEFINE ("Ipv4L3ClickProtocol");
43
44const uint16_t Ipv4L3ClickProtocol::PROT_NUMBER = 0x0800;
45
46
47NS_OBJECT_ENSURE_REGISTERED (Ipv4L3ClickProtocol);
48
49TypeId
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
68Ipv4L3ClickProtocol::Ipv4L3ClickProtocol ()
69 : m_identification (0)
70{
71}
72
73Ipv4L3ClickProtocol::~Ipv4L3ClickProtocol ()
74{
75}
76
77void
78Ipv4L3ClickProtocol::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
100void
101Ipv4L3ClickProtocol::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
116void
117Ipv4L3ClickProtocol::SetRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol)
118{
119 NS_LOG_FUNCTION (this);
120 m_routingProtocol = routingProtocol;
121 m_routingProtocol->SetIpv4 (this);
122}
123
124
125Ptr<Ipv4RoutingProtocol>
126Ipv4L3ClickProtocol::GetRoutingProtocol (void) const
127{
128 return m_routingProtocol;
129}
130
131Ptr<Ipv4Interface>
132Ipv4L3ClickProtocol::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
143Ipv4L3ClickProtocol::GetNInterfaces (void) const
144{
146 return m_interfaces.size ();
147}
148
150Ipv4L3ClickProtocol::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
173Ipv4L3ClickProtocol::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
197Ipv4L3ClickProtocol::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
211bool
212Ipv4L3ClickProtocol::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
278void
279Ipv4L3ClickProtocol::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
289bool
290Ipv4L3ClickProtocol::GetIpForward (void) const
291{
292 return m_ipForward;
293}
294
295void
296Ipv4L3ClickProtocol::SetWeakEsModel (bool model)
297{
298 m_weakEsModel = model;
299}
300
301bool
302Ipv4L3ClickProtocol::GetWeakEsModel (void) const
303{
304 return m_weakEsModel;
305}
306
307Ptr<NetDevice>
308Ipv4L3ClickProtocol::GetNetDevice (uint32_t i)
309{
310 NS_LOG_FUNCTION (this << i);
311 return GetInterface (i)->GetDevice ();
312}
313
314void
315Ipv4L3ClickProtocol::SetDefaultTtl (uint8_t ttl)
316{
318 m_defaultTtl = ttl;
319}
320
321void
322Ipv4L3ClickProtocol::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
356Ptr<Socket>
357Ipv4L3ClickProtocol::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}
365void
366Ipv4L3ClickProtocol::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
381void
382Ipv4L3ClickProtocol::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
389bool
390Ipv4L3ClickProtocol::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
402Ipv4InterfaceAddress
403Ipv4L3ClickProtocol::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
411Ipv4L3ClickProtocol::GetNAddresses (uint32_t interface) const
412{
413 NS_LOG_FUNCTION (this << interface);
414 Ptr<Ipv4Interface> iface = GetInterface (interface);
415 return iface->GetNAddresses ();
416}
417
418bool
419Ipv4L3ClickProtocol::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
435bool
436Ipv4L3ClickProtocol::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
458Ipv4Address
459Ipv4L3ClickProtocol::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
485Ipv4Address
486Ipv4L3ClickProtocol::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
547void
548Ipv4L3ClickProtocol::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
555uint16_t
556Ipv4L3ClickProtocol::GetMetric (uint32_t i) const
557{
558 NS_LOG_FUNCTION (i);
559 Ptr<Ipv4Interface> interface = GetInterface (i);
560 return interface->GetMetric ();
561}
562
563uint16_t
564Ipv4L3ClickProtocol::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
571bool
572Ipv4L3ClickProtocol::IsUp (uint32_t i) const
573{
574 NS_LOG_FUNCTION (this << i);
575 Ptr<Ipv4Interface> interface = GetInterface (i);
576 return interface->IsUp ();
577}
578
579void
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
592void
593Ipv4L3ClickProtocol::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
605bool
606Ipv4L3ClickProtocol::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
614void
615Ipv4L3ClickProtocol::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
622void
623Ipv4L3ClickProtocol::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
635Ipv4L3ClickProtocol::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
652Ipv4L3ClickProtocol::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
664Ipv4Header
665Ipv4L3ClickProtocol::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
700void
701Ipv4L3ClickProtocol::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
730void
731Ipv4L3ClickProtocol::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
746void
747Ipv4L3ClickProtocol::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
779void
780Ipv4L3ClickProtocol::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
831void
832Ipv4L3ClickProtocol::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
880Ptr<Icmpv4L4Protocol>
881Ipv4L3ClickProtocol::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
894void
895Ipv4L3ClickProtocol::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
906void
907Ipv4L3ClickProtocol::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
919void
920Ipv4L3ClickProtocol::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
936void
937Ipv4L3ClickProtocol::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
953Ptr<IpL4Protocol>
954Ipv4L3ClickProtocol::GetProtocol (int protocolNumber) const
955{
956 NS_LOG_FUNCTION (this << protocolNumber);
957
958 return GetProtocol (protocolNumber, -1);
959}
960
961Ptr<IpL4Protocol>
962Ipv4L3ClickProtocol::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)
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
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)