A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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
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
39namespace ns3
40{
41
42NS_LOG_COMPONENT_DEFINE("Ipv4L3ClickProtocol");
43
44const uint16_t Ipv4L3ClickProtocol::PROT_NUMBER = 0x0800;
45
46NS_OBJECT_ENSURE_REGISTERED(Ipv4L3ClickProtocol);
47
48TypeId
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
70Ipv4L3ClickProtocol::Ipv4L3ClickProtocol()
71 : m_identification(0)
72{
73}
74
75Ipv4L3ClickProtocol::~Ipv4L3ClickProtocol()
76{
77}
78
79void
80Ipv4L3ClickProtocol::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
102void
103Ipv4L3ClickProtocol::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
118void
119Ipv4L3ClickProtocol::SetRoutingProtocol(Ptr<Ipv4RoutingProtocol> routingProtocol)
120{
121 NS_LOG_FUNCTION(this);
122 m_routingProtocol = routingProtocol;
123 m_routingProtocol->SetIpv4(this);
124}
125
126Ptr<Ipv4RoutingProtocol>
127Ipv4L3ClickProtocol::GetRoutingProtocol() const
128{
129 return m_routingProtocol;
130}
131
132Ptr<Ipv4Interface>
133Ipv4L3ClickProtocol::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
144Ipv4L3ClickProtocol::GetNInterfaces() const
145{
147 return m_interfaces.size();
148}
149
151Ipv4L3ClickProtocol::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
172Ipv4L3ClickProtocol::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
193Ipv4L3ClickProtocol::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
206bool
207Ipv4L3ClickProtocol::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 {
233 NS_LOG_LOGIC("For me (Ipv4Addr multicast address");
234 return true;
235 }
236 }
237
238 if (address.IsBroadcast())
239 {
240 NS_LOG_LOGIC("For me (Ipv4Addr broadcast address)");
241 return true;
242 }
243
244 if (GetWeakEsModel()) // Check other interfaces
245 {
246 for (uint32_t j = 0; j < GetNInterfaces(); j++)
247 {
248 if (j == uint32_t(iif))
249 {
250 continue;
251 }
252 for (uint32_t i = 0; i < GetNAddresses(j); i++)
253 {
254 Ipv4InterfaceAddress iaddr = GetAddress(j, i);
255 if (address == iaddr.GetLocal())
256 {
257 NS_LOG_LOGIC("For me (destination " << address
258 << " match) on another interface");
259 return true;
260 }
261 // This is a small corner case: match another interface's broadcast address
262 if (address == iaddr.GetBroadcast())
263 {
264 NS_LOG_LOGIC("For me (interface broadcast address on another interface)");
265 return true;
266 }
267 }
268 }
269 }
270 return false;
271}
272
273void
274Ipv4L3ClickProtocol::SetIpForward(bool forward)
275{
276 NS_LOG_FUNCTION(this << forward);
277 m_ipForward = forward;
278 for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin(); i != m_interfaces.end(); i++)
279 {
280 (*i)->SetForwarding(forward);
281 }
282}
283
284bool
285Ipv4L3ClickProtocol::GetIpForward() const
286{
287 return m_ipForward;
288}
289
290void
291Ipv4L3ClickProtocol::SetWeakEsModel(bool model)
292{
293 m_weakEsModel = model;
294}
295
296bool
297Ipv4L3ClickProtocol::GetWeakEsModel() const
298{
299 return m_weakEsModel;
300}
301
302Ptr<NetDevice>
303Ipv4L3ClickProtocol::GetNetDevice(uint32_t i)
304{
305 NS_LOG_FUNCTION(this << i);
306 return GetInterface(i)->GetDevice();
307}
308
309void
310Ipv4L3ClickProtocol::SetDefaultTtl(uint8_t ttl)
311{
313 m_defaultTtl = ttl;
314}
315
316void
317Ipv4L3ClickProtocol::SetupLoopback()
318{
320
321 Ptr<Ipv4Interface> interface = CreateObject<Ipv4Interface>();
322 Ptr<LoopbackNetDevice> device = nullptr;
323 // First check whether an existing LoopbackNetDevice exists on the node
324 for (uint32_t i = 0; i < m_node->GetNDevices(); i++)
325 {
326 if ((device = DynamicCast<LoopbackNetDevice>(m_node->GetDevice(i))))
327 {
328 break;
329 }
330 }
331 if (!device)
332 {
333 device = CreateObject<LoopbackNetDevice>();
334 m_node->AddDevice(device);
335 }
336 interface->SetDevice(device);
337 interface->SetNode(m_node);
338 Ipv4InterfaceAddress ifaceAddr =
339 Ipv4InterfaceAddress(Ipv4Address::GetLoopback(), Ipv4Mask::GetLoopback());
340 interface->AddAddress(ifaceAddr);
341 uint32_t index = AddIpv4Interface(interface);
342 Ptr<Node> node = GetObject<Node>();
343 node->RegisterProtocolHandler(MakeCallback(&Ipv4L3ClickProtocol::Receive, this),
344 Ipv4L3ClickProtocol::PROT_NUMBER,
345 device);
346 interface->SetUp();
347 if (m_routingProtocol)
348 {
349 m_routingProtocol->NotifyInterfaceUp(index);
350 }
351}
352
353Ptr<Socket>
354Ipv4L3ClickProtocol::CreateRawSocket()
355{
356 NS_LOG_FUNCTION(this);
357 Ptr<Ipv4RawSocketImpl> socket = CreateObject<Ipv4RawSocketImpl>();
358 socket->SetNode(m_node);
359 m_sockets.push_back(socket);
360 return socket;
361}
362
363void
364Ipv4L3ClickProtocol::DeleteRawSocket(Ptr<Socket> socket)
365{
366 NS_LOG_FUNCTION(this << socket);
367 for (SocketList::iterator i = m_sockets.begin(); i != m_sockets.end(); ++i)
368 {
369 if ((*i) == socket)
370 {
371 m_sockets.erase(i);
372 return;
373 }
374 }
375}
376
377void
378Ipv4L3ClickProtocol::SetNode(Ptr<Node> node)
379{
380 m_node = node;
381 // Add a LoopbackNetDevice if needed, and an Ipv4Interface on top of it
382 SetupLoopback();
383}
384
385bool
386Ipv4L3ClickProtocol::AddAddress(uint32_t i, Ipv4InterfaceAddress address)
387{
388 NS_LOG_FUNCTION(this << i << address);
389 Ptr<Ipv4Interface> interface = GetInterface(i);
390 bool retVal = interface->AddAddress(address);
391 if (m_routingProtocol)
392 {
393 m_routingProtocol->NotifyAddAddress(i, address);
394 }
395 return retVal;
396}
397
398Ipv4InterfaceAddress
399Ipv4L3ClickProtocol::GetAddress(uint32_t interfaceIndex, uint32_t addressIndex) const
400{
401 NS_LOG_FUNCTION(this << interfaceIndex << addressIndex);
402 Ptr<Ipv4Interface> interface = GetInterface(interfaceIndex);
403 return interface->GetAddress(addressIndex);
404}
405
407Ipv4L3ClickProtocol::GetNAddresses(uint32_t interface) const
408{
409 NS_LOG_FUNCTION(this << interface);
410 Ptr<Ipv4Interface> iface = GetInterface(interface);
411 return iface->GetNAddresses();
412}
413
414bool
415Ipv4L3ClickProtocol::RemoveAddress(uint32_t i, uint32_t addressIndex)
416{
417 NS_LOG_FUNCTION(this << i << addressIndex);
418 Ptr<Ipv4Interface> interface = GetInterface(i);
419 Ipv4InterfaceAddress address = interface->RemoveAddress(addressIndex);
420 if (address != Ipv4InterfaceAddress())
421 {
422 if (m_routingProtocol)
423 {
424 m_routingProtocol->NotifyRemoveAddress(i, address);
425 }
426 return true;
427 }
428 return false;
429}
430
431bool
432Ipv4L3ClickProtocol::RemoveAddress(uint32_t i, Ipv4Address address)
433{
434 NS_LOG_FUNCTION(this << i << address);
435
436 if (address == Ipv4Address::GetLoopback())
437 {
438 NS_LOG_WARN("Cannot remove loopback address.");
439 return false;
440 }
441 Ptr<Ipv4Interface> interface = GetInterface(i);
442 Ipv4InterfaceAddress ifAddr = interface->RemoveAddress(address);
443 if (ifAddr != Ipv4InterfaceAddress())
444 {
445 if (m_routingProtocol)
446 {
447 m_routingProtocol->NotifyRemoveAddress(i, ifAddr);
448 }
449 return true;
450 }
451 return false;
452}
453
454Ipv4Address
455Ipv4L3ClickProtocol::SourceAddressSelection(uint32_t interfaceIdx, Ipv4Address dest)
456{
457 NS_LOG_FUNCTION(this << interfaceIdx << " " << dest);
458 if (GetNAddresses(interfaceIdx) == 1) // common case
459 {
460 return GetAddress(interfaceIdx, 0).GetLocal();
461 }
462 // no way to determine the scope of the destination, so adopt the
463 // following rule: pick the first available address (index 0) unless
464 // a subsequent address is on link (in which case, pick the primary
465 // address if there are multiple)
466 Ipv4Address candidate = GetAddress(interfaceIdx, 0).GetLocal();
467 for (uint32_t i = 0; i < GetNAddresses(interfaceIdx); i++)
468 {
469 Ipv4InterfaceAddress test = GetAddress(interfaceIdx, i);
470 if (test.GetLocal().CombineMask(test.GetMask()) == dest.CombineMask(test.GetMask()))
471 {
472 if (!test.IsSecondary())
473 {
474 return test.GetLocal();
475 }
476 }
477 }
478 return candidate;
479}
480
481Ipv4Address
482Ipv4L3ClickProtocol::SelectSourceAddress(Ptr<const NetDevice> device,
483 Ipv4Address dst,
484 Ipv4InterfaceAddress::InterfaceAddressScope_e scope)
485{
486 NS_LOG_FUNCTION(device << dst << scope);
487 Ipv4Address addr("0.0.0.0");
488 Ipv4InterfaceAddress iaddr;
489 bool found = false;
490
491 if (device)
492 {
493 int32_t i = GetInterfaceForDevice(device);
494 NS_ASSERT_MSG(i >= 0, "No device found on node");
495 for (uint32_t j = 0; j < GetNAddresses(i); j++)
496 {
497 iaddr = GetAddress(i, j);
498 if (iaddr.IsSecondary())
499 {
500 continue;
501 }
502 if (iaddr.GetScope() > scope)
503 {
504 continue;
505 }
506 if (dst.CombineMask(iaddr.GetMask()) == iaddr.GetLocal().CombineMask(iaddr.GetMask()))
507 {
508 return iaddr.GetLocal();
509 }
510 if (!found)
511 {
512 addr = iaddr.GetLocal();
513 found = true;
514 }
515 }
516 }
517 if (found)
518 {
519 return addr;
520 }
521
522 // Iterate among all interfaces
523 for (uint32_t i = 0; i < GetNInterfaces(); i++)
524 {
525 for (uint32_t j = 0; j < GetNAddresses(i); j++)
526 {
527 iaddr = GetAddress(i, j);
528 if (iaddr.IsSecondary())
529 {
530 continue;
531 }
532 if (iaddr.GetScope() != Ipv4InterfaceAddress::LINK && iaddr.GetScope() <= scope)
533 {
534 return iaddr.GetLocal();
535 }
536 }
537 }
538 NS_LOG_WARN("Could not find source address for " << dst << " and scope " << scope
539 << ", returning 0");
540 return addr;
541}
542
543void
544Ipv4L3ClickProtocol::SetMetric(uint32_t i, uint16_t metric)
545{
546 NS_LOG_FUNCTION(i << metric);
547 Ptr<Ipv4Interface> interface = GetInterface(i);
548 interface->SetMetric(metric);
549}
550
551uint16_t
552Ipv4L3ClickProtocol::GetMetric(uint32_t i) const
553{
555 Ptr<Ipv4Interface> interface = GetInterface(i);
556 return interface->GetMetric();
557}
558
559uint16_t
560Ipv4L3ClickProtocol::GetMtu(uint32_t i) const
561{
562 NS_LOG_FUNCTION(this << i);
563 Ptr<Ipv4Interface> interface = GetInterface(i);
564 return interface->GetDevice()->GetMtu();
565}
566
567bool
568Ipv4L3ClickProtocol::IsUp(uint32_t i) const
569{
570 NS_LOG_FUNCTION(this << i);
571 Ptr<Ipv4Interface> interface = GetInterface(i);
572 return interface->IsUp();
573}
574
575void
576Ipv4L3ClickProtocol::SetUp(uint32_t i)
577{
578 NS_LOG_FUNCTION(this << i);
579 Ptr<Ipv4Interface> interface = GetInterface(i);
580 interface->SetUp();
581
582 if (m_routingProtocol)
583 {
584 m_routingProtocol->NotifyInterfaceUp(i);
585 }
586}
587
588void
589Ipv4L3ClickProtocol::SetDown(uint32_t ifaceIndex)
590{
591 NS_LOG_FUNCTION(this << ifaceIndex);
592 Ptr<Ipv4Interface> interface = GetInterface(ifaceIndex);
593 interface->SetDown();
594
595 if (m_routingProtocol)
596 {
597 m_routingProtocol->NotifyInterfaceDown(ifaceIndex);
598 }
599}
600
601bool
602Ipv4L3ClickProtocol::IsForwarding(uint32_t i) const
603{
604 NS_LOG_FUNCTION(this << i);
605 Ptr<Ipv4Interface> interface = GetInterface(i);
606 NS_LOG_LOGIC("Forwarding state: " << interface->IsForwarding());
607 return interface->IsForwarding();
608}
609
610void
611Ipv4L3ClickProtocol::SetForwarding(uint32_t i, bool val)
612{
613 NS_LOG_FUNCTION(this << i);
614 Ptr<Ipv4Interface> interface = GetInterface(i);
615 interface->SetForwarding(val);
616}
617
618void
619Ipv4L3ClickProtocol::SetPromisc(uint32_t i)
620{
621 NS_ASSERT(i <= m_node->GetNDevices());
622 Ptr<NetDevice> netdev = GetNetDevice(i);
623 NS_ASSERT(netdev);
624 Ptr<Node> node = GetObject<Node>();
625 NS_ASSERT(node);
626 node->RegisterProtocolHandler(MakeCallback(&Ipv4L3ClickProtocol::Receive, this),
627 0,
628 netdev,
629 true);
630}
631
633Ipv4L3ClickProtocol::AddInterface(Ptr<NetDevice> device)
634{
635 NS_LOG_FUNCTION(this << &device);
636 Ptr<Node> node = GetObject<Node>();
637 node->RegisterProtocolHandler(MakeCallback(&Ipv4L3ClickProtocol::Receive, this),
638 Ipv4L3ClickProtocol::PROT_NUMBER,
639 device);
640 node->RegisterProtocolHandler(MakeCallback(&Ipv4L3ClickProtocol::Receive, this),
641 ArpL3Protocol::PROT_NUMBER,
642 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(Ipv4Address source,
666 Ipv4Address destination,
667 uint8_t protocol,
668 uint16_t payloadSize,
669 uint8_t ttl,
670 bool mayFragment)
671{
673 Ipv4Header ipHeader;
674 ipHeader.SetSource(source);
675 ipHeader.SetDestination(destination);
676 ipHeader.SetProtocol(protocol);
677 ipHeader.SetPayloadSize(payloadSize);
678 ipHeader.SetTtl(ttl);
679 if (mayFragment)
680 {
681 ipHeader.SetMayFragment();
682 ipHeader.SetIdentification(m_identification);
683 m_identification++;
684 }
685 else
686 {
687 ipHeader.SetDontFragment();
688 // TBD: set to zero here; will cause traces to change
689 ipHeader.SetIdentification(m_identification);
690 m_identification++;
691 }
692 if (Node::ChecksumEnabled())
693 {
694 ipHeader.EnableChecksum();
695 }
696 return ipHeader;
697}
698
699void
700Ipv4L3ClickProtocol::Send(Ptr<Packet> packet,
701 Ipv4Address source,
702 Ipv4Address destination,
703 uint8_t protocol,
704 Ptr<Ipv4Route> route)
705{
706 NS_LOG_FUNCTION(this << packet << source << destination << uint32_t(protocol) << route);
707
708 Ipv4Header ipHeader;
709 bool mayFragment = true;
710 uint8_t ttl = m_defaultTtl;
711 SocketIpTtlTag tag;
712 bool found = packet->RemovePacketTag(tag);
713 if (found)
714 {
715 ttl = tag.GetTtl();
716 }
717
718 ipHeader = BuildHeader(source, destination, protocol, packet->GetSize(), ttl, mayFragment);
719 Ptr<Ipv4ClickRouting> click = DynamicCast<Ipv4ClickRouting>(m_routingProtocol);
720 if (Node::ChecksumEnabled())
721 {
722 ipHeader.EnableChecksum();
723 }
724 packet->AddHeader(ipHeader);
725 click->Send(packet->Copy(), source, destination);
726}
727
728void
729Ipv4L3ClickProtocol::SendWithHeader(Ptr<Packet> packet, Ipv4Header ipHeader, Ptr<Ipv4Route> route)
730{
731 NS_LOG_FUNCTION(this << packet << ipHeader << route);
732
733 Ptr<Ipv4ClickRouting> click = DynamicCast<Ipv4ClickRouting>(m_routingProtocol);
734 if (Node::ChecksumEnabled())
735 {
736 ipHeader.EnableChecksum();
737 }
738 packet->AddHeader(ipHeader);
739 click->Send(packet->Copy(), ipHeader.GetSource(), ipHeader.GetDestination());
740}
741
742void
743Ipv4L3ClickProtocol::SendDown(Ptr<Packet> p, int ifid)
744{
745 // Called by Ipv4ClickRouting.
746
747 // NetDevice::Send () attaches ethernet headers,
748 // so the one that Click attaches isn't required
749 // but we need the destination address and
750 // protocol values from the header.
751
752 Ptr<NetDevice> netdev = GetNetDevice(ifid);
753
754 EthernetHeader header;
755 p->RemoveHeader(header);
756
757 uint16_t protocol;
758
759 if (header.GetLengthType() <= 1500)
760 {
761 LlcSnapHeader llc;
762 p->RemoveHeader(llc);
763 protocol = llc.GetType();
764 }
765 else
766 {
767 protocol = header.GetLengthType();
768 }
769
770 // Use the destination address and protocol obtained
771 // from above to send the packet.
772 netdev->Send(p, header.GetDestination(), protocol);
773}
774
775void
776Ipv4L3ClickProtocol::Receive(Ptr<NetDevice> device,
777 Ptr<const Packet> p,
778 uint16_t protocol,
779 const Address& from,
780 const Address& to,
781 NetDevice::PacketType packetType)
782{
783 NS_LOG_FUNCTION(this << device << p << from << to);
784
785 NS_LOG_LOGIC("Packet from " << from << " received on node " << m_node->GetId());
786
787 // Forward packet to raw sockets, if any
788 if (protocol == Ipv4L3ClickProtocol::PROT_NUMBER && !m_sockets.empty())
789 {
790 Ptr<Packet> packetForRawSocket = p->Copy();
791 int32_t interface = GetInterfaceForDevice(device);
792 NS_ASSERT_MSG(interface != -1,
793 "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 for (SocketList::iterator i = m_sockets.begin(); i != m_sockets.end(); ++i)
809 {
810 NS_LOG_LOGIC("Forwarding to raw socket");
811 Ptr<Ipv4RawSocketImpl> socket = *i;
812 socket->ForwardUp(packetForRawSocket, ipHeader, ipv4Interface);
813 }
814 }
815
816 Ptr<Packet> packet = p->Copy();
817
818 // Add an ethernet frame. This allows
819 // Click to work with csma and wifi
820 EthernetHeader hdr;
821 hdr.SetSource(Mac48Address::ConvertFrom(from));
822 hdr.SetDestination(Mac48Address::ConvertFrom(to));
823 hdr.SetLengthType(protocol);
824 packet->AddHeader(hdr);
825
826 Ptr<Ipv4ClickRouting> click = DynamicCast<Ipv4ClickRouting>(GetRoutingProtocol());
827 click->Receive(packet->Copy(),
828 Mac48Address::ConvertFrom(device->GetAddress()),
829 Mac48Address::ConvertFrom(to));
830}
831
832void
833Ipv4L3ClickProtocol::LocalDeliver(Ptr<const Packet> packet, const Ipv4Header& ip, uint32_t iif)
834{
835 NS_LOG_FUNCTION(this << packet << &ip);
836 Ptr<Packet> p = packet->Copy(); // need to pass a non-const packet up
837
838 m_localDeliverTrace(ip, packet, iif);
839
840 Ptr<IpL4Protocol> protocol = GetProtocol(ip.GetProtocol());
841 if (protocol)
842 {
843 // we need to make a copy in the unlikely event we hit the
844 // RX_ENDPOINT_UNREACH codepath
845 Ptr<Packet> copy = p->Copy();
846 IpL4Protocol::RxStatus status = 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() || ip.GetDestination().IsMulticast())
857 {
858 break; // Do not reply to broadcast or multicast
859 }
860 // Another case to suppress ICMP is a subnet-directed broadcast
861 bool subnetDirected = false;
862 for (uint32_t i = 0; i < GetNAddresses(iif); i++)
863 {
864 Ipv4InterfaceAddress addr = GetAddress(iif, i);
865 if (addr.GetLocal().CombineMask(addr.GetMask()) ==
866 ip.GetDestination().CombineMask(addr.GetMask()) &&
867 ip.GetDestination().IsSubnetDirectedBroadcast(addr.GetMask()))
868 {
869 subnetDirected = true;
870 }
871 }
872 if (!subnetDirected)
873 {
874 GetIcmp()->SendDestUnreachPort(ip, copy);
875 }
876 }
877 }
878}
879
880Ptr<Icmpv4L4Protocol>
881Ipv4L3ClickProtocol::GetIcmp() const
882{
883 Ptr<IpL4Protocol> prot = GetProtocol(Icmpv4L4Protocol::GetStaticProtocolNumber());
884 if (prot)
885 {
886 return prot->GetObject<Icmpv4L4Protocol>();
887 }
888 else
889 {
890 return nullptr;
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())
915 << " on interface " << int(interfaceIndex));
916 }
917 m_protocols[key] = protocol;
918}
919
920void
921Ipv4L3ClickProtocol::Remove(Ptr<IpL4Protocol> protocol)
922{
923 NS_LOG_FUNCTION(this << protocol);
924
925 L4ListKey_t key = std::make_pair(protocol->GetProtocolNumber(), -1);
926 L4List_t::iterator iter = m_protocols.find(key);
927 if (iter == m_protocols.end())
928 {
929 NS_LOG_WARN("Trying to remove an non-existent default protocol "
930 << int(protocol->GetProtocolNumber()));
931 }
932 else
933 {
934 m_protocols.erase(key);
935 }
936}
937
938void
939Ipv4L3ClickProtocol::Remove(Ptr<IpL4Protocol> protocol, uint32_t interfaceIndex)
940{
941 NS_LOG_FUNCTION(this << protocol << interfaceIndex);
942
943 L4ListKey_t key = std::make_pair(protocol->GetProtocolNumber(), interfaceIndex);
944 L4List_t::iterator iter = m_protocols.find(key);
945 if (iter == m_protocols.end())
946 {
947 NS_LOG_WARN("Trying to remove an non-existent protocol "
948 << int(protocol->GetProtocolNumber()) << " on interface "
949 << int(interfaceIndex));
950 }
951 else
952 {
953 m_protocols.erase(key);
954 }
955}
956
957Ptr<IpL4Protocol>
958Ipv4L3ClickProtocol::GetProtocol(int protocolNumber) const
959{
960 NS_LOG_FUNCTION(this << protocolNumber);
961
962 return GetProtocol(protocolNumber, -1);
963}
964
965Ptr<IpL4Protocol>
966Ipv4L3ClickProtocol::GetProtocol(int protocolNumber, int32_t interfaceIndex) const
967{
968 NS_LOG_FUNCTION(this << protocolNumber << interfaceIndex);
969
970 L4ListKey_t key;
971 L4List_t::const_iterator i;
972 if (interfaceIndex >= 0)
973 {
974 // try the interface-specific protocol.
975 key = std::make_pair(protocolNumber, interfaceIndex);
976 i = m_protocols.find(key);
977 if (i != m_protocols.end())
978 {
979 return i->second;
980 }
981 }
982 // try the generic protocol.
983 key = std::make_pair(protocolNumber, -1);
984 i = m_protocols.find(key);
985 if (i != m_protocols.end())
986 {
987 return i->second;
988 }
989
990 return nullptr;
991}
992
993} // namespace ns3
994
995#endif // NS3_CLICK
Ipv4()
Definition: ipv4.cc:64
static TypeId GetTypeId()
Get the type ID.
Definition: object-base.cc:62
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:936
#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)
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
ns 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:702
-ns3 Test suite for the ns3 wrapper script