src/devices/bridge/bridge-net-device.cc
author vincent@clarinet.u-strasbg.fr
Fri Nov 07 11:36:15 2008 -0800 (2008-11-07)
changeset 3852 9cf7ad0cac85
parent 3841 1e7abf5fca79
child 3936 e525995ce5dc
permissions -rw-r--r--
Initial IPv6 capability
gjc@3439
     1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
gjc@3439
     2
/*
gjc@3439
     3
 * This program is free software; you can redistribute it and/or modify
gjc@3439
     4
 * it under the terms of the GNU General Public License version 2 as
gjc@3439
     5
 * published by the Free Software Foundation;
gjc@3439
     6
 *
gjc@3439
     7
 * This program is distributed in the hope that it will be useful,
gjc@3439
     8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
gjc@3439
     9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
gjc@3439
    10
 * GNU General Public License for more details.
gjc@3439
    11
 *
gjc@3439
    12
 * You should have received a copy of the GNU General Public License
gjc@3439
    13
 * along with this program; if not, write to the Free Software
gjc@3439
    14
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
gjc@3439
    15
 *
gjc@3439
    16
 * Author: Gustavo Carneiro  <gjc@inescporto.pt>
gjc@3439
    17
 */
gjc@3439
    18
#include "bridge-net-device.h"
gjc@3439
    19
#include "ns3/node.h"
gjc@3439
    20
#include "ns3/channel.h"
gjc@3439
    21
#include "ns3/packet.h"
gjc@3439
    22
#include "ns3/log.h"
gjc@3444
    23
#include "ns3/boolean.h"
gjc@3444
    24
#include "ns3/simulator.h"
gjc@3439
    25
gjc@3439
    26
NS_LOG_COMPONENT_DEFINE ("BridgeNetDevice");
gjc@3439
    27
gjc@3439
    28
namespace ns3 {
gjc@3439
    29
mathieu@3519
    30
NS_OBJECT_ENSURE_REGISTERED (BridgeNetDevice);
mathieu@3519
    31
gjc@3439
    32
gjc@3439
    33
TypeId
gjc@3439
    34
BridgeNetDevice::GetTypeId (void)
gjc@3439
    35
{
gjc@3439
    36
  static TypeId tid = TypeId ("ns3::BridgeNetDevice")
gjc@3439
    37
    .SetParent<NetDevice> ()
gjc@3439
    38
    .AddConstructor<BridgeNetDevice> ()
gjc@3444
    39
    .AddAttribute ("EnableLearning",
gjc@3444
    40
                   "Enable the learning mode of the Learning Bridge",
gjc@3444
    41
                   BooleanValue (true),
gjc@3444
    42
                   MakeBooleanAccessor (&BridgeNetDevice::m_enableLearning),
gjc@3444
    43
                   MakeBooleanChecker ())
gjc@3444
    44
    .AddAttribute ("ExpirationTime",
gjc@3444
    45
                   "Time it takes for learned MAC state entry to expire.",
gjc@3444
    46
                   TimeValue (Seconds (30)),
gjc@3444
    47
                   MakeTimeAccessor (&BridgeNetDevice::m_expirationTime),
gjc@3444
    48
                   MakeTimeChecker ())
gjc@3439
    49
    ;
gjc@3439
    50
  return tid;
gjc@3439
    51
}
gjc@3439
    52
gjc@3439
    53
gjc@3439
    54
BridgeNetDevice::BridgeNetDevice ()
gjc@3439
    55
  : m_node (0),
gjc@3439
    56
    m_name (""),
gjc@3444
    57
    m_ifIndex (0),
gjc@3444
    58
    m_mtu (0xffff)
gjc@3449
    59
{
gjc@3449
    60
  m_channel = CreateObject<BridgeChannel> ();
gjc@3449
    61
}
gjc@3439
    62
gjc@3439
    63
void
mathieu@3548
    64
BridgeNetDevice::ReceiveFromDevice (Ptr<NetDevice> incomingPort, Ptr<const Packet> packet, uint16_t protocol,
gjc@3448
    65
                                    Address const &src, Address const &dst, PacketType packetType)
gjc@3439
    66
{
gjc@3439
    67
  NS_LOG_FUNCTION_NOARGS ();
gjc@3443
    68
  NS_LOG_DEBUG ("UID is " << packet->GetUid ());
gjc@3439
    69
gjc@3439
    70
  Mac48Address src48 = Mac48Address::ConvertFrom (src);
gjc@3439
    71
  Mac48Address dst48 = Mac48Address::ConvertFrom (dst);
gjc@3439
    72
gjc@3460
    73
  if (!m_promiscRxCallback.IsNull ())
gjc@3460
    74
    {
gjc@3460
    75
      m_promiscRxCallback (this, packet, protocol, src, dst, packetType);
gjc@3460
    76
    }
gjc@3448
    77
gjc@3448
    78
  switch (packetType)
gjc@3439
    79
    {
gjc@3448
    80
    case PACKET_HOST:
gjc@3448
    81
      if (dst48 == m_address)
gjc@3448
    82
        {
gjc@3460
    83
          m_rxCallback (this, packet, protocol, src);
gjc@3448
    84
        }
gjc@3448
    85
      break;
gjc@3439
    86
gjc@3448
    87
    case PACKET_BROADCAST:
gjc@3448
    88
    case PACKET_MULTICAST:
gjc@3460
    89
      m_rxCallback (this, packet, protocol, src);
gjc@3448
    90
      ForwardBroadcast (incomingPort, packet, protocol, src48, dst48);
gjc@3448
    91
      break;
gjc@3439
    92
gjc@3448
    93
    case PACKET_OTHERHOST:
gjc@3444
    94
      ForwardUnicast (incomingPort, packet, protocol, src48, dst48);
gjc@3448
    95
      break;
gjc@3439
    96
    }
gjc@3439
    97
}
gjc@3439
    98
gjc@3439
    99
void
mathieu@3548
   100
BridgeNetDevice::ForwardUnicast (Ptr<NetDevice> incomingPort, Ptr<const Packet> packet,
gjc@3444
   101
                                 uint16_t protocol, Mac48Address src, Mac48Address dst)
gjc@3444
   102
{
gjc@3444
   103
  NS_LOG_DEBUG ("LearningBridgeForward (incomingPort=" << incomingPort->GetName ()
gjc@3444
   104
                << ", packet=" << packet << ", protocol="<<protocol
gjc@3444
   105
                << ", src=" << src << ", dst=" << dst << ")");
gjc@3444
   106
gjc@3444
   107
  Learn (src, incomingPort);
gjc@3444
   108
  Ptr<NetDevice> outPort = GetLearnedState (dst);
gjc@3444
   109
  if (outPort != NULL && outPort != incomingPort)
gjc@3444
   110
    {
gjc@3444
   111
      NS_LOG_LOGIC ("Learning bridge state says to use port `" << outPort->GetName () << "'");
gjc@3444
   112
      outPort->SendFrom (packet->Copy (), src, dst, protocol);
gjc@3444
   113
    }
gjc@3444
   114
  else
gjc@3444
   115
    {
gjc@3444
   116
      NS_LOG_LOGIC ("No learned state: send through all ports");
gjc@3444
   117
      for (std::vector< Ptr<NetDevice> >::iterator iter = m_ports.begin ();
gjc@3444
   118
           iter != m_ports.end (); iter++)
gjc@3444
   119
        {
gjc@3444
   120
          Ptr<NetDevice> port = *iter;
gjc@3444
   121
          if (port != incomingPort)
gjc@3444
   122
            {
gjc@3444
   123
              NS_LOG_LOGIC ("LearningBridgeForward (" << src << " => " << dst << "): " << incomingPort->GetName ()
gjc@3444
   124
                            << " --> " << port->GetName ()
gjc@3444
   125
                            << " (UID " << packet->GetUid () << ").");
gjc@3444
   126
              port->SendFrom (packet->Copy (), src, dst, protocol);
gjc@3444
   127
            }
gjc@3444
   128
        }
gjc@3444
   129
    }
gjc@3444
   130
}
gjc@3444
   131
gjc@3444
   132
void
mathieu@3548
   133
BridgeNetDevice::ForwardBroadcast (Ptr<NetDevice> incomingPort, Ptr<const Packet> packet,
gjc@3439
   134
                                        uint16_t protocol, Mac48Address src, Mac48Address dst)
gjc@3439
   135
{
gjc@3439
   136
  NS_LOG_DEBUG ("LearningBridgeForward (incomingPort=" << incomingPort->GetName ()
gjc@3439
   137
                << ", packet=" << packet << ", protocol="<<protocol
gjc@3439
   138
                << ", src=" << src << ", dst=" << dst << ")");
gjc@3444
   139
  Learn (src, incomingPort);
gjc@3439
   140
gjc@3439
   141
  for (std::vector< Ptr<NetDevice> >::iterator iter = m_ports.begin ();
gjc@3439
   142
         iter != m_ports.end (); iter++)
gjc@3439
   143
    {
gjc@3439
   144
      Ptr<NetDevice> port = *iter;
gjc@3439
   145
      if (port != incomingPort)
gjc@3439
   146
        {
gjc@3443
   147
          NS_LOG_LOGIC ("LearningBridgeForward (" << src << " => " << dst << "): " << incomingPort->GetName ()
gjc@3443
   148
                        << " --> " << port->GetName ()
gjc@3443
   149
                        << " (UID " << packet->GetUid () << ").");
gjc@3443
   150
          port->SendFrom (packet->Copy (), src, dst, protocol);
gjc@3439
   151
        }
gjc@3439
   152
    }
gjc@3439
   153
}
gjc@3439
   154
gjc@3444
   155
void BridgeNetDevice::Learn (Mac48Address source, Ptr<NetDevice> port)
gjc@3444
   156
{
gjc@3444
   157
  if (m_enableLearning)
gjc@3444
   158
    {
gjc@3444
   159
      LearnedState &state = m_learnState[source];
gjc@3444
   160
      state.associatedPort = port;
gjc@3444
   161
      state.expirationTime = Simulator::Now () + m_expirationTime;
gjc@3444
   162
    }
gjc@3444
   163
}
gjc@3444
   164
gjc@3444
   165
Ptr<NetDevice> BridgeNetDevice::GetLearnedState (Mac48Address source)
gjc@3444
   166
{
gjc@3444
   167
  if (m_enableLearning)
gjc@3444
   168
    {
gjc@3460
   169
      Time now = Simulator::Now ();
gjc@3444
   170
      std::map<Mac48Address, LearnedState>::iterator iter =
gjc@3444
   171
        m_learnState.find (source);
gjc@3444
   172
      if (iter != m_learnState.end ())
gjc@3444
   173
        {
gjc@3444
   174
          LearnedState &state = iter->second;
gjc@3460
   175
          if (state.expirationTime > now)
gjc@3444
   176
            {
gjc@3444
   177
              return state.associatedPort;
gjc@3444
   178
            }
gjc@3444
   179
          else
gjc@3444
   180
            {
gjc@3444
   181
              m_learnState.erase (iter);
gjc@3444
   182
            }
gjc@3444
   183
        }
gjc@3444
   184
    }
gjc@3444
   185
  return NULL;
gjc@3444
   186
}
gjc@3439
   187
gjc@3439
   188
void 
gjc@3439
   189
BridgeNetDevice::AddBridgePort (Ptr<NetDevice> bridgePort)
gjc@3439
   190
{
gjc@3443
   191
  NS_ASSERT (bridgePort != this);
mathieu@3584
   192
  if (!Mac48Address::IsMatchingType (bridgePort->GetAddress ()))
mathieu@3584
   193
    {
mathieu@3584
   194
      NS_FATAL_ERROR ("Device does not support eui 48 addresses: cannot be added to bridge.");
mathieu@3584
   195
    }
mathieu@3584
   196
  if (!bridgePort->SupportsSendFrom ())
mathieu@3584
   197
    {
mathieu@3584
   198
      NS_FATAL_ERROR ("Device does not support SendFrom: cannot be added to bridge.");
mathieu@3584
   199
    }
gjc@3439
   200
  if (m_address == Mac48Address ())
gjc@3439
   201
    {
gjc@3439
   202
      m_address = Mac48Address::ConvertFrom (bridgePort->GetAddress ());
gjc@3439
   203
    }
gjc@3439
   204
gjc@3460
   205
  NS_LOG_DEBUG ("RegisterProtocolHandler for " << bridgePort->GetName ());
gjc@3448
   206
  m_node->RegisterProtocolHandler (MakeCallback (&BridgeNetDevice::ReceiveFromDevice, this),
gjc@3460
   207
                                   0, bridgePort, true);
gjc@3439
   208
  m_ports.push_back (bridgePort);
gjc@3449
   209
  m_channel->AddChannel (bridgePort->GetChannel ());
gjc@3439
   210
}
gjc@3439
   211
gjc@3439
   212
void 
gjc@3439
   213
BridgeNetDevice::SetName(const std::string name)
gjc@3439
   214
{
gjc@3439
   215
  m_name = name;
gjc@3439
   216
}
gjc@3439
   217
gjc@3439
   218
std::string 
gjc@3439
   219
BridgeNetDevice::GetName(void) const
gjc@3439
   220
{
gjc@3439
   221
  return m_name;
gjc@3439
   222
}
gjc@3439
   223
gjc@3439
   224
void 
gjc@3439
   225
BridgeNetDevice::SetIfIndex(const uint32_t index)
gjc@3439
   226
{
gjc@3439
   227
  m_ifIndex = index;
gjc@3439
   228
}
gjc@3439
   229
gjc@3439
   230
uint32_t 
gjc@3439
   231
BridgeNetDevice::GetIfIndex(void) const
gjc@3439
   232
{
gjc@3439
   233
  return m_ifIndex;
gjc@3439
   234
}
gjc@3439
   235
gjc@3439
   236
Ptr<Channel> 
gjc@3439
   237
BridgeNetDevice::GetChannel (void) const
gjc@3439
   238
{
gjc@3449
   239
  return m_channel;
gjc@3439
   240
}
gjc@3439
   241
gjc@3439
   242
Address 
gjc@3439
   243
BridgeNetDevice::GetAddress (void) const
gjc@3439
   244
{
gjc@3439
   245
  return m_address;
gjc@3439
   246
}
gjc@3439
   247
gjc@3439
   248
bool 
gjc@3439
   249
BridgeNetDevice::SetMtu (const uint16_t mtu)
gjc@3439
   250
{
gjc@3439
   251
  m_mtu = mtu;
gjc@3439
   252
  return true;
gjc@3439
   253
}
gjc@3439
   254
gjc@3439
   255
uint16_t 
gjc@3439
   256
BridgeNetDevice::GetMtu (void) const
gjc@3439
   257
{
gjc@3439
   258
  return m_mtu;
gjc@3439
   259
}
gjc@3439
   260
gjc@3439
   261
gjc@3439
   262
bool 
gjc@3439
   263
BridgeNetDevice::IsLinkUp (void) const
gjc@3439
   264
{
gjc@3439
   265
  return true;
gjc@3439
   266
}
gjc@3439
   267
gjc@3439
   268
gjc@3439
   269
void 
gjc@3439
   270
BridgeNetDevice::SetLinkChangeCallback (Callback<void> callback)
gjc@3439
   271
{}
gjc@3439
   272
gjc@3439
   273
gjc@3439
   274
bool 
gjc@3439
   275
BridgeNetDevice::IsBroadcast (void) const
gjc@3439
   276
{
gjc@3439
   277
  return true;
gjc@3439
   278
}
gjc@3439
   279
gjc@3439
   280
gjc@3439
   281
Address
gjc@3439
   282
BridgeNetDevice::GetBroadcast (void) const
gjc@3439
   283
{
gjc@3439
   284
  return Mac48Address ("ff:ff:ff:ff:ff:ff");
gjc@3439
   285
}
gjc@3439
   286
gjc@3439
   287
bool
gjc@3439
   288
BridgeNetDevice::IsMulticast (void) const
gjc@3439
   289
{
gjc@3439
   290
  return true;
gjc@3439
   291
}
gjc@3439
   292
gjc@3439
   293
Address
craigdo@3841
   294
BridgeNetDevice::GetMulticast (Ipv4Address multicastGroup) const
gjc@3439
   295
{
gjc@3439
   296
 NS_LOG_FUNCTION (this << multicastGroup);
mathieu@3585
   297
 Mac48Address multicast = Mac48Address::GetMulticast (multicastGroup);
mathieu@3585
   298
 return multicast;
gjc@3439
   299
}
gjc@3439
   300
gjc@3439
   301
gjc@3439
   302
bool 
gjc@3439
   303
BridgeNetDevice::IsPointToPoint (void) const
gjc@3439
   304
{
gjc@3439
   305
  return false;
gjc@3439
   306
}
gjc@3439
   307
gjc@3439
   308
gjc@3439
   309
bool 
gjc@3443
   310
BridgeNetDevice::Send (Ptr<Packet> packet, const Address& dest, uint16_t protocolNumber)
gjc@3439
   311
{
gjc@3439
   312
  for (std::vector< Ptr<NetDevice> >::iterator iter = m_ports.begin ();
gjc@3439
   313
         iter != m_ports.end (); iter++)
gjc@3439
   314
    {
gjc@3439
   315
      Ptr<NetDevice> port = *iter;
gjc@3443
   316
      port->SendFrom (packet, m_address, dest, protocolNumber);
gjc@3443
   317
    }
gjc@3443
   318
gjc@3443
   319
  return true;
gjc@3443
   320
}
gjc@3443
   321
gjc@3443
   322
bool 
gjc@3443
   323
BridgeNetDevice::SendFrom (Ptr<Packet> packet, const Address& src, const Address& dest, uint16_t protocolNumber)
gjc@3443
   324
{
gjc@3443
   325
  for (std::vector< Ptr<NetDevice> >::iterator iter = m_ports.begin ();
gjc@3443
   326
         iter != m_ports.end (); iter++)
gjc@3443
   327
    {
gjc@3443
   328
      Ptr<NetDevice> port = *iter;
gjc@3443
   329
      port->SendFrom (packet, src, dest, protocolNumber);
gjc@3439
   330
    }
gjc@3439
   331
gjc@3439
   332
  return true;
gjc@3439
   333
}
gjc@3439
   334
gjc@3439
   335
gjc@3439
   336
Ptr<Node> 
gjc@3439
   337
BridgeNetDevice::GetNode (void) const
gjc@3439
   338
{
gjc@3439
   339
  return m_node;
gjc@3439
   340
}
gjc@3439
   341
gjc@3439
   342
gjc@3439
   343
void 
gjc@3439
   344
BridgeNetDevice::SetNode (Ptr<Node> node)
gjc@3439
   345
{
gjc@3439
   346
  m_node = node;
gjc@3439
   347
}
gjc@3439
   348
gjc@3439
   349
gjc@3439
   350
bool 
gjc@3439
   351
BridgeNetDevice::NeedsArp (void) const
gjc@3439
   352
{
gjc@3439
   353
  return true;
gjc@3439
   354
}
gjc@3439
   355
gjc@3439
   356
gjc@3439
   357
void 
gjc@3439
   358
BridgeNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
gjc@3439
   359
{
gjc@3439
   360
  m_rxCallback = cb;
gjc@3439
   361
}
gjc@3439
   362
gjc@3460
   363
void 
gjc@3460
   364
BridgeNetDevice::SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb)
gjc@3460
   365
{
gjc@3460
   366
  m_promiscRxCallback = cb;
gjc@3460
   367
}
gjc@3460
   368
gjc@3460
   369
bool
mathieu@3584
   370
BridgeNetDevice::SupportsSendFrom () const
gjc@3460
   371
{
gjc@3460
   372
  return true;
gjc@3460
   373
}
gjc@3460
   374
gjc@3439
   375
gjc@3439
   376
void
gjc@3439
   377
BridgeNetDevice::DoDispose (void)
gjc@3439
   378
{
gjc@3439
   379
  m_node = 0;
gjc@3439
   380
  NetDevice::DoDispose ();
gjc@3439
   381
}
gjc@3439
   382
vincent@3852
   383
Address BridgeNetDevice::GetMulticast (Ipv6Address addr) const
vincent@3852
   384
{
vincent@3852
   385
  NS_LOG_FUNCTION (this << addr);
vincent@3852
   386
  return Mac48Address::GetMulticast (addr);
vincent@3852
   387
}
gjc@3439
   388
gjc@3439
   389
} // namespace ns3