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 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
274void
275Ipv4L3ClickProtocol::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
285bool
286Ipv4L3ClickProtocol::GetIpForward() const
287{
288 return m_ipForward;
289}
290
291void
292Ipv4L3ClickProtocol::SetWeakEsModel(bool model)
293{
294 m_weakEsModel = model;
295}
296
297bool
298Ipv4L3ClickProtocol::GetWeakEsModel() const
299{
300 return m_weakEsModel;
301}
302
303Ptr<NetDevice>
304Ipv4L3ClickProtocol::GetNetDevice(uint32_t i)
305{
306 NS_LOG_FUNCTION(this << i);
307 return GetInterface(i)->GetDevice();
308}
309
310void
311Ipv4L3ClickProtocol::SetDefaultTtl(uint8_t ttl)
312{
314 m_defaultTtl = ttl;
315}
316
317void
318Ipv4L3ClickProtocol::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
354Ptr<Socket>
355Ipv4L3ClickProtocol::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
364void
365Ipv4L3ClickProtocol::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
378void
379Ipv4L3ClickProtocol::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
386bool
387Ipv4L3ClickProtocol::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
399Ipv4InterfaceAddress
400Ipv4L3ClickProtocol::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
408Ipv4L3ClickProtocol::GetNAddresses(uint32_t interface) const
409{
410 NS_LOG_FUNCTION(this << interface);
411 Ptr<Ipv4Interface> iface = GetInterface(interface);
412 return iface->GetNAddresses();
413}
414
415bool
416Ipv4L3ClickProtocol::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
432bool
433Ipv4L3ClickProtocol::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
455Ipv4Address
456Ipv4L3ClickProtocol::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
482Ipv4Address
483Ipv4L3ClickProtocol::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
544void
545Ipv4L3ClickProtocol::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
552uint16_t
553Ipv4L3ClickProtocol::GetMetric(uint32_t i) const
554{
556 Ptr<Ipv4Interface> interface = GetInterface(i);
557 return interface->GetMetric();
558}
559
560uint16_t
561Ipv4L3ClickProtocol::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
568bool
569Ipv4L3ClickProtocol::IsUp(uint32_t i) const
570{
571 NS_LOG_FUNCTION(this << i);
572 Ptr<Ipv4Interface> interface = GetInterface(i);
573 return interface->IsUp();
574}
575
576void
577Ipv4L3ClickProtocol::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
589void
590Ipv4L3ClickProtocol::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
602bool
603Ipv4L3ClickProtocol::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
611void
612Ipv4L3ClickProtocol::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
619void
620Ipv4L3ClickProtocol::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
634Ipv4L3ClickProtocol::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
653Ipv4L3ClickProtocol::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
665Ipv4Header
666Ipv4L3ClickProtocol::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
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}
728
729void
730Ipv4L3ClickProtocol::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
743void
744Ipv4L3ClickProtocol::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
776void
777Ipv4L3ClickProtocol::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
833void
834Ipv4L3ClickProtocol::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
882Ptr<Icmpv4L4Protocol>
883Ipv4L3ClickProtocol::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
896void
897Ipv4L3ClickProtocol::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
908void
909Ipv4L3ClickProtocol::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
922void
923Ipv4L3ClickProtocol::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
940void
941Ipv4L3ClickProtocol::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
959Ptr<IpL4Protocol>
960Ipv4L3ClickProtocol::GetProtocol(int protocolNumber) const
961{
962 NS_LOG_FUNCTION(this << protocolNumber);
963
964 return GetProtocol(protocolNumber, -1);
965}
966
967Ptr<IpL4Protocol>
968Ipv4L3ClickProtocol::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: object-base.cc:62
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
#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:707
-ns3 Test suite for the ns3 wrapper script