A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
arp-l3-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 INRIA
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: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  */
20 #include "ns3/packet.h"
21 #include "ns3/log.h"
22 #include "ns3/node.h"
23 #include "ns3/net-device.h"
24 #include "ns3/object-vector.h"
25 #include "ns3/trace-source-accessor.h"
26 
27 #include "ipv4-l3-protocol.h"
28 #include "arp-l3-protocol.h"
29 #include "arp-header.h"
30 #include "arp-cache.h"
31 #include "ipv4-interface.h"
32 
33 NS_LOG_COMPONENT_DEFINE ("ArpL3Protocol");
34 
35 namespace ns3 {
36 
37 const uint16_t ArpL3Protocol::PROT_NUMBER = 0x0806;
38 
39 NS_OBJECT_ENSURE_REGISTERED (ArpL3Protocol);
40 
41 TypeId
43 {
44  static TypeId tid = TypeId ("ns3::ArpL3Protocol")
45  .SetParent<Object> ()
46  .AddConstructor<ArpL3Protocol> ()
47  .AddAttribute ("CacheList",
48  "The list of ARP caches",
51  MakeObjectVectorChecker<ArpCache> ())
52  .AddTraceSource ("Drop",
53  "Packet dropped because not enough room in pending queue for a specific cache entry.",
55  ;
56  return tid;
57 }
58 
60 {
61  NS_LOG_FUNCTION (this);
62 }
63 
65 {
66  NS_LOG_FUNCTION (this);
67 }
68 
69 void
71 {
72  NS_LOG_FUNCTION (this << node);
73  m_node = node;
74 }
75 
76 /*
77  * This method is called by AddAgregate and completes the aggregation
78  * by setting the node in the ipv4 stack
79  */
80 void
82 {
83  NS_LOG_FUNCTION (this);
84  if (m_node == 0)
85  {
86  Ptr<Node>node = this->GetObject<Node> ();
87  //verify that it's a valid node and that
88  //the node was not set before
89  if (node != 0)
90  {
91  this->SetNode (node);
92  }
93  }
95 }
96 
97 void
99 {
100  NS_LOG_FUNCTION (this);
101  for (CacheList::iterator i = m_cacheList.begin (); i != m_cacheList.end (); ++i)
102  {
103  Ptr<ArpCache> cache = *i;
104  cache->Dispose ();
105  }
106  m_cacheList.clear ();
107  m_node = 0;
109 }
110 
113 {
114  NS_LOG_FUNCTION (this << device << interface);
116  Ptr<ArpCache> cache = CreateObject<ArpCache> ();
117  cache->SetDevice (device, interface);
118  NS_ASSERT (device->IsBroadcast ());
120  cache->SetArpRequestCallback (MakeCallback (&ArpL3Protocol::SendArpRequest, this));
121  m_cacheList.push_back (cache);
122  return cache;
123 }
124 
127 {
128  NS_LOG_FUNCTION (this << device);
129  for (CacheList::const_iterator i = m_cacheList.begin (); i != m_cacheList.end (); i++)
130  {
131  if ((*i)->GetDevice () == device)
132  {
133  return *i;
134  }
135  }
136  NS_ASSERT (false);
137  // quiet compiler
138  return 0;
139 }
140 
141 void
142 ArpL3Protocol::Receive (Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol, const Address &from,
143  const Address &to, NetDevice::PacketType packetType)
144 {
145  NS_LOG_FUNCTION (this << device << p->GetSize () << protocol << from << to << packetType);
146 
147  Ptr<Packet> packet = p->Copy ();
148 
149  NS_LOG_LOGIC ("ARP: received packet of size "<< packet->GetSize ());
150 
151  Ptr<ArpCache> cache = FindCache (device);
152 
153  //
154  // If we're connected to a real world network, then some of the fields sizes
155  // in an ARP packet can vary in ways not seen in simulations. We need to be
156  // able to detect ARP packets with headers we don't recongnize and not process
157  // them instead of crashing. The ArpHeader will return 0 if it can't deal
158  // with the received header.
159  //
160  ArpHeader arp;
161  uint32_t size = packet->RemoveHeader (arp);
162  if (size == 0)
163  {
164  NS_LOG_LOGIC ("ARP: Cannot remove ARP header");
165  return;
166  }
167  NS_LOG_LOGIC ("ARP: received "<< (arp.IsRequest () ? "request" : "reply") <<
168  " node="<<m_node->GetId ()<<", got request from " <<
169  arp.GetSourceIpv4Address () << " for address " <<
170  arp.GetDestinationIpv4Address () << "; we have addresses: ");
171  for (uint32_t i = 0; i < cache->GetInterface ()->GetNAddresses (); i++)
172  {
173  NS_LOG_LOGIC (cache->GetInterface ()->GetAddress (i).GetLocal () << ", ");
174  }
175 
180  bool found = false;
181  for (uint32_t i = 0; i < cache->GetInterface ()->GetNAddresses (); i++)
182  {
183  if (arp.IsRequest () && arp.GetDestinationIpv4Address () ==
184  cache->GetInterface ()->GetAddress (i).GetLocal ())
185  {
186  found = true;
187  NS_LOG_LOGIC ("node="<<m_node->GetId () <<", got request from " <<
188  arp.GetSourceIpv4Address () << " -- send reply");
190  arp.GetSourceHardwareAddress ());
191  break;
192  }
193  else if (arp.IsReply () &&
194  arp.GetDestinationIpv4Address ().IsEqual (cache->GetInterface ()->GetAddress (i).GetLocal ()) &&
195  arp.GetDestinationHardwareAddress () == device->GetAddress ())
196  {
197  found = true;
198  Ipv4Address from = arp.GetSourceIpv4Address ();
199  ArpCache::Entry *entry = cache->Lookup (from);
200  if (entry != 0)
201  {
202  if (entry->IsWaitReply ())
203  {
204  NS_LOG_LOGIC ("node="<< m_node->GetId () <<
205  ", got reply from " << arp.GetSourceIpv4Address ()
206  << " for waiting entry -- flush");
207  Address from_mac = arp.GetSourceHardwareAddress ();
208  entry->MarkAlive (from_mac);
209  Ptr<Packet> pending = entry->DequeuePending ();
210  while (pending != 0)
211  {
212  cache->GetInterface ()->Send (pending,
213  arp.GetSourceIpv4Address ());
214  pending = entry->DequeuePending ();
215  }
216  }
217  else
218  {
219  // ignore this reply which might well be an attempt
220  // at poisening my arp cache.
221  NS_LOG_LOGIC ("node="<<m_node->GetId ()<<", got reply from " <<
222  arp.GetSourceIpv4Address () <<
223  " for non-waiting entry -- drop");
224  m_dropTrace (packet);
225  }
226  }
227  else
228  {
229  NS_LOG_LOGIC ("node="<<m_node->GetId ()<<", got reply for unknown entry -- drop");
230  m_dropTrace (packet);
231  }
232  break;
233  }
234  }
235  if (found == false)
236  {
237  NS_LOG_LOGIC ("node="<<m_node->GetId ()<<", got request from " <<
238  arp.GetSourceIpv4Address () << " for unknown address " <<
239  arp.GetDestinationIpv4Address () << " -- drop");
240  }
241 }
242 
243 bool
245  Ptr<NetDevice> device,
246  Ptr<ArpCache> cache,
247  Address *hardwareDestination)
248 {
249  NS_LOG_FUNCTION (this << packet << destination << device << cache << hardwareDestination);
250  ArpCache::Entry *entry = cache->Lookup (destination);
251  if (entry != 0)
252  {
253  if (entry->IsExpired ())
254  {
255  if (entry->IsDead ())
256  {
257  NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
258  ", dead entry for " << destination << " expired -- send arp request");
259  entry->MarkWaitReply (packet);
260  SendArpRequest (cache, destination);
261  }
262  else if (entry->IsAlive ())
263  {
264  NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
265  ", alive entry for " << destination << " expired -- send arp request");
266  entry->MarkWaitReply (packet);
267  SendArpRequest (cache, destination);
268  }
269  else if (entry->IsWaitReply ())
270  {
271  NS_FATAL_ERROR ("Test for possibly unreachable code-- please file a bug report, with a test case, if this is ever hit");
272  }
273  }
274  else
275  {
276  if (entry->IsDead ())
277  {
278  NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
279  ", dead entry for " << destination << " valid -- drop");
280  m_dropTrace (packet);
281  }
282  else if (entry->IsAlive ())
283  {
284  NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
285  ", alive entry for " << destination << " valid -- send");
286  *hardwareDestination = entry->GetMacAddress ();
287  return true;
288  }
289  else if (entry->IsWaitReply ())
290  {
291  NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
292  ", wait reply for " << destination << " valid -- drop previous");
293  if (!entry->UpdateWaitReply (packet))
294  {
295  m_dropTrace (packet);
296  }
297  }
298  }
299  }
300  else
301  {
302  // This is our first attempt to transmit data to this destination.
303  NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
304  ", no entry for " << destination << " -- send arp request");
305  entry = cache->Add (destination);
306  entry->MarkWaitReply (packet);
307  SendArpRequest (cache, destination);
308  }
309  return false;
310 }
311 
312 void
314 {
315  NS_LOG_FUNCTION (this << cache << to);
316  ArpHeader arp;
317  // need to pick a source address; use routing implementation to select
319  Ptr<NetDevice> device = cache->GetDevice ();
320  NS_ASSERT (device != 0);
321  Ipv4Header header;
322  header.SetDestination (to);
323  Ptr<Packet> packet = Create<Packet> ();
324  Ipv4Address source = ipv4->SelectSourceAddress (device, to, Ipv4InterfaceAddress::GLOBAL);
325  NS_LOG_LOGIC ("ARP: sending request from node "<<m_node->GetId ()<<
326  " || src: " << device->GetAddress () << " / " << source <<
327  " || dst: " << device->GetBroadcast () << " / " << to);
328  arp.SetRequest (device->GetAddress (), source, device->GetBroadcast (), to);
329  packet->AddHeader (arp);
330  cache->GetDevice ()->Send (packet, device->GetBroadcast (), PROT_NUMBER);
331 }
332 
333 void
335 {
336  NS_LOG_FUNCTION (this << cache << myIp << toIp << toMac);
337  ArpHeader arp;
338  NS_LOG_LOGIC ("ARP: sending reply from node "<<m_node->GetId ()<<
339  "|| src: " << cache->GetDevice ()->GetAddress () <<
340  " / " << myIp <<
341  " || dst: " << toMac << " / " << toIp);
342  arp.SetReply (cache->GetDevice ()->GetAddress (), myIp, toMac, toIp);
343  Ptr<Packet> packet = Create<Packet> ();
344  packet->AddHeader (arp);
345  cache->GetDevice ()->Send (packet, toMac, PROT_NUMBER);
346 }
347 
348 } // namespace ns3