src/internet-node/ipv4-l3-protocol.cc
author Gustavo J. A. M. Carneiro <gjc@inescporto.pt>
Mon Feb 11 14:46:44 2008 +0000 (2008-02-11)
changeset 2325 084b07dceafb
parent 2324 a3e10db411b9
child 2326 eec07777d1a2
permissions -rw-r--r--
Add the IPv4 header before deciding whether to drop packets. Closes bug #135.
mathieu@236
     1
// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
mathieu@236
     2
//
mathieu@236
     3
// Copyright (c) 2006 Georgia Tech Research Corporation
mathieu@236
     4
// All rights reserved.
mathieu@236
     5
//
mathieu@236
     6
// This program is free software; you can redistribute it and/or modify
mathieu@236
     7
// it under the terms of the GNU General Public License version 2 as
mathieu@236
     8
// published by the Free Software Foundation;
mathieu@236
     9
//
mathieu@236
    10
// This program is distributed in the hope that it will be useful,
mathieu@236
    11
// but WITHOUT ANY WARRANTY; without even the implied warranty of
mathieu@236
    12
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
mathieu@236
    13
// GNU General Public License for more details.
mathieu@236
    14
//
mathieu@236
    15
// You should have received a copy of the GNU General Public License
mathieu@236
    16
// along with this program; if not, write to the Free Software
mathieu@236
    17
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
mathieu@236
    18
//
mathieu@236
    19
// Author: George F. Riley<riley@ece.gatech.edu>
mathieu@236
    20
//
mathieu@236
    21
mathieu@236
    22
#include "ns3/packet.h"
craigdo@1504
    23
#include "ns3/log.h"
tomh@345
    24
#include "ns3/composite-trace-resolver.h"
tomh@345
    25
#include "ns3/callback.h"
mathieu@524
    26
#include "ns3/ipv4-address.h"
mathieu@524
    27
#include "ns3/ipv4-route.h"
mathieu@729
    28
#include "ns3/node.h"
mathieu@568
    29
#include "ns3/net-device.h"
mathieu@236
    30
mathieu@733
    31
#include "ipv4-l3-protocol.h"
mathieu@236
    32
#include "ipv4-l4-protocol.h"
mathieu@236
    33
#include "ipv4-header.h"
mathieu@236
    34
#include "ipv4-interface.h"
mathieu@444
    35
#include "ipv4-loopback-interface.h"
mathieu@444
    36
#include "arp-ipv4-interface.h"
mathieu@236
    37
#include "ipv4-l4-demux.h"
mathieu@236
    38
craigdo@1504
    39
NS_LOG_COMPONENT_DEFINE ("Ipv4L3Protocol");
mathieu@236
    40
mathieu@236
    41
namespace ns3 {
mathieu@236
    42
mathieu@734
    43
const uint16_t Ipv4L3Protocol::PROT_NUMBER = 0x0800;
mathieu@293
    44
mathieu@2249
    45
NS_OBJECT_ENSURE_REGISTERED (Ipv4L3Protocol);
mathieu@2249
    46
mathieu@2250
    47
TypeId 
mathieu@2251
    48
Ipv4L3Protocol::GetTypeId (void)
mathieu@2232
    49
{
mathieu@2252
    50
  static TypeId tid = TypeId ("Ipv4L3Protocol")
mathieu@2238
    51
    .SetParent<Object> ();
mathieu@2252
    52
  return tid;
mathieu@2232
    53
}
mathieu@2232
    54
mathieu@1229
    55
Ipv4L3ProtocolTraceContextElement::Ipv4L3ProtocolTraceContextElement ()
mathieu@1229
    56
  : m_type (TX)
craigdo@1504
    57
{
craigdo@1504
    58
  NS_LOG_FUNCTION;
craigdo@1504
    59
}
craigdo@1504
    60
mathieu@1229
    61
Ipv4L3ProtocolTraceContextElement::Ipv4L3ProtocolTraceContextElement (enum Type type)
mathieu@1229
    62
  : m_type (type)
craigdo@1504
    63
{
craigdo@1504
    64
  NS_LOG_FUNCTION;
craigdo@1504
    65
}
craigdo@1504
    66
mathieu@1229
    67
bool 
mathieu@1229
    68
Ipv4L3ProtocolTraceContextElement::IsTx (void) const
mathieu@1229
    69
{
craigdo@1504
    70
  NS_LOG_FUNCTION;
mathieu@1229
    71
  return m_type == TX;
mathieu@1229
    72
}
craigdo@1504
    73
mathieu@1229
    74
bool 
mathieu@1229
    75
Ipv4L3ProtocolTraceContextElement::IsRx (void) const
mathieu@1229
    76
{
craigdo@1504
    77
  NS_LOG_FUNCTION;
mathieu@1229
    78
  return m_type == RX;
mathieu@1229
    79
}
craigdo@1504
    80
mathieu@1229
    81
bool 
mathieu@1229
    82
Ipv4L3ProtocolTraceContextElement::IsDrop (void) const
mathieu@1229
    83
{
craigdo@1504
    84
  NS_LOG_FUNCTION;
mathieu@1229
    85
  return m_type == DROP;
mathieu@1229
    86
}
craigdo@1504
    87
mathieu@1229
    88
void 
mathieu@1229
    89
Ipv4L3ProtocolTraceContextElement::Print (std::ostream &os) const
mathieu@1229
    90
{
craigdo@1504
    91
  NS_LOG_FUNCTION;
mathieu@1229
    92
  os << "ipv4=";
mathieu@1229
    93
  switch (m_type)
mathieu@1229
    94
    {
mathieu@1229
    95
    case TX:
mathieu@1229
    96
      os << "tx";
mathieu@1229
    97
      break;
mathieu@1229
    98
    case RX:
mathieu@1229
    99
      os << "rx";
mathieu@1229
   100
      break;
mathieu@1229
   101
    case DROP:
mathieu@1229
   102
      os << "drop";
mathieu@1229
   103
      break;
mathieu@1229
   104
    }
mathieu@1229
   105
}
craigdo@1504
   106
mathieu@1229
   107
uint16_t 
mathieu@1229
   108
Ipv4L3ProtocolTraceContextElement::GetUid (void)
mathieu@1229
   109
{
craigdo@1504
   110
  NS_LOG_FUNCTION;
mathieu@1235
   111
  static uint16_t uid = AllocateUid<Ipv4L3ProtocolTraceContextElement> ("Ipv4L3ProtocolTraceContextElement");
mathieu@1229
   112
  return uid;
mathieu@1229
   113
}
craigdo@1504
   114
mathieu@1364
   115
std::string 
mathieu@1401
   116
Ipv4L3ProtocolTraceContextElement::GetTypeName (void) const
mathieu@1364
   117
{
craigdo@1504
   118
  NS_LOG_FUNCTION;
mathieu@1401
   119
  return "ns3::Ipv4L3ProtocolTraceContextElement";
mathieu@1364
   120
}
mathieu@1229
   121
mathieu@1341
   122
Ipv4L3ProtocolInterfaceIndex::Ipv4L3ProtocolInterfaceIndex ()
mathieu@1229
   123
  : m_index (0)
craigdo@1504
   124
{
craigdo@1504
   125
  NS_LOG_FUNCTION;
craigdo@1504
   126
}
craigdo@1504
   127
mathieu@1341
   128
Ipv4L3ProtocolInterfaceIndex::Ipv4L3ProtocolInterfaceIndex (uint32_t index)
mathieu@1229
   129
  : m_index (index)
craigdo@1504
   130
{
craigdo@1504
   131
  NS_LOG_FUNCTION;
craigdo@1504
   132
}
craigdo@1504
   133
mathieu@1229
   134
uint32_t 
mathieu@1341
   135
Ipv4L3ProtocolInterfaceIndex::Get (void) const
mathieu@1229
   136
{
craigdo@1504
   137
  NS_LOG_FUNCTION;
mathieu@1229
   138
  return m_index;
mathieu@1229
   139
}
craigdo@1504
   140
mathieu@1229
   141
void 
mathieu@1341
   142
Ipv4L3ProtocolInterfaceIndex::Print (std::ostream &os) const
mathieu@1229
   143
{
mathieu@1229
   144
  os << "ipv4-interface=" << m_index;
mathieu@1229
   145
}
craigdo@1504
   146
mathieu@1229
   147
uint16_t 
mathieu@1341
   148
Ipv4L3ProtocolInterfaceIndex::GetUid (void)
mathieu@1229
   149
{
craigdo@1504
   150
  NS_LOG_FUNCTION;
mathieu@1341
   151
  static uint16_t uid = AllocateUid<Ipv4L3ProtocolInterfaceIndex> ("Ipv4L3ProtocolInterfaceIndex");
mathieu@1229
   152
  return uid;
mathieu@1229
   153
}
craigdo@1504
   154
mathieu@1364
   155
std::string
mathieu@1401
   156
Ipv4L3ProtocolInterfaceIndex::GetTypeName (void) const
mathieu@1364
   157
{
craigdo@1504
   158
  NS_LOG_FUNCTION;
mathieu@1401
   159
  return "ns3::Ipv4L3ProtocolInterfaceIndex";
mathieu@1364
   160
}
mathieu@1229
   161
mathieu@1229
   162
mathieu@734
   163
Ipv4L3Protocol::Ipv4L3Protocol(Ptr<Node> node)
mathieu@1176
   164
  : m_nInterfaces (0),
mathieu@236
   165
    m_defaultTtl (64),
mathieu@236
   166
    m_identification (0),
mathieu@241
   167
    m_node (node)
mathieu@444
   168
{
craigdo@1504
   169
  NS_LOG_FUNCTION;
mathieu@2230
   170
  m_staticRouting = CreateObject<Ipv4StaticRouting> ();
gjc@983
   171
  AddRoutingProtocol (m_staticRouting, 0);
mathieu@444
   172
  SetupLoopback ();
mathieu@444
   173
}
craigdo@1429
   174
mathieu@734
   175
Ipv4L3Protocol::~Ipv4L3Protocol ()
craigdo@1429
   176
{
craigdo@1504
   177
  NS_LOG_FUNCTION;
craigdo@1429
   178
}
mathieu@496
   179
mathieu@496
   180
void 
mathieu@734
   181
Ipv4L3Protocol::DoDispose (void)
mathieu@496
   182
{
craigdo@1504
   183
  NS_LOG_FUNCTION;
mathieu@496
   184
  m_interfaces.clear ();
mathieu@555
   185
  m_node = 0;
gjc@983
   186
  m_staticRouting->Dispose ();
gjc@983
   187
  m_staticRouting = 0;
mathieu@1176
   188
  Object::DoDispose ();
mathieu@236
   189
}
mathieu@236
   190
mathieu@444
   191
void
mathieu@734
   192
Ipv4L3Protocol::SetupLoopback (void)
mathieu@444
   193
{
craigdo@1504
   194
  NS_LOG_FUNCTION;
craigdo@1429
   195
mathieu@2230
   196
  Ptr<Ipv4LoopbackInterface> interface = CreateObject<Ipv4LoopbackInterface> (m_node);
mathieu@444
   197
  interface->SetAddress (Ipv4Address::GetLoopback ());
mathieu@444
   198
  interface->SetNetworkMask (Ipv4Mask::GetLoopback ());
mathieu@444
   199
  uint32_t index = AddIpv4Interface (interface);
mathieu@444
   200
  AddHostRouteTo (Ipv4Address::GetLoopback (), index);
mathieu@444
   201
  interface->SetUp ();
mathieu@444
   202
}
mathieu@444
   203
mathieu@1333
   204
Ptr<TraceResolver>
mathieu@1383
   205
Ipv4L3Protocol::GetTraceResolver (void) const
tomh@345
   206
{
craigdo@1504
   207
  NS_LOG_FUNCTION;
craigdo@1429
   208
mathieu@1333
   209
  Ptr<CompositeTraceResolver> resolver = Create<CompositeTraceResolver> ();
mathieu@1379
   210
  resolver->AddSource ("tx", 
mathieu@1379
   211
                       TraceDoc ("send ipv4 packet to outgoing interface",
mathieu@1866
   212
                                 "Ptr<const Packet>", "packet sent",
mathieu@1379
   213
                                 "uint32_t", "index of output ipv4 interface"),
mathieu@1372
   214
                       m_txTrace, Ipv4L3ProtocolTraceContextElement(Ipv4L3ProtocolTraceContextElement::TX));
mathieu@1379
   215
  resolver->AddSource ("rx",
mathieu@1379
   216
                       TraceDoc ("receive ipv4 packet from incoming interface",
mathieu@1866
   217
                                 "Ptr<const Packet>", "packet received",
mathieu@1379
   218
                                 "uint32_t", "index of input ipv4 interface"),
mathieu@1372
   219
                       m_rxTrace, Ipv4L3ProtocolTraceContextElement(Ipv4L3ProtocolTraceContextElement::RX));
mathieu@1379
   220
  resolver->AddSource ("drop", 
mathieu@1379
   221
                       TraceDoc ("drop ipv4 packet",
mathieu@1866
   222
                                 "Ptr<const Packet>", "packet dropped"),
mathieu@1372
   223
                       m_dropTrace, Ipv4L3ProtocolTraceContextElement (Ipv4L3ProtocolTraceContextElement::DROP));
mathieu@1341
   224
  resolver->AddArray ("interfaces", 
mathieu@1341
   225
                      m_interfaces.begin (), m_interfaces.end (), 
mathieu@1341
   226
                      Ipv4L3ProtocolInterfaceIndex ());
tomh@345
   227
  return resolver;
tomh@345
   228
}
tomh@345
   229
mathieu@236
   230
void 
mathieu@734
   231
Ipv4L3Protocol::SetDefaultTtl (uint8_t ttl)
mathieu@236
   232
{
craigdo@1504
   233
  NS_LOG_FUNCTION;
mathieu@236
   234
  m_defaultTtl = ttl;
mathieu@236
   235
}
mathieu@236
   236
    
mathieu@236
   237
mathieu@236
   238
void 
mathieu@734
   239
Ipv4L3Protocol::AddHostRouteTo (Ipv4Address dest, 
tomh@345
   240
                      Ipv4Address nextHop, 
tomh@345
   241
                      uint32_t interface)
mathieu@236
   242
{
craigdo@1504
   243
  NS_LOG_FUNCTION;
tomh@1828
   244
  NS_LOG_PARAMS (this << dest << nextHop << interface);
gjc@983
   245
  m_staticRouting->AddHostRouteTo (dest, nextHop, interface);
mathieu@236
   246
}
craigdo@1429
   247
mathieu@236
   248
void 
mathieu@734
   249
Ipv4L3Protocol::AddHostRouteTo (Ipv4Address dest, 
mathieu@236
   250
				uint32_t interface)
mathieu@236
   251
{
craigdo@1504
   252
  NS_LOG_FUNCTION;
tomh@1828
   253
  NS_LOG_PARAMS (this << dest << interface);
gjc@983
   254
  m_staticRouting->AddHostRouteTo (dest, interface);
mathieu@236
   255
}
craigdo@1429
   256
mathieu@236
   257
void 
mathieu@734
   258
Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network, 
mathieu@236
   259
				   Ipv4Mask networkMask, 
mathieu@236
   260
				   Ipv4Address nextHop, 
mathieu@236
   261
				   uint32_t interface)
mathieu@236
   262
{
craigdo@1504
   263
  NS_LOG_FUNCTION;
tomh@1828
   264
  NS_LOG_PARAMS (this << network << networkMask << nextHop << interface);
gjc@983
   265
  m_staticRouting->AddNetworkRouteTo (network, networkMask, nextHop, interface);
mathieu@236
   266
}
craigdo@1504
   267
mathieu@236
   268
void 
mathieu@734
   269
Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network, 
mathieu@236
   270
				   Ipv4Mask networkMask, 
mathieu@236
   271
				   uint32_t interface)
mathieu@236
   272
{
craigdo@1504
   273
  NS_LOG_FUNCTION; 
tomh@1828
   274
  NS_LOG_PARAMS (this << network << networkMask << interface);
gjc@983
   275
  m_staticRouting->AddNetworkRouteTo (network, networkMask, interface);
mathieu@236
   276
}
craigdo@1504
   277
mathieu@236
   278
void 
mathieu@734
   279
Ipv4L3Protocol::SetDefaultRoute (Ipv4Address nextHop, 
mathieu@236
   280
				 uint32_t interface)
mathieu@236
   281
{
craigdo@1504
   282
  NS_LOG_FUNCTION;
tomh@1828
   283
  NS_LOG_PARAMS (this << nextHop << interface);
gjc@983
   284
  m_staticRouting->SetDefaultRoute (nextHop, interface);
mathieu@236
   285
}
mathieu@236
   286
mathieu@1235
   287
void
craigdo@1432
   288
Ipv4L3Protocol::Lookup (
craigdo@1432
   289
  Ipv4Header const &ipHeader,
mathieu@1866
   290
  Ptr<Packet> packet,
craigdo@1432
   291
  Ipv4RoutingProtocol::RouteReplyCallback routeReply)
mathieu@1235
   292
{
craigdo@1504
   293
  NS_LOG_FUNCTION;
mathieu@1870
   294
  NS_LOG_PARAMS (this << &ipHeader << packet << &routeReply);
craigdo@1432
   295
craigdo@1432
   296
  Lookup (Ipv4RoutingProtocol::IF_INDEX_ANY, ipHeader, packet, routeReply);
craigdo@1432
   297
}
gjc@983
   298
gjc@983
   299
void
craigdo@1432
   300
Ipv4L3Protocol::Lookup (
craigdo@1432
   301
  uint32_t ifIndex,
craigdo@1432
   302
  Ipv4Header const &ipHeader,
mathieu@1866
   303
  Ptr<Packet> packet,
craigdo@1432
   304
  Ipv4RoutingProtocol::RouteReplyCallback routeReply)
mathieu@236
   305
{
craigdo@1504
   306
  NS_LOG_FUNCTION;
mathieu@1870
   307
  NS_LOG_PARAMS (this << ifIndex << &ipHeader << packet << &routeReply);
craigdo@1429
   308
craigdo@1428
   309
  for (Ipv4RoutingProtocolList::const_iterator rprotoIter = 
craigdo@1428
   310
         m_routingProtocols.begin ();
craigdo@1428
   311
       rprotoIter != m_routingProtocols.end (); 
craigdo@1428
   312
       rprotoIter++)
mathieu@236
   313
    {
craigdo@1504
   314
      NS_LOG_LOGIC ("Requesting route");
craigdo@1432
   315
      if ((*rprotoIter).second->RequestRoute (ifIndex, ipHeader, packet, 
craigdo@1432
   316
                                              routeReply))
gjc@983
   317
        return;
mathieu@236
   318
    }
craigdo@1428
   319
craigdo@1440
   320
  if (ipHeader.GetDestination ().IsMulticast () && 
craigdo@1440
   321
      ifIndex == Ipv4RoutingProtocol::IF_INDEX_ANY)
craigdo@1440
   322
    {
craigdo@1504
   323
      NS_LOG_LOGIC ("Multicast destination with local source");
craigdo@1440
   324
//
craigdo@1445
   325
// We have a multicast packet originating from the current node and were not
craigdo@1445
   326
// able to send it using the usual RequestRoute process.  Since the usual
craigdo@1445
   327
// process includes trying to use a default multicast route, this means that
craigdo@1445
   328
// there was no specific route out of the node found, and there was no default
craigdo@1445
   329
// multicast route set.
craigdo@1440
   330
//
craigdo@1445
   331
// The fallback position is to look for a default unicast route and use that
craigdo@1445
   332
// to get the packet off the node if we have one.
craigdo@1445
   333
//
craigdo@1445
   334
      Ipv4Route *route = m_staticRouting->GetDefaultRoute ();
craigdo@1440
   335
craigdo@1445
   336
      if (route)
craigdo@1440
   337
        {
craigdo@1504
   338
          NS_LOG_LOGIC ("Local source. Using unicast default route for "
craigdo@1504
   339
            "multicast packet");
craigdo@1445
   340
craigdo@1445
   341
          routeReply (true, *route, packet, ipHeader);
craigdo@1445
   342
          return;
craigdo@1440
   343
        }
craigdo@1440
   344
    }
craigdo@1445
   345
//
craigdo@1445
   346
// No route found
craigdo@1445
   347
//
gjc@983
   348
  routeReply (false, Ipv4Route (), packet, ipHeader);
gjc@983
   349
}
gjc@983
   350
gjc@983
   351
void
gjc@983
   352
Ipv4L3Protocol::AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol,
gjc@983
   353
                                    int priority)
gjc@983
   354
{
craigdo@1504
   355
  NS_LOG_FUNCTION;
tomh@1828
   356
  NS_LOG_PARAMS (this << &routingProtocol << priority);
gjc@983
   357
  m_routingProtocols.push_back
gjc@983
   358
    (std::pair<int, Ptr<Ipv4RoutingProtocol> > (-priority, routingProtocol));
gjc@983
   359
  m_routingProtocols.sort ();
mathieu@236
   360
}
mathieu@236
   361
mathieu@236
   362
uint32_t 
mathieu@734
   363
Ipv4L3Protocol::GetNRoutes (void)
mathieu@236
   364
{
craigdo@1504
   365
  NS_LOG_FUNCTION;
gjc@983
   366
  return m_staticRouting->GetNRoutes ();
mathieu@236
   367
}
gjc@983
   368
mathieu@236
   369
Ipv4Route *
mathieu@734
   370
Ipv4L3Protocol::GetRoute (uint32_t index)
mathieu@236
   371
{
craigdo@1504
   372
  NS_LOG_FUNCTION;
gjc@983
   373
  return m_staticRouting->GetRoute (index);
mathieu@236
   374
}
gjc@983
   375
mathieu@236
   376
void 
mathieu@734
   377
Ipv4L3Protocol::RemoveRoute (uint32_t index)
mathieu@236
   378
{
craigdo@1504
   379
  NS_LOG_FUNCTION;
tomh@1828
   380
  NS_LOG_PARAMS (this << index);
gjc@983
   381
  m_staticRouting->RemoveRoute (index);
mathieu@236
   382
}
mathieu@236
   383
craigdo@1428
   384
void 
craigdo@1428
   385
Ipv4L3Protocol::AddMulticastRoute (Ipv4Address origin,
craigdo@1428
   386
                                   Ipv4Address group,
craigdo@1428
   387
                                   uint32_t inputInterface,
craigdo@1428
   388
                                   std::vector<uint32_t> outputInterfaces)
craigdo@1428
   389
{
craigdo@1504
   390
  NS_LOG_FUNCTION; 
tomh@1828
   391
  NS_LOG_PARAMS (this << origin << group << inputInterface << &outputInterfaces);
craigdo@1429
   392
craigdo@1428
   393
  m_staticRouting->AddMulticastRoute (origin, group, inputInterface,
craigdo@1428
   394
    outputInterfaces);
craigdo@1428
   395
}
craigdo@1428
   396
craigdo@1442
   397
void 
craigdo@1444
   398
Ipv4L3Protocol::SetDefaultMulticastRoute (uint32_t outputInterface)
craigdo@1442
   399
{
craigdo@1504
   400
  NS_LOG_FUNCTION;
tomh@1828
   401
  NS_LOG_PARAMS (this << outputInterface);
craigdo@1442
   402
craigdo@1444
   403
  m_staticRouting->SetDefaultMulticastRoute (outputInterface);
craigdo@1442
   404
}
craigdo@1442
   405
craigdo@1428
   406
uint32_t 
craigdo@1428
   407
Ipv4L3Protocol::GetNMulticastRoutes (void) const
craigdo@1428
   408
{
craigdo@1504
   409
  NS_LOG_FUNCTION;
craigdo@1428
   410
  return m_staticRouting->GetNMulticastRoutes ();
craigdo@1428
   411
}
craigdo@1428
   412
craigdo@1428
   413
Ipv4MulticastRoute *
craigdo@1428
   414
Ipv4L3Protocol::GetMulticastRoute (uint32_t index) const
craigdo@1428
   415
{
craigdo@1504
   416
  NS_LOG_FUNCTION;
tomh@1828
   417
  NS_LOG_PARAMS (this << index);
craigdo@1428
   418
  return m_staticRouting->GetMulticastRoute (index);
craigdo@1428
   419
}
craigdo@1428
   420
craigdo@1428
   421
void 
craigdo@1428
   422
Ipv4L3Protocol::RemoveMulticastRoute (Ipv4Address origin,
craigdo@1428
   423
                                       Ipv4Address group,
craigdo@1428
   424
                                       uint32_t inputInterface)
craigdo@1428
   425
{
craigdo@1504
   426
  NS_LOG_FUNCTION;
tomh@1828
   427
  NS_LOG_PARAMS (this << origin << group << inputInterface);
craigdo@1428
   428
  m_staticRouting->RemoveMulticastRoute (origin, group, inputInterface);
craigdo@1428
   429
}
craigdo@1428
   430
craigdo@1428
   431
void 
craigdo@1428
   432
Ipv4L3Protocol::RemoveMulticastRoute (uint32_t index)
craigdo@1428
   433
{
craigdo@1504
   434
  NS_LOG_FUNCTION;
tomh@1828
   435
  NS_LOG_PARAMS (this << index);
craigdo@1428
   436
  m_staticRouting->RemoveMulticastRoute (index);
craigdo@1428
   437
}
mathieu@236
   438
mathieu@236
   439
uint32_t 
mathieu@734
   440
Ipv4L3Protocol::AddInterface (Ptr<NetDevice> device)
mathieu@444
   441
{
craigdo@1504
   442
  NS_LOG_FUNCTION;
tomh@1828
   443
  NS_LOG_PARAMS (this << &device);
mathieu@2230
   444
  Ptr<Ipv4Interface> interface = CreateObject<ArpIpv4Interface> (m_node, device);
mathieu@444
   445
  return AddIpv4Interface (interface);
mathieu@444
   446
}
craigdo@1429
   447
mathieu@444
   448
uint32_t 
mathieu@1341
   449
Ipv4L3Protocol::AddIpv4Interface (Ptr<Ipv4Interface>interface)
mathieu@236
   450
{
craigdo@1504
   451
  NS_LOG_FUNCTION;
tomh@1828
   452
  NS_LOG_PARAMS (this << interface);
mathieu@236
   453
  uint32_t index = m_nInterfaces;
mathieu@236
   454
  m_interfaces.push_back (interface);
mathieu@236
   455
  m_nInterfaces++;
mathieu@236
   456
  return index;
mathieu@236
   457
}
craigdo@1429
   458
mathieu@1341
   459
Ptr<Ipv4Interface>
mathieu@734
   460
Ipv4L3Protocol::GetInterface (uint32_t index) const
mathieu@236
   461
{
craigdo@1504
   462
  NS_LOG_FUNCTION;
tomh@1828
   463
  NS_LOG_PARAMS (this << index);
mathieu@236
   464
  uint32_t tmp = 0;
mathieu@236
   465
  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
mathieu@236
   466
    {
mathieu@236
   467
      if (index == tmp) 
mathieu@236
   468
	{
mathieu@236
   469
	  return *i;
mathieu@236
   470
	}
mathieu@236
   471
      tmp++;
mathieu@236
   472
    }
mathieu@236
   473
  return 0;
mathieu@236
   474
}
craigdo@1429
   475
mathieu@236
   476
uint32_t 
mathieu@734
   477
Ipv4L3Protocol::GetNInterfaces (void) const
mathieu@236
   478
{
craigdo@1504
   479
  NS_LOG_FUNCTION;
mathieu@236
   480
  return m_nInterfaces;
mathieu@236
   481
}
mathieu@236
   482
craigdo@1440
   483
uint32_t 
craigdo@1440
   484
Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr) const
craigdo@1440
   485
{
craigdo@1504
   486
  NS_LOG_FUNCTION;
tomh@1828
   487
  NS_LOG_PARAMS (this << addr);
craigdo@1440
   488
craigdo@1440
   489
  uint32_t ifIndex = 0;
craigdo@1440
   490
  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); 
craigdo@1440
   491
       i != m_interfaces.end (); 
craigdo@1440
   492
       i++, ifIndex++)
craigdo@1440
   493
    {
craigdo@1440
   494
      if ((*i)->GetAddress () == addr)
craigdo@1440
   495
        {
craigdo@1440
   496
          return ifIndex;
craigdo@1440
   497
        }
craigdo@1440
   498
    }
craigdo@1440
   499
craigdo@1440
   500
  NS_ASSERT_MSG(false, "Ipv4L3Protocol::FindInterfaceForAddr (): "
craigdo@1440
   501
    "Interface not found for IP address");
craigdo@1440
   502
  return 0;
craigdo@1440
   503
}
craigdo@1440
   504
craigdo@1440
   505
uint32_t 
craigdo@1440
   506
Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const
craigdo@1440
   507
{
craigdo@1504
   508
  NS_LOG_FUNCTION;
tomh@1828
   509
  NS_LOG_PARAMS (this << addr << mask);
craigdo@1440
   510
craigdo@1440
   511
  uint32_t ifIndex = 0;
craigdo@1440
   512
  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); 
craigdo@1440
   513
       i != m_interfaces.end (); 
craigdo@1440
   514
       i++, ifIndex++)
craigdo@1440
   515
    {
craigdo@1440
   516
      if ((*i)->GetAddress ().CombineMask (mask) == addr.CombineMask (mask))
craigdo@1440
   517
        {
craigdo@1440
   518
          return ifIndex;
craigdo@1440
   519
        }
craigdo@1440
   520
    }
craigdo@1440
   521
craigdo@1440
   522
  NS_ASSERT_MSG(false, "Ipv4L3Protocol::FindInterfaceForAddr (): "
craigdo@1440
   523
    "Interface not found for masked IP address");
craigdo@1440
   524
  return 0;
craigdo@1440
   525
}
craigdo@1440
   526
mathieu@1341
   527
Ptr<Ipv4Interface>
mathieu@734
   528
Ipv4L3Protocol::FindInterfaceForDevice (Ptr<const NetDevice> device)
mathieu@242
   529
{
craigdo@1504
   530
  NS_LOG_FUNCTION;
tomh@1828
   531
  NS_LOG_PARAMS (this << &device);
mathieu@242
   532
  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
mathieu@242
   533
    {
mathieu@568
   534
      if ((*i)->GetDevice () == device)
mathieu@242
   535
        {
mathieu@242
   536
          return *i;
mathieu@242
   537
        }
mathieu@242
   538
    }
mathieu@242
   539
  return 0;
mathieu@242
   540
}  
mathieu@236
   541
mathieu@236
   542
void 
mathieu@1866
   543
Ipv4L3Protocol::Receive( Ptr<NetDevice> device, Ptr<Packet> packet, uint16_t protocol, const Address &from)
mathieu@236
   544
{
craigdo@1504
   545
  NS_LOG_FUNCTION;
mathieu@1870
   546
  NS_LOG_PARAMS (this << &device << packet << protocol <<  from);
craigdo@1429
   547
craigdo@1504
   548
  NS_LOG_LOGIC ("Packet from " << from);
craigdo@1443
   549
mathieu@457
   550
  uint32_t index = 0;
gjc@1524
   551
  Ptr<Ipv4Interface> ipv4Interface;
craigdo@1432
   552
  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); 
craigdo@1432
   553
       i != m_interfaces.end (); 
craigdo@1432
   554
       i++)
mathieu@457
   555
    {
gjc@1524
   556
      ipv4Interface = *i;
gjc@1524
   557
      if (ipv4Interface->GetDevice () == device)
mathieu@457
   558
        {
mathieu@1866
   559
          m_rxTrace (packet, index);
mathieu@457
   560
          break;
mathieu@457
   561
        }
mathieu@457
   562
      index++;
mathieu@457
   563
    }
mathieu@236
   564
  Ipv4Header ipHeader;
mathieu@1866
   565
  packet->RemoveHeader (ipHeader);
mathieu@236
   566
mathieu@236
   567
  if (!ipHeader.IsChecksumOk ()) 
mathieu@236
   568
    {
mathieu@236
   569
      return;
mathieu@236
   570
    }
mathieu@236
   571
craigdo@1432
   572
  if (Forwarding (index, packet, ipHeader, device)) 
mathieu@236
   573
    {
mathieu@236
   574
      return;
mathieu@236
   575
    }
mathieu@236
   576
craigdo@1504
   577
  NS_LOG_LOGIC ("Forward up");
gjc@1524
   578
  ForwardUp (packet, ipHeader, ipv4Interface);
mathieu@236
   579
}
mathieu@236
   580
gjc@983
   581
mathieu@236
   582
void 
mathieu@1866
   583
Ipv4L3Protocol::Send (Ptr<Packet> packet, 
mathieu@457
   584
            Ipv4Address source, 
mathieu@457
   585
            Ipv4Address destination,
mathieu@457
   586
            uint8_t protocol)
mathieu@236
   587
{
craigdo@1504
   588
  NS_LOG_FUNCTION;
mathieu@1870
   589
  NS_LOG_PARAMS (this << packet << source << destination << protocol);
craigdo@1429
   590
mathieu@236
   591
  Ipv4Header ipHeader;
mathieu@236
   592
mathieu@236
   593
  ipHeader.SetSource (source);
mathieu@236
   594
  ipHeader.SetDestination (destination);
mathieu@236
   595
  ipHeader.SetProtocol (protocol);
mathieu@1866
   596
  ipHeader.SetPayloadSize (packet->GetSize ());
mathieu@236
   597
  ipHeader.SetTtl (m_defaultTtl);
mathieu@236
   598
  ipHeader.SetMayFragment ();
mathieu@236
   599
  ipHeader.SetIdentification (m_identification);
mathieu@236
   600
mathieu@236
   601
  m_identification ++;
mathieu@236
   602
gjc@983
   603
  if (destination.IsBroadcast ())
mathieu@236
   604
    {
gjc@983
   605
      uint32_t ifaceIndex = 0;
gjc@983
   606
      for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
gjc@983
   607
           ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
gjc@983
   608
        {
mathieu@1341
   609
          Ptr<Ipv4Interface> outInterface = *ifaceIter;
mathieu@1866
   610
          Ptr<Packet> packetCopy = packet->Copy ();
mathieu@1308
   611
mathieu@1866
   612
          NS_ASSERT (packetCopy->GetSize () <= outInterface->GetMtu ());
mathieu@1866
   613
          packetCopy->AddHeader (ipHeader);
mathieu@1308
   614
          m_txTrace (packetCopy, ifaceIndex);
mathieu@1308
   615
          outInterface->Send (packetCopy, destination);
gjc@983
   616
        }
gjc@983
   617
    }
gjc@983
   618
  else
gjc@983
   619
    {
gjc@983
   620
      // XXX Note here that in most ipv4 stacks in the world,
gjc@983
   621
      // the route calculation for an outgoing packet is not
gjc@983
   622
      // done in the ip layer. It is done within the application
gjc@983
   623
      // socket when the first packet is sent to avoid this
gjc@983
   624
      // costly lookup on a per-packet basis.
gjc@983
   625
      // That would require us to get the route from the packet,
gjc@983
   626
      // most likely with a packet tag. The higher layers do not
gjc@983
   627
      // do this yet for us.
gjc@983
   628
      Lookup (ipHeader, packet,
gjc@983
   629
              MakeCallback (&Ipv4L3Protocol::SendRealOut, this));
gjc@983
   630
    }
gjc@983
   631
}
gjc@983
   632
gjc@983
   633
void
gjc@983
   634
Ipv4L3Protocol::SendRealOut (bool found,
gjc@983
   635
                             Ipv4Route const &route,
mathieu@1866
   636
                             Ptr<Packet> packet,
gjc@983
   637
                             Ipv4Header const &ipHeader)
gjc@983
   638
{
craigdo@1504
   639
  NS_LOG_FUNCTION;
mathieu@1870
   640
  NS_LOG_PARAMS (this << found << &route << packet << &ipHeader);
craigdo@1429
   641
gjc@2325
   642
  packet->AddHeader (ipHeader);
gjc@983
   643
  if (!found)
gjc@983
   644
    {
craigdo@1504
   645
      NS_LOG_WARN ("No route to host.  Drop.");
tomh@345
   646
      m_dropTrace (packet);
mathieu@236
   647
      return;
mathieu@236
   648
    }
craigdo@1430
   649
craigdo@1504
   650
  NS_LOG_LOGIC ("Send via interface " << route.GetInterface ());
craigdo@1430
   651
mathieu@1341
   652
  Ptr<Ipv4Interface> outInterface = GetInterface (route.GetInterface ());
mathieu@1866
   653
  NS_ASSERT (packet->GetSize () <= outInterface->GetMtu ());
mathieu@457
   654
  m_txTrace (packet, route.GetInterface ());
mathieu@236
   655
  if (route.IsGateway ()) 
mathieu@236
   656
    {
craigdo@1504
   657
      NS_LOG_LOGIC ("Send to gateway " << route.GetGateway ());
mathieu@236
   658
      outInterface->Send (packet, route.GetGateway ());
mathieu@236
   659
    } 
mathieu@236
   660
  else 
mathieu@236
   661
    {
craigdo@1504
   662
      NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestination ());
gjc@983
   663
      outInterface->Send (packet, ipHeader.GetDestination ());
mathieu@236
   664
    }
mathieu@236
   665
}
mathieu@236
   666
mathieu@1235
   667
bool
craigdo@1432
   668
Ipv4L3Protocol::Forwarding (
craigdo@1432
   669
  uint32_t ifIndex, 
mathieu@1866
   670
  Ptr<Packet> packet, 
craigdo@1432
   671
  Ipv4Header &ipHeader, 
craigdo@1432
   672
  Ptr<NetDevice> device)
mathieu@1235
   673
{
craigdo@1504
   674
  NS_LOG_FUNCTION;
mathieu@1870
   675
  NS_LOG_PARAMS (ifIndex << packet << &ipHeader<< device);
mathieu@236
   676
mathieu@236
   677
  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
mathieu@236
   678
       i != m_interfaces.end (); i++) 
mathieu@236
   679
    {
mathieu@236
   680
      if ((*i)->GetAddress ().IsEqual (ipHeader.GetDestination ())) 
mathieu@236
   681
        {
craigdo@1504
   682
          NS_LOG_LOGIC ("For me (destination match)");
mathieu@236
   683
          return false;
mathieu@236
   684
        }
mathieu@236
   685
    }
mathieu@236
   686
  
mathieu@236
   687
  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
mathieu@236
   688
       i != m_interfaces.end (); i++) 
mathieu@236
   689
    {
mathieu@1341
   690
      Ptr<Ipv4Interface> interface = *i;
mathieu@568
   691
      if (interface->GetDevice () == device)
mathieu@236
   692
	{
mathieu@236
   693
	  if (ipHeader.GetDestination ().IsEqual (interface->GetBroadcast ())) 
mathieu@236
   694
	    {
craigdo@1504
   695
              NS_LOG_LOGIC ("For me (interface broadcast address)");
mathieu@236
   696
	      return false;
mathieu@236
   697
	    }
mathieu@236
   698
	  break;
mathieu@236
   699
	}
mathieu@236
   700
    }
mathieu@236
   701
      
gjc@983
   702
  if (ipHeader.GetDestination ().IsBroadcast ()) 
mathieu@236
   703
    {
craigdo@1504
   704
      NS_LOG_LOGIC ("For me (Ipv4Addr broadcast address)");
mathieu@236
   705
      return false;
mathieu@236
   706
    }
craigdo@1430
   707
mathieu@236
   708
  if (ipHeader.GetDestination ().IsEqual (Ipv4Address::GetAny ())) 
mathieu@236
   709
    {
craigdo@1504
   710
      NS_LOG_LOGIC ("For me (Ipv4Addr any address)");
mathieu@236
   711
      return false;
mathieu@236
   712
    }
craigdo@1430
   713
mathieu@236
   714
  if (ipHeader.GetTtl () == 1) 
mathieu@236
   715
    {
mathieu@236
   716
      // Should send ttl expired here
mathieu@236
   717
      // XXX
craigdo@1504
   718
      NS_LOG_LOGIC ("Not for me (TTL expired).  Drop");
tomh@345
   719
      m_dropTrace (packet);
mathieu@236
   720
      return true;
mathieu@236
   721
    }
mathieu@236
   722
  ipHeader.SetTtl (ipHeader.GetTtl () - 1);
gjc@983
   723
craigdo@1504
   724
  NS_LOG_LOGIC ("Forwarding packet.");
craigdo@1432
   725
  Lookup (ifIndex, ipHeader, packet,
gjc@983
   726
          MakeCallback (&Ipv4L3Protocol::SendRealOut, this));
craigdo@1428
   727
//
craigdo@1428
   728
// If this is a to a multicast address and this node is a member of the 
craigdo@1428
   729
// indicated group we need to return false so the multicast is forwarded up.
craigdo@1428
   730
// Note that we may have just forwarded this packet too.
craigdo@1428
   731
//
craigdo@1428
   732
  for (Ipv4MulticastGroupList::const_iterator i = m_multicastGroups.begin ();
craigdo@1428
   733
       i != m_multicastGroups.end (); i++) 
craigdo@1428
   734
    {
craigdo@1428
   735
      if ((*i).first.IsEqual (ipHeader.GetSource ()) &&
craigdo@1428
   736
          (*i).second.IsEqual (ipHeader.GetDestination ()))
craigdo@1428
   737
        {
craigdo@1504
   738
          NS_LOG_LOGIC ("For me (Joined multicast group)");
craigdo@1428
   739
          return false;
craigdo@1428
   740
        }
craigdo@1428
   741
    }
craigdo@1428
   742
  
craigdo@1504
   743
  NS_LOG_LOGIC("Not for me.");
mathieu@236
   744
  return true;
mathieu@236
   745
}
mathieu@236
   746
mathieu@236
   747
void
mathieu@1866
   748
Ipv4L3Protocol::ForwardUp (Ptr<Packet> p, Ipv4Header const&ip,
gjc@1524
   749
                           Ptr<Ipv4Interface> incomingInterface)
mathieu@236
   750
{
craigdo@1504
   751
  NS_LOG_FUNCTION;
mathieu@1870
   752
  NS_LOG_PARAMS (this << p << &ip);
craigdo@1504
   753
mathieu@2257
   754
  Ptr<Ipv4L4Demux> demux = m_node->GetObject<Ipv4L4Demux> ();
mathieu@568
   755
  Ptr<Ipv4L4Protocol> protocol = demux->GetProtocol (ip.GetProtocol ());
gjc@1524
   756
  protocol->Receive (p, ip.GetSource (), ip.GetDestination (), incomingInterface);
mathieu@236
   757
}
mathieu@236
   758
mathieu@444
   759
void 
craigdo@1428
   760
Ipv4L3Protocol::JoinMulticastGroup (Ipv4Address origin, Ipv4Address group)
craigdo@1428
   761
{
craigdo@1504
   762
  NS_LOG_FUNCTION;
tomh@1828
   763
  NS_LOG_PARAMS (this << origin << group);
craigdo@1428
   764
  m_multicastGroups.push_back(
craigdo@1428
   765
    std::pair<Ipv4Address, Ipv4Address> (origin, group));
craigdo@1428
   766
}
craigdo@1428
   767
craigdo@1428
   768
void
craigdo@1428
   769
Ipv4L3Protocol::LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group)
craigdo@1428
   770
{
craigdo@1504
   771
  NS_LOG_FUNCTION;
tomh@1828
   772
  NS_LOG_PARAMS (this << origin << group);
craigdo@1429
   773
craigdo@1428
   774
  for (Ipv4MulticastGroupList::iterator i = m_multicastGroups.begin ();
craigdo@1428
   775
       i != m_multicastGroups.end (); 
craigdo@1428
   776
       i++)
craigdo@1428
   777
    {
craigdo@1428
   778
      if ((*i).first.IsEqual(origin) && (*i).second.IsEqual(group))
craigdo@1428
   779
        {
craigdo@1428
   780
          m_multicastGroups.erase (i);
craigdo@1428
   781
          return;
craigdo@1428
   782
        }
craigdo@1428
   783
    }
craigdo@1428
   784
}
craigdo@1428
   785
craigdo@1428
   786
void 
mathieu@734
   787
Ipv4L3Protocol::SetAddress (uint32_t i, Ipv4Address address)
mathieu@444
   788
{
craigdo@1504
   789
  NS_LOG_FUNCTION;
tomh@1828
   790
  NS_LOG_PARAMS (this << i << address);
mathieu@1341
   791
  Ptr<Ipv4Interface> interface = GetInterface (i);
mathieu@444
   792
  interface->SetAddress (address);
mathieu@444
   793
}
craigdo@1429
   794
mathieu@444
   795
void 
mathieu@734
   796
Ipv4L3Protocol::SetNetworkMask (uint32_t i, Ipv4Mask mask)
mathieu@444
   797
{
craigdo@1504
   798
  NS_LOG_FUNCTION;
tomh@1828
   799
  NS_LOG_PARAMS (this << i << mask);
mathieu@1341
   800
  Ptr<Ipv4Interface> interface = GetInterface (i);
mathieu@444
   801
  interface->SetNetworkMask (mask);
mathieu@444
   802
}
craigdo@1429
   803
mathieu@444
   804
Ipv4Mask 
mathieu@734
   805
Ipv4L3Protocol::GetNetworkMask (uint32_t i) const
mathieu@444
   806
{
craigdo@1504
   807
  NS_LOG_FUNCTION;
tomh@1828
   808
  NS_LOG_PARAMS (this << i);
mathieu@1341
   809
  Ptr<Ipv4Interface> interface = GetInterface (i);
mathieu@444
   810
  return interface->GetNetworkMask ();
mathieu@444
   811
}
craigdo@1429
   812
mathieu@444
   813
Ipv4Address 
mathieu@734
   814
Ipv4L3Protocol::GetAddress (uint32_t i) const
mathieu@444
   815
{
craigdo@1504
   816
  NS_LOG_FUNCTION;
tomh@1828
   817
  NS_LOG_PARAMS (this << i);
mathieu@1341
   818
  Ptr<Ipv4Interface> interface = GetInterface (i);
mathieu@444
   819
  return interface->GetAddress ();
mathieu@444
   820
}
craigdo@1429
   821
tomh@1776
   822
void 
tomh@1776
   823
Ipv4L3Protocol::SetMetric (uint32_t i, uint16_t metric)
tomh@1776
   824
{
tomh@1776
   825
  NS_LOG_FUNCTION;
tomh@1828
   826
  NS_LOG_PARAMS ("(" << i << ", " << metric << ")");
tomh@1776
   827
  Ptr<Ipv4Interface> interface = GetInterface (i);
tomh@1776
   828
  interface->SetMetric (metric);
tomh@1776
   829
}
tomh@1776
   830
tomh@1776
   831
uint16_t
tomh@1776
   832
Ipv4L3Protocol::GetMetric (uint32_t i) const
tomh@1776
   833
{
tomh@1776
   834
  NS_LOG_FUNCTION;
tomh@1828
   835
  NS_LOG_PARAMS ("(" << i << ")");
tomh@1776
   836
  Ptr<Ipv4Interface> interface = GetInterface (i);
tomh@1776
   837
  return interface->GetMetric ();
tomh@1776
   838
}
tomh@1776
   839
craigdo@1434
   840
bool
craigdo@1434
   841
Ipv4L3Protocol::GetIfIndexForDestination (
craigdo@1434
   842
  Ipv4Address destination, uint32_t& ifIndex) const
craigdo@1434
   843
{
craigdo@1504
   844
  NS_LOG_FUNCTION;
tomh@1828
   845
  NS_LOG_PARAMS (this << destination << &ifIndex);
craigdo@1442
   846
//
craigdo@1442
   847
// The first thing we do in trying to determine a source address is to 
craigdo@1442
   848
// consult the routing protocols.  These will also check for a default route
craigdo@1442
   849
// if one has been set.
craigdo@1442
   850
//
craigdo@1434
   851
  for (Ipv4RoutingProtocolList::const_iterator i = m_routingProtocols.begin ();
craigdo@1434
   852
       i != m_routingProtocols.end (); 
craigdo@1434
   853
       i++)
craigdo@1434
   854
    {
craigdo@1504
   855
      NS_LOG_LOGIC ("Requesting Source Address");
craigdo@1435
   856
      uint32_t ifIndexTmp;
craigdo@1434
   857
craigdo@1435
   858
      if ((*i).second->RequestIfIndex (destination, ifIndexTmp))
craigdo@1434
   859
        {
craigdo@1504
   860
          NS_LOG_LOGIC ("Found ifIndex " << ifIndexTmp);
craigdo@1435
   861
          ifIndex = ifIndexTmp;
craigdo@1434
   862
          return true;
craigdo@1434
   863
        }
craigdo@1434
   864
    }
craigdo@1440
   865
//
craigdo@1442
   866
// If there's no routing table entry telling us what *single* interface will 
craigdo@1442
   867
// be used to send a packet to this destination, we'll have to just pick one.  
craigdo@1440
   868
// If there's only one interface on this node, a good answer isn't very hard
craigdo@1440
   869
// to come up with.  Before jumping to any conclusions, remember that the 
craigdo@1440
   870
// zeroth interface is the loopback interface, so what we actually want is
craigdo@1440
   871
// a situation where there are exactly two interfaces on the node, in which
craigdo@1442
   872
// case interface one is the "single" interface connected to the outside world.
craigdo@1440
   873
//
craigdo@1440
   874
  if (GetNInterfaces () == 2)
craigdo@1440
   875
    {
craigdo@1504
   876
      NS_LOG_LOGIC ("One Interface.  Using interface 1.");
craigdo@1440
   877
      ifIndex = 1;
craigdo@1440
   878
      return true;
craigdo@1440
   879
    }
craigdo@1440
   880
//
craigdo@1440
   881
// If we fall through to here, we have a node with multiple interfaces and
craigdo@1442
   882
// no routes to guide us in determining what interface to choose.  Either
craigdo@1442
   883
// no default route was found (for unicast or multicast), or in the case of a
craigdo@1442
   884
// multicast, the default route contained multiple outbound interfaces.
craigdo@1442
   885
//
craigdo@1442
   886
// The fallback position is to just get the unicast default route and use 
craigdo@1442
   887
// the outgoing interface specified there.  We don't want to leave the source
craigdo@1442
   888
// address unset, so we just assert here.
craigdo@1442
   889
//
craigdo@1442
   890
// N.B. that in the case of a multicast with a route containing multiple
craigdo@1442
   891
// outgoing interfaces, the source address of packets from that node will be
craigdo@1442
   892
// set to the IP address of the interface set in the default unicast route.
craigdo@1442
   893
// Also, in the case of a broadcast, the same will be true.
craigdo@1442
   894
//
craigdo@1504
   895
  NS_LOG_LOGIC ("Using default unicast route");
craigdo@1440
   896
  Ipv4Route *route = m_staticRouting->GetDefaultRoute ();
craigdo@1440
   897
gjc@2324
   898
  if (route == NULL)
gjc@2324
   899
    {
gjc@2324
   900
      NS_LOG_LOGIC ("Ipv4L3Protocol::GetIfIndexForDestination (): "
gjc@2324
   901
                    "Unable to determine outbound interface.  No default route set");
gjc@2324
   902
      return false;
gjc@2324
   903
    }
craigdo@1440
   904
craigdo@1440
   905
  ifIndex = route->GetInterface ();
craigdo@1440
   906
craigdo@1504
   907
  NS_LOG_LOGIC ("Default route specifies interface " << ifIndex);
craigdo@1440
   908
  return true;
craigdo@1434
   909
}
craigdo@1434
   910
mathieu@444
   911
uint16_t 
mathieu@734
   912
Ipv4L3Protocol::GetMtu (uint32_t i) const
mathieu@444
   913
{
craigdo@1504
   914
  NS_LOG_FUNCTION;
tomh@1828
   915
  NS_LOG_PARAMS (this << i);
mathieu@1341
   916
  Ptr<Ipv4Interface> interface = GetInterface (i);
mathieu@444
   917
  return interface->GetMtu ();
mathieu@444
   918
}
craigdo@1429
   919
mathieu@444
   920
bool 
mathieu@734
   921
Ipv4L3Protocol::IsUp (uint32_t i) const
mathieu@444
   922
{
craigdo@1504
   923
  NS_LOG_FUNCTION;
tomh@1828
   924
  NS_LOG_PARAMS (this << i);
mathieu@1341
   925
  Ptr<Ipv4Interface> interface = GetInterface (i);
mathieu@444
   926
  return interface->IsUp ();
mathieu@444
   927
}
craigdo@1429
   928
mathieu@444
   929
void 
mathieu@734
   930
Ipv4L3Protocol::SetUp (uint32_t i)
mathieu@444
   931
{
craigdo@1504
   932
  NS_LOG_FUNCTION;
tomh@1828
   933
  NS_LOG_PARAMS (this << i);
mathieu@1341
   934
  Ptr<Ipv4Interface> interface = GetInterface (i);
mathieu@444
   935
  interface->SetUp ();
tomh@979
   936
tomh@979
   937
  // If interface address and network mask have been set, add a route
tomh@979
   938
  // to the network of the interface (like e.g. ifconfig does on a
tomh@979
   939
  // Linux box)
tomh@979
   940
  if ((interface->GetAddress ()) != (Ipv4Address ())
tomh@979
   941
      && (interface->GetNetworkMask ()) != (Ipv4Mask ()))
tomh@979
   942
    {
tomh@979
   943
      AddNetworkRouteTo (interface->GetAddress ().CombineMask (interface->GetNetworkMask ()),
tomh@979
   944
                         interface->GetNetworkMask (), i);
tomh@979
   945
    }
mathieu@444
   946
}
craigdo@1429
   947
mathieu@444
   948
void 
tomh@979
   949
Ipv4L3Protocol::SetDown (uint32_t ifaceIndex)
mathieu@444
   950
{
craigdo@1504
   951
  NS_LOG_FUNCTION;
tomh@1828
   952
  NS_LOG_PARAMS (this << ifaceIndex);
mathieu@1341
   953
  Ptr<Ipv4Interface> interface = GetInterface (ifaceIndex);
mathieu@444
   954
  interface->SetDown ();
tomh@979
   955
tomh@979
   956
  // Remove all routes that are going through this interface
tomh@979
   957
  bool modified = true;
tomh@979
   958
  while (modified)
tomh@979
   959
    {
tomh@979
   960
      modified = false;
tomh@979
   961
      for (uint32_t i = 0; i < GetNRoutes (); i++)
tomh@979
   962
        {
tomh@979
   963
          Ipv4Route *route = GetRoute (i);
tomh@979
   964
          if (route->GetInterface () == ifaceIndex)
tomh@979
   965
            {
tomh@979
   966
              RemoveRoute (i);
tomh@979
   967
              modified = true;
tomh@979
   968
              break;
tomh@979
   969
            }
tomh@979
   970
        }
tomh@979
   971
    }
mathieu@444
   972
}
mathieu@444
   973
mathieu@236
   974
}//namespace ns3