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