1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2005,2006,2007 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 
21 #include "ipv4-interface.h"
22 #include "loopback-net-device.h"
23 #include "ipv4-l3-protocol.h"
24 #include "ipv4-queue-disc-item.h"
25 #include "arp-l3-protocol.h"
26 #include "arp-cache.h"
27 #include "ns3/net-device.h"
28 #include "ns3/log.h"
29 #include "ns3/packet.h"
30 #include "ns3/node.h"
31 #include "ns3/pointer.h"
32 #include "ns3/traffic-control-layer.h"
33 
34 
35 namespace ns3 {
36 
37 NS_LOG_COMPONENT_DEFINE ("Ipv4Interface");
38 
39 NS_OBJECT_ENSURE_REGISTERED (Ipv4Interface);
40 
41 TypeId
GetTypeId(void)42 Ipv4Interface::GetTypeId (void)
43 {
44   static TypeId tid = TypeId ("ns3::Ipv4Interface")
45     .SetParent<Object> ()
46     .SetGroupName ("Internet")
47     .AddAttribute ("ArpCache",
48                    "The arp cache for this ipv4 interface",
49                    PointerValue (0),
50                    MakePointerAccessor (&Ipv4Interface::SetArpCache,
51                                         &Ipv4Interface::GetArpCache),
52                    MakePointerChecker<ArpCache> ())
53   ;
54   ;
55   return tid;
56 }
57 
58 /**
59  * By default, Ipv4 interface are created in the "down" state
60  *  with no IP addresses.  Before becoming usable, the user must
61  * invoke SetUp on them once an Ipv4 address and mask have been set.
62  */
Ipv4Interface()63 Ipv4Interface::Ipv4Interface ()
64   : m_ifup (false),
65     m_forwarding (true),
66     m_metric (1),
67     m_node (0),
68     m_device (0),
69     m_tc (0),
70     m_cache (0)
71 {
72   NS_LOG_FUNCTION (this);
73 }
74 
~Ipv4Interface()75 Ipv4Interface::~Ipv4Interface ()
76 {
77   NS_LOG_FUNCTION (this);
78 }
79 
80 void
DoDispose(void)81 Ipv4Interface::DoDispose (void)
82 {
83   NS_LOG_FUNCTION (this);
84   m_node = 0;
85   m_device = 0;
86   m_tc = 0;
87   m_cache = 0;
88   Object::DoDispose ();
89 }
90 
91 void
SetNode(Ptr<Node> node)92 Ipv4Interface::SetNode (Ptr<Node> node)
93 {
94   NS_LOG_FUNCTION (this << node);
95   m_node = node;
96   DoSetup ();
97 }
98 
99 void
SetDevice(Ptr<NetDevice> device)100 Ipv4Interface::SetDevice (Ptr<NetDevice> device)
101 {
102   NS_LOG_FUNCTION (this << device);
103   m_device = device;
104   DoSetup ();
105 }
106 
107 void
SetTrafficControl(Ptr<TrafficControlLayer> tc)108 Ipv4Interface::SetTrafficControl (Ptr<TrafficControlLayer> tc)
109 {
110   NS_LOG_FUNCTION (this << tc);
111   m_tc = tc;
112 }
113 
114 void
DoSetup(void)115 Ipv4Interface::DoSetup (void)
116 {
117   NS_LOG_FUNCTION (this);
118   if (m_node == 0 || m_device == 0)
119     {
120       return;
121     }
122   if (!m_device->NeedsArp ())
123     {
124       return;
125     }
126   Ptr<ArpL3Protocol> arp = m_node->GetObject<ArpL3Protocol> ();
127   m_cache = arp->CreateCache (m_device, this);
128 }
129 
130 Ptr<NetDevice>
GetDevice(void) const131 Ipv4Interface::GetDevice (void) const
132 {
133   NS_LOG_FUNCTION (this);
134   return m_device;
135 }
136 
137 void
SetMetric(uint16_t metric)138 Ipv4Interface::SetMetric (uint16_t metric)
139 {
140   NS_LOG_FUNCTION (this << metric);
141   m_metric = metric;
142 }
143 
144 uint16_t
GetMetric(void) const145 Ipv4Interface::GetMetric (void) const
146 {
147   NS_LOG_FUNCTION (this);
148   return m_metric;
149 }
150 
151 void
SetArpCache(Ptr<ArpCache> a)152 Ipv4Interface::SetArpCache (Ptr<ArpCache> a)
153 {
154   NS_LOG_FUNCTION (this << a);
155   m_cache = a;
156 }
157 
158 Ptr<ArpCache>
GetArpCache() const159 Ipv4Interface::GetArpCache () const
160 {
161   NS_LOG_FUNCTION (this);
162   return m_cache;
163 }
164 
165 /**
166  * These are IP interface states and may be distinct from
167  * NetDevice states, such as found in real implementations
168  * (where the device may be down but IP interface state is still up).
169  */
170 bool
IsUp(void) const171 Ipv4Interface::IsUp (void) const
172 {
173   NS_LOG_FUNCTION (this);
174   return m_ifup;
175 }
176 
177 bool
IsDown(void) const178 Ipv4Interface::IsDown (void) const
179 {
180   NS_LOG_FUNCTION (this);
181   return !m_ifup;
182 }
183 
184 void
SetUp(void)185 Ipv4Interface::SetUp (void)
186 {
187   NS_LOG_FUNCTION (this);
188   m_ifup = true;
189 }
190 
191 void
SetDown(void)192 Ipv4Interface::SetDown (void)
193 {
194   NS_LOG_FUNCTION (this);
195   m_ifup = false;
196 }
197 
198 bool
IsForwarding(void) const199 Ipv4Interface::IsForwarding (void) const
200 {
201   NS_LOG_FUNCTION (this);
202   return m_forwarding;
203 }
204 
205 void
SetForwarding(bool val)206 Ipv4Interface::SetForwarding (bool val)
207 {
208   NS_LOG_FUNCTION (this << val);
209   m_forwarding = val;
210 }
211 
212 void
Send(Ptr<Packet> p,const Ipv4Header & hdr,Ipv4Address dest)213 Ipv4Interface::Send (Ptr<Packet> p, const Ipv4Header & hdr, Ipv4Address dest)
214 {
215   NS_LOG_FUNCTION (this << *p << dest);
216   if (!IsUp ())
217     {
218       return;
219     }
220 
221   // Check for a loopback device, if it's the case we don't pass through
222   // traffic control layer
223   if (DynamicCast<LoopbackNetDevice> (m_device))
224     {
225       /// \todo additional checks needed here (such as whether multicast
226       /// goes to loopback)?
227       p->AddHeader (hdr);
228       m_device->Send (p, m_device->GetBroadcast (), Ipv4L3Protocol::PROT_NUMBER);
229       return;
230     }
231 
232   NS_ASSERT (m_tc != 0);
233 
234   // is this packet aimed at a local interface ?
235   for (Ipv4InterfaceAddressListCI i = m_ifaddrs.begin (); i != m_ifaddrs.end (); ++i)
236     {
237       if (dest == (*i).GetLocal ())
238         {
239           p->AddHeader (hdr);
240           m_tc->Receive (m_device, p, Ipv4L3Protocol::PROT_NUMBER,
241                          m_device->GetBroadcast (),
242                          m_device->GetBroadcast (),
243                          NetDevice::PACKET_HOST);
244           return;
245         }
246     }
247   if (m_device->NeedsArp ())
248     {
249       NS_LOG_LOGIC ("Needs ARP" << " " << dest);
250       Ptr<ArpL3Protocol> arp = m_node->GetObject<ArpL3Protocol> ();
251       Address hardwareDestination;
252       bool found = false;
253       if (dest.IsBroadcast ())
254         {
255           NS_LOG_LOGIC ("All-network Broadcast");
256           hardwareDestination = m_device->GetBroadcast ();
257           found = true;
258         }
259       else if (dest.IsMulticast ())
260         {
261           NS_LOG_LOGIC ("IsMulticast");
262           NS_ASSERT_MSG (m_device->IsMulticast (),
263                          "ArpIpv4Interface::SendTo (): Sending multicast packet over "
264                          "non-multicast device");
265 
266           hardwareDestination = m_device->GetMulticast (dest);
267           found = true;
268         }
269       else
270         {
271           for (Ipv4InterfaceAddressListCI i = m_ifaddrs.begin (); i != m_ifaddrs.end (); ++i)
272             {
273               if (dest.IsSubnetDirectedBroadcast ((*i).GetMask ()))
274                 {
275                   NS_LOG_LOGIC ("Subnetwork Broadcast");
276                   hardwareDestination = m_device->GetBroadcast ();
277                   found = true;
278                   break;
279                 }
280             }
281           if (!found)
282             {
283               NS_LOG_LOGIC ("ARP Lookup");
284               found = arp->Lookup (p, hdr, dest, m_device, m_cache, &hardwareDestination);
285             }
286         }
287 
288       if (found)
289         {
290           NS_LOG_LOGIC ("Address Resolved.  Send.");
291           m_tc->Send (m_device, Create<Ipv4QueueDiscItem> (p, hardwareDestination, Ipv4L3Protocol::PROT_NUMBER, hdr));
292         }
293     }
294   else
295     {
296       NS_LOG_LOGIC ("Doesn't need ARP");
297       m_tc->Send (m_device, Create<Ipv4QueueDiscItem> (p, m_device->GetBroadcast (), Ipv4L3Protocol::PROT_NUMBER, hdr));
298     }
299 }
300 
301 uint32_t
GetNAddresses(void) const302 Ipv4Interface::GetNAddresses (void) const
303 {
304   NS_LOG_FUNCTION (this);
305   return m_ifaddrs.size ();
306 }
307 
308 bool
AddAddress(Ipv4InterfaceAddress addr)309 Ipv4Interface::AddAddress (Ipv4InterfaceAddress addr)
310 {
311   NS_LOG_FUNCTION (this << addr);
312   m_ifaddrs.push_back (addr);
313   return true;
314 }
315 
316 Ipv4InterfaceAddress
GetAddress(uint32_t index) const317 Ipv4Interface::GetAddress (uint32_t index) const
318 {
319   NS_LOG_FUNCTION (this << index);
320   if (index < m_ifaddrs.size ())
321     {
322       uint32_t tmp = 0;
323       for (Ipv4InterfaceAddressListCI i = m_ifaddrs.begin (); i!= m_ifaddrs.end (); i++)
324         {
325           if (tmp  == index)
326             {
327               return *i;
328             }
329           ++tmp;
330         }
331     }
332   else
333     {
334       NS_FATAL_ERROR ("index " << index << " out of bounds");
335     }
336   Ipv4InterfaceAddress addr;
337   return (addr);  // quiet compiler
338 }
339 
340 Ipv4InterfaceAddress
RemoveAddress(uint32_t index)341 Ipv4Interface::RemoveAddress (uint32_t index)
342 {
343   NS_LOG_FUNCTION (this << index);
344   if (index >= m_ifaddrs.size ())
345     {
346       NS_FATAL_ERROR ("Bug in Ipv4Interface::RemoveAddress");
347     }
348   Ipv4InterfaceAddressListI i = m_ifaddrs.begin ();
349   uint32_t tmp = 0;
350   while (i != m_ifaddrs.end ())
351     {
352       if (tmp  == index)
353         {
354           Ipv4InterfaceAddress addr = *i;
355           m_ifaddrs.erase (i);
356           return addr;
357         }
358       ++tmp;
359       ++i;
360     }
361   NS_FATAL_ERROR ("Address " << index << " not found");
362   Ipv4InterfaceAddress addr;
363   return (addr);  // quiet compiler
364 }
365 
366 Ipv4InterfaceAddress
RemoveAddress(Ipv4Address address)367 Ipv4Interface::RemoveAddress(Ipv4Address address)
368 {
369   NS_LOG_FUNCTION(this << address);
370 
371   if (address == address.GetLoopback())
372     {
373       NS_LOG_WARN ("Cannot remove loopback address.");
374       return Ipv4InterfaceAddress();
375     }
376 
377   for(Ipv4InterfaceAddressListI it = m_ifaddrs.begin(); it != m_ifaddrs.end(); it++)
378     {
379       if((*it).GetLocal() == address)
380         {
381           Ipv4InterfaceAddress ifAddr = *it;
382           m_ifaddrs.erase(it);
383           return ifAddr;
384         }
385     }
386   return Ipv4InterfaceAddress();
387 }
388 
389 } // namespace ns3
390 
391