ns-3 Direct Code Execution
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ipv4-linux.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2012 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: Frédéric Urbani
19  * Hajime Tazaki <tazaki@nict.go.jp>
20  */
21 
22 #include "ipv4-linux.h"
23 #include "ns3/log.h"
24 #include "ns3/node.h"
25 #include "ns3/ipv4-list-routing-helper.h"
26 #include "ns3/ipv4-static-routing-helper.h"
27 #include "ns3/ipv4-global-routing-helper.h"
28 #include "ns3/ipv4-interface.h"
29 #include "ns3/ipv4-global-routing.h"
30 #include "ns3/ipv4-routing-table-entry.h"
31 #include "../../helper/dce-application-helper.h"
36 
37 NS_LOG_COMPONENT_DEFINE ("Ipv4Linux");
38 
39 namespace ns3 {
40 
41 NS_OBJECT_ENSURE_REGISTERED (Ipv4Linux);
42 
43 static void
44 RunIp (Ptr<Node> node, Time at, std::string str)
45 {
46  DceApplicationHelper process;
47  ApplicationContainer apps;
48  process.SetBinary ("ip");
49  process.SetStackSize (1 << 16);
50  process.ResetArguments ();
51  process.ParseArguments (str.c_str ());
52  apps = process.Install (node);
53  apps.Start (at);
54 }
55 
56 TypeId
58 {
59  static TypeId tid = TypeId ("ns3::Ipv4Linux")
60  .SetParent<Ipv4> ()
61  .AddConstructor<Ipv4Linux> ();
62 
63  return tid;
64 }
65 
67  : m_nanoSec (0)
68 {
69  NS_LOG_FUNCTION (this);
70 }
71 
73 {
74  NS_LOG_FUNCTION (this);
75 }
76 
77 void
78 Ipv4Linux::SetRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol)
79 {
80  NS_LOG_FUNCTION (this);
81  m_routingProtocol = routingProtocol;
82  m_routingProtocol->SetIpv4 (this);
83 }
84 
85 Ptr<Ipv4RoutingProtocol>
87 {
88  NS_LOG_FUNCTION (this);
89  return m_routingProtocol;
90 }
91 
92 uint32_t
93 Ipv4Linux::AddInterface (Ptr<NetDevice> device)
94 {
95  NS_LOG_FUNCTION (this << &device);
96 
97  Ptr<Ipv4Interface> interface = CreateObject<Ipv4Interface> ();
98  interface->SetDevice (device);
99  interface->SetForwarding (m_ipForward);
100  return AddIpv4Interface (interface);
101 }
102 uint32_t
103 Ipv4Linux::AddIpv4Interface (Ptr<Ipv4Interface>interface)
104 {
105  NS_LOG_FUNCTION (this << interface);
106  uint32_t index = m_interfaces.size ();
107  m_interfaces.push_back (interface);
108  return index;
109 }
110 
111 uint32_t
113 {
114  NS_LOG_FUNCTION (this);
115  return m_interfaces.size ();
116 }
117 
118 int32_t
119 Ipv4Linux::GetInterfaceForAddress (Ipv4Address address) const
120 {
121  NS_LOG_FUNCTION (this);
122 
123  int32_t interface = 0;
124  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
125  i != m_interfaces.end ();
126  i++, interface++)
127  {
128  for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
129  {
130  if ((*i)->GetAddress (j).GetLocal () == address)
131  {
132  return interface;
133  }
134  }
135  }
136 
137  return -1;
138 }
139 
140 void
141 Ipv4Linux::Send (Ptr<Packet> packet, Ipv4Address source,
142  Ipv4Address destination, uint8_t protocol, Ptr<Ipv4Route> route)
143 {
144  NS_LOG_FUNCTION (this << "empty method.");
145 }
146 
147 void
148 Ipv4Linux::SendWithHeader (Ptr<Packet> packet, Ipv4Header ipHeader, Ptr<Ipv4Route> route)
149 {
150  NS_LOG_FUNCTION (this << "empty method.");
151 }
152 
153 void
154 Ipv4Linux::Insert (Ptr<IpL4Protocol> protocol)
155 {
156  NS_LOG_FUNCTION (this << "empty method.");
157 }
158 
159 bool
160 Ipv4Linux::IsDestinationAddress (Ipv4Address address, uint32_t iif) const
161 {
162  // First check the incoming interface for a unicast address match
163  for (uint32_t i = 0; i < GetNAddresses (iif); i++)
164  {
165  Ipv4InterfaceAddress iaddr = GetAddress (iif, i);
166  if (address == iaddr.GetLocal ())
167  {
168  NS_LOG_LOGIC ("For me (destination " << address << " match)");
169  return true;
170  }
171  if (address == iaddr.GetBroadcast ())
172  {
173  NS_LOG_LOGIC ("For me (interface broadcast address)");
174  return true;
175  }
176  }
177 
178  if (address.IsMulticast ())
179  {
180 #ifdef NOTYET
181  if (MulticastCheckGroup (iif, address))
182 #endif
183  if (true)
184  {
185  NS_LOG_LOGIC ("For me (Ipv4Addr multicast address");
186  return true;
187  }
188  }
189 
190  if (address.IsBroadcast ())
191  {
192  NS_LOG_LOGIC ("For me (Ipv4Addr broadcast address)");
193  return true;
194  }
195 
196  if (GetWeakEsModel ()) // Check other interfaces
197  {
198  for (uint32_t j = 0; j < GetNInterfaces (); j++)
199  {
200  if (j == uint32_t (iif))
201  {
202  continue;
203  }
204  for (uint32_t i = 0; i < GetNAddresses (j); i++)
205  {
206  Ipv4InterfaceAddress iaddr = GetAddress (j, i);
207  if (address == iaddr.GetLocal ())
208  {
209  NS_LOG_LOGIC ("For me (destination " << address << " match) on another interface");
210  return true;
211  }
212  // This is a small corner case: match another interface's broadcast address
213  if (address == iaddr.GetBroadcast ())
214  {
215  NS_LOG_LOGIC ("For me (interface broadcast address on another interface)");
216  return true;
217  }
218  }
219  }
220  }
221  return false;
222 }
223 
224 int32_t
225 Ipv4Linux::GetInterfaceForPrefix (Ipv4Address address, Ipv4Mask mask) const
226 {
227  NS_LOG_FUNCTION (this);
228  int32_t interface = 0;
229  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
230  i != m_interfaces.end ();
231  i++, interface++)
232  {
233  for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
234  {
235  if ((*i)->GetAddress (j).GetLocal ().CombineMask (mask) == address.CombineMask (mask))
236  {
237  return interface;
238  }
239  }
240  }
241 
242  return -1;
243 }
244 
245 Ptr<NetDevice>
247 {
248  NS_LOG_FUNCTION (this);
249  return GetInterface (i)->GetDevice ();
250 }
251 
252 int32_t
253 Ipv4Linux::GetInterfaceForDevice (Ptr<const NetDevice> device) const
254 {
255  NS_LOG_FUNCTION (this);
256  int32_t interface = 0;
257  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
258  i != m_interfaces.end ();
259  i++, interface++)
260  {
261  if ((*i)->GetDevice () == device)
262  {
263  return interface;
264  }
265  }
266 
267  return -1;
268 }
269 
270 bool
271 Ipv4Linux::AddAddress (uint32_t i, Ipv4InterfaceAddress address)
272 {
273  NS_LOG_FUNCTION (this << i << address);
274  Ptr<Ipv4Interface> interface = GetInterface (i);
275  bool retVal = interface->AddAddress (address);
276  if (m_routingProtocol != 0)
277  {
278  m_routingProtocol->NotifyAddAddress (i, address);
279  }
280 
281  std::ostringstream oss;
282  Ptr<Node> node = this->GetObject<Node> ();
283  oss << "-f inet addr add ";
284  address.GetLocal ().Print (oss);
285  oss << '/' << address.GetMask ().GetPrefixLength () << " dev sim" << i;
286  RunIp (node, NanoSeconds (++m_nanoSec), oss.str ());
287  oss.str ("");
288  oss << "link set sim" << i << " up arp "
289  << ((interface->GetDevice ()->NeedsArp ()) ? "on" : "off");
290  RunIp (node, NanoSeconds (++m_nanoSec), oss.str ());
291 
292  return retVal;
293 }
294 
295 uint32_t
296 Ipv4Linux::GetNAddresses (uint32_t interface) const
297 {
298  Ptr<Ipv4Interface> iface = GetInterface (interface);
299  return iface->GetNAddresses ();
300 }
301 
302 Ipv4InterfaceAddress
303 Ipv4Linux::GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const
304 {
305  NS_LOG_FUNCTION (this);
306  Ptr<Ipv4Interface> interface = GetInterface (interfaceIndex);
307  return interface->GetAddress (addressIndex);
308 }
309 
310 bool
311 Ipv4Linux::RemoveAddress (uint32_t i, uint32_t addressIndex)
312 {
313  NS_LOG_FUNCTION (this << i << addressIndex);
314  Ptr<Ipv4Interface> interface = GetInterface (i);
315  Ipv4InterfaceAddress address = interface->RemoveAddress (addressIndex);
316  if (address != Ipv4InterfaceAddress ())
317  {
318  if (m_routingProtocol != 0)
319  {
320  m_routingProtocol->NotifyRemoveAddress (i, address);
321  }
322  return true;
323  }
324  return false;
325 }
326 
327 bool
328 Ipv4Linux::RemoveAddress (uint32_t i, Ipv4Address address)
329 {
330  NS_LOG_FUNCTION (this << i << address);
331 
332  if (address == Ipv4Address::GetLoopback())
333  {
334  NS_LOG_WARN ("Cannot remove loopback address.");
335  return false;
336  }
337  Ptr<Ipv4Interface> interface = GetInterface (i);
338  Ipv4InterfaceAddress ifAddr = interface->RemoveAddress (address);
339  if (ifAddr != Ipv4InterfaceAddress ())
340  {
341  if (m_routingProtocol != 0)
342  {
343  m_routingProtocol->NotifyRemoveAddress (i, ifAddr);
344  }
345  return true;
346  }
347  return false;
348 }
349 
350 Ipv4Address
351 Ipv4Linux::SelectSourceAddress (Ptr<const NetDevice> device,
352  Ipv4Address dst, Ipv4InterfaceAddress::InterfaceAddressScope_e scope)
353 {
354  NS_LOG_FUNCTION (this << device << dst << scope);
355  Ipv4Address addr ("0.0.0.0");
356  Ipv4InterfaceAddress iaddr;
357  bool found = false;
358 
359  if (device != 0)
360  {
361  int32_t i = GetInterfaceForDevice (device);
362  NS_ASSERT_MSG (i >= 0, "No device found on node");
363  for (uint32_t j = 0; j < GetNAddresses (i); j++)
364  {
365  iaddr = GetAddress (i, j);
366  if (iaddr.IsSecondary ())
367  {
368  continue;
369  }
370  if (iaddr.GetScope () > scope)
371  {
372  continue;
373  }
374  if (dst.CombineMask (iaddr.GetMask ()) == iaddr.GetLocal ().CombineMask (iaddr.GetMask ()) )
375  {
376  return iaddr.GetLocal ();
377  }
378  if (!found)
379  {
380  addr = iaddr.GetLocal ();
381  found = true;
382  }
383  }
384  }
385  if (found)
386  {
387  return addr;
388  }
389 
390  // Iterate among all interfaces
391  for (uint32_t i = 0; i < GetNInterfaces (); i++)
392  {
393  for (uint32_t j = 0; j < GetNAddresses (i); j++)
394  {
395  iaddr = GetAddress (i, j);
396  if (iaddr.IsSecondary ())
397  {
398  continue;
399  }
400  if (iaddr.GetScope () != Ipv4InterfaceAddress::LINK
401  && iaddr.GetScope () <= scope)
402  {
403  return iaddr.GetLocal ();
404  }
405  }
406  }
407  NS_LOG_WARN ("Could not find source address for " << dst << " and scope "
408  << scope << ", returning 0");
409  return addr;
410 }
411 
412 void
413 Ipv4Linux::SetMetric (uint32_t i, uint16_t metric)
414 {
415  NS_LOG_FUNCTION (this << i << metric);
416  Ptr<Ipv4Interface> interface = GetInterface (i);
417  interface->SetMetric (metric);
418 }
419 
420 uint16_t
421 Ipv4Linux::GetMetric (uint32_t i) const
422 {
423  Ptr<Ipv4Interface> interface = GetInterface (i);
424  return interface->GetMetric ();
425 }
426 
427 uint16_t
428 Ipv4Linux::GetMtu (uint32_t i) const
429 {
430  Ptr<Ipv4Interface> interface = GetInterface (i);
431  return interface->GetDevice ()->GetMtu ();
432 }
433 
434 bool
435 Ipv4Linux::IsUp (uint32_t i) const
436 {
437  Ptr<Ipv4Interface> interface = GetInterface (i);
438  return interface->IsUp ();
439 }
440 
441 void
442 Ipv4Linux::SetUp (uint32_t i)
443 {
444  NS_LOG_FUNCTION (this << i);
445  Ptr<Ipv4Interface> interface = GetInterface (i);
446  interface->SetUp ();
447 
448  if (m_routingProtocol != 0)
449  {
450  m_routingProtocol->NotifyInterfaceUp (i);
451  }
452 }
453 
454 void
455 Ipv4Linux::SetDown (uint32_t ifaceIndex)
456 {
457  NS_LOG_FUNCTION (this << ifaceIndex);
458  Ptr<Ipv4Interface> interface = GetInterface (ifaceIndex);
459  interface->SetDown ();
460 
461  if (m_routingProtocol != 0)
462  {
463  m_routingProtocol->NotifyInterfaceDown (ifaceIndex);
464  }
465 }
466 
467 bool
468 Ipv4Linux::IsForwarding (uint32_t i) const
469 {
470  NS_LOG_FUNCTION (this << i);
471  Ptr<Ipv4Interface> interface = GetInterface (i);
472  NS_LOG_LOGIC ("Forwarding state: " << interface->IsForwarding ());
473  return interface->IsForwarding ();
474 }
475 
476 void
477 Ipv4Linux::SetForwarding (uint32_t i, bool val)
478 {
479  NS_LOG_FUNCTION (this << i);
480  Ptr<Ipv4Interface> interface = GetInterface (i);
481  interface->SetForwarding (val);
482 }
483 
484 void
486 {
487  NS_LOG_FUNCTION (this << forward);
488  m_ipForward = forward;
489  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
490  {
491  (*i)->SetForwarding (forward);
492  }
493 }
494 
495 bool
497 {
498  return m_ipForward;
499 }
500 
501 void
503 {
504  m_weakEsModel = model;
505 }
506 
507 bool
509 {
510  return m_weakEsModel;
511 }
512 
513 void
514 Ipv4Linux::InstallNode (Ptr<Node> node)
515 {
516  ObjectFactory factory;
517  factory.SetTypeId ("ns3::Ipv4Linux");
518  Ptr<Object> protocol = factory.Create <Object> ();
519  node->AggregateObject (protocol);
520  Ipv4GlobalRoutingHelper globalRouting;
521  // Set routing
522  Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
523  Ptr<Ipv4RoutingProtocol> ipv4Routing = globalRouting.Create (node);
524  ipv4->SetRoutingProtocol (ipv4Routing);
525  // Socket related stuff
526  Ptr<LinuxIpv4RawSocketFactoryImpl> ipv4rawFactory = CreateObject<LinuxIpv4RawSocketFactoryImpl> ();
527  node->AggregateObject (ipv4rawFactory);
528  Ptr<LinuxUdpSocketFactoryImpl> udpFactory = CreateObject<LinuxUdpSocketFactoryImpl> ();
529  node->AggregateObject (udpFactory);
530  Ptr<LinuxTcpSocketFactoryImpl> tcpFactory = CreateObject<LinuxTcpSocketFactoryImpl> ();
531  node->AggregateObject (tcpFactory);
532  Ptr<LinuxDccpSocketFactoryImpl> dccpFactory = CreateObject<LinuxDccpSocketFactoryImpl> ();
533  node->AggregateObject (dccpFactory);
534 }
535 Ptr<Ipv4Interface>
536 Ipv4Linux::GetInterface (uint32_t index) const
537 {
538  if (index < m_interfaces.size ())
539  {
540  return m_interfaces[index];
541  }
542  return 0;
543 }
544 
545 Ptr<IpL4Protocol>
546 Ipv4Linux::GetProtocol (int protocolNumber) const
547 {
548  return 0;
549 }
550 
551 Ptr<Socket>
553 {
554  return 0;
555 }
556 
560 void
561 Ipv4Linux::DeleteRawSocket (Ptr<Socket> socket)
562 {
563 
564 }
565 
566 void
568 {
569  // Only support Ipv4GlobalRouting
570  Ptr<Node> node = this->GetObject<Node> ();
571  Ptr<Ipv4GlobalRouting> globalRouting = DynamicCast<Ipv4GlobalRouting> (GetRoutingProtocol ());
572  NS_ASSERT_MSG (globalRouting, "No global routing");
573 
574  for (uint32_t i = 0; i < globalRouting->GetNRoutes (); i++)
575  {
576  Ipv4RoutingTableEntry route = globalRouting->GetRoute (i);
577  std::ostringstream oss;
578  oss << "route add to " << route.GetDest () << '/' << route.GetDestNetworkMask () << " via " << route.GetGateway ();
579  RunIp (node, NanoSeconds (++m_nanoSec), oss.str ());
580  }
581 }
582 
583 }