src/devices/csma/csma-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 3861 dacfd1f07538
permissions -rw-r--r--
Initial IPv6 capability
emmanuelle@977
     1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
emmanuelle@977
     2
/*
emmanuelle@977
     3
 * Copyright (c) 2007 Emmanuelle Laprise
emmanuelle@977
     4
 *
emmanuelle@977
     5
 * This program is free software; you can redistribute it and/or modify
emmanuelle@977
     6
 * it under the terms of the GNU General Public License version 2 as
emmanuelle@977
     7
 * published by the Free Software Foundation;
emmanuelle@977
     8
 *
emmanuelle@977
     9
 * This program is distributed in the hope that it will be useful,
emmanuelle@977
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
emmanuelle@977
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
emmanuelle@977
    12
 * GNU General Public License for more details.
emmanuelle@977
    13
 *
emmanuelle@977
    14
 * You should have received a copy of the GNU General Public License
emmanuelle@977
    15
 * along with this program; if not, write to the Free Software
emmanuelle@977
    16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
emmanuelle@977
    17
 *
emmanuelle@977
    18
 * Author: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
emmanuelle@977
    19
 */
emmanuelle@977
    20
craigdo@1504
    21
#include "ns3/log.h"
emmanuelle@977
    22
#include "ns3/queue.h"
emmanuelle@977
    23
#include "ns3/simulator.h"
emmanuelle@977
    24
#include "ns3/ethernet-header.h"
emmanuelle@977
    25
#include "ns3/ethernet-trailer.h"
emmanuelle@977
    26
#include "ns3/llc-snap-header.h"
tomh@1820
    27
#include "ns3/error-model.h"
mathieu@2500
    28
#include "ns3/enum.h"
mathieu@2500
    29
#include "ns3/boolean.h"
craigdo@3476
    30
#include "ns3/uinteger.h"
mathieu@2927
    31
#include "ns3/pointer.h"
mathieu@2500
    32
#include "ns3/trace-source-accessor.h"
mathieu@2500
    33
#include "csma-net-device.h"
mathieu@2500
    34
#include "csma-channel.h"
mathieu@2500
    35
craigdo@1504
    36
NS_LOG_COMPONENT_DEFINE ("CsmaNetDevice");
emmanuelle@977
    37
emmanuelle@977
    38
namespace ns3 {
emmanuelle@977
    39
mathieu@2501
    40
NS_OBJECT_ENSURE_REGISTERED (CsmaNetDevice);
mathieu@2501
    41
craigdo@3504
    42
  TypeId 
mathieu@2500
    43
CsmaNetDevice::GetTypeId (void)
craigdo@1504
    44
{
mathieu@2602
    45
  static TypeId tid = TypeId ("ns3::CsmaNetDevice")
mathieu@2500
    46
    .SetParent<NetDevice> ()
mathieu@2500
    47
    .AddConstructor<CsmaNetDevice> ()
craigdo@3257
    48
    .AddAttribute ("Address", 
craigdo@3504
    49
                   "The MAC address of this device.",
craigdo@3504
    50
                   Mac48AddressValue (Mac48Address ("ff:ff:ff:ff:ff:ff")),
craigdo@3504
    51
                   MakeMac48AddressAccessor (&CsmaNetDevice::m_address),
craigdo@3504
    52
                   MakeMac48AddressChecker ())
craigdo@3632
    53
    .AddAttribute ("FrameSize", 
craigdo@3629
    54
                   "The maximum size of a packet sent over this device.",
craigdo@3629
    55
                   UintegerValue (DEFAULT_FRAME_SIZE),
craigdo@3629
    56
                   MakeUintegerAccessor (&CsmaNetDevice::SetFrameSize,
craigdo@3629
    57
                                         &CsmaNetDevice::GetFrameSize),
craigdo@3504
    58
                   MakeUintegerChecker<uint16_t> ())
craigdo@3257
    59
    .AddAttribute ("EncapsulationMode", 
craigdo@3504
    60
                   "The link-layer encapsulation type to use.",
craigdo@3633
    61
                   EnumValue (DIX),
craigdo@3506
    62
                   MakeEnumAccessor (&CsmaNetDevice::SetEncapsulationMode),
craigdo@3629
    63
                   MakeEnumChecker (DIX, "Dix",
craigdo@3504
    64
                                    LLC, "Llc"))
craigdo@3257
    65
    .AddAttribute ("SendEnable", 
craigdo@3504
    66
                   "Enable or disable the transmitter section of the device.",
craigdo@3504
    67
                   BooleanValue (true),
craigdo@3504
    68
                   MakeBooleanAccessor (&CsmaNetDevice::m_sendEnable),
craigdo@3504
    69
                   MakeBooleanChecker ())
craigdo@3257
    70
    .AddAttribute ("ReceiveEnable",
craigdo@3504
    71
                   "Enable or disable the receiver section of the device.",
craigdo@3504
    72
                   BooleanValue (true),
craigdo@3504
    73
                   MakeBooleanAccessor (&CsmaNetDevice::m_receiveEnable),
craigdo@3504
    74
                   MakeBooleanChecker ())
craigdo@3257
    75
    .AddAttribute ("RxErrorModel", 
craigdo@3504
    76
                   "The receiver error model used to simulate packet loss",
craigdo@3504
    77
                   PointerValue (),
craigdo@3504
    78
                   MakePointerAccessor (&CsmaNetDevice::m_receiveErrorModel),
craigdo@3504
    79
                   MakePointerChecker<ErrorModel> ())
craigdo@3257
    80
    .AddAttribute ("TxQueue", 
craigdo@3504
    81
                   "A queue to use as the transmit queue in the device.",
craigdo@3504
    82
                   PointerValue (),
craigdo@3504
    83
                   MakePointerAccessor (&CsmaNetDevice::m_queue),
craigdo@3504
    84
                   MakePointerChecker<Queue> ())
craigdo@3257
    85
    .AddTraceSource ("Rx", 
craigdo@3504
    86
                     "The trace source to fire on reception of a MAC packet.",
craigdo@3504
    87
                     MakeTraceSourceAccessor (&CsmaNetDevice::m_rxTrace))
craigdo@3257
    88
    .AddTraceSource ("Drop", 
craigdo@3504
    89
                     "Trace source to fire on when a MAC packet is dropped.",
craigdo@3504
    90
                     MakeTraceSourceAccessor (&CsmaNetDevice::m_dropTrace))
mathieu@2500
    91
    ;
mathieu@2500
    92
  return tid;
craigdo@1504
    93
}
craigdo@1504
    94
mathieu@2500
    95
CsmaNetDevice::CsmaNetDevice ()
mathieu@2500
    96
  : m_name (""),
craigdo@3476
    97
    m_linkUp (false)
emmanuelle@977
    98
{
mathieu@2983
    99
  NS_LOG_FUNCTION (this);
mathieu@2500
   100
  m_txMachineState = READY;
craigdo@3257
   101
  m_tInterframeGap = Seconds (0);
mathieu@2500
   102
  m_channel = 0; 
craigdo@3506
   103
craigdo@3630
   104
  // 
craigdo@3630
   105
  // We would like to let the attribute system take care of initializing the packet encapsulation stuff, but we also don't want to
craigdo@3630
   106
  // get caught up in initialization order changes.  So we'll get the three problem variables into a consistent state here before the
craigdo@3630
   107
  // attribute calls, and then depend on the semantics of the setters to preserve a consistent state.  This really doesn't have to be
craigdo@3630
   108
  // the same set of values as the initial values set by the attributes, but it does have to be a consistent set.  That is, you can
craigdo@3630
   109
  // just change the ddfault encapsulation mode above without having to change it here.  We keep it the same for GP.
craigdo@3630
   110
  //
craigdo@3630
   111
  m_encapMode = DIX;
craigdo@3629
   112
  m_frameSize = DEFAULT_FRAME_SIZE;
craigdo@3629
   113
  m_mtu = MtuFromFrameSize (m_frameSize);
emmanuelle@977
   114
}
emmanuelle@977
   115
craigdo@1276
   116
CsmaNetDevice::~CsmaNetDevice()
emmanuelle@977
   117
{
mathieu@2983
   118
  NS_LOG_FUNCTION_NOARGS ();
emmanuelle@977
   119
  m_queue = 0;
emmanuelle@977
   120
}
emmanuelle@977
   121
craigdo@3257
   122
  void 
craigdo@1276
   123
CsmaNetDevice::DoDispose ()
emmanuelle@977
   124
{
mathieu@2983
   125
  NS_LOG_FUNCTION_NOARGS ();
emmanuelle@977
   126
  m_channel = 0;
mathieu@2470
   127
  m_node = 0;
emmanuelle@977
   128
  NetDevice::DoDispose ();
emmanuelle@977
   129
}
emmanuelle@977
   130
craigdo@3682
   131
  uint32_t
craigdo@3682
   132
CsmaNetDevice::MtuFromFrameSize (uint32_t frameSize)
craigdo@3506
   133
{
craigdo@3629
   134
  NS_LOG_FUNCTION (frameSize);
craigdo@3506
   135
craigdo@3682
   136
  NS_ASSERT_MSG (frameSize <= std::numeric_limits<uint16_t>::max (), 
craigdo@3682
   137
                 "CsmaNetDevice::MtuFromFrameSize(): Frame size should be derived from 16-bit quantity: " << frameSize);
craigdo@3682
   138
craigdo@3682
   139
  uint32_t newSize;
craigdo@3682
   140
craigdo@3506
   141
  switch (m_encapMode) 
craigdo@3506
   142
    {
craigdo@3629
   143
    case DIX:
craigdo@3682
   144
      newSize = frameSize - ETHERNET_OVERHEAD;
craigdo@3682
   145
      break;
craigdo@3506
   146
    case LLC: 
craigdo@3506
   147
      {
craigdo@3506
   148
        LlcSnapHeader llc;
craigdo@3506
   149
craigdo@3630
   150
        NS_ASSERT_MSG ((uint32_t)(frameSize - ETHERNET_OVERHEAD) >= llc.GetSerializedSize (), 
craigdo@3630
   151
                       "CsmaNetDevice::MtuFromFrameSize(): Given frame size too small to support LLC mode");
craigdo@3682
   152
        newSize = frameSize - ETHERNET_OVERHEAD - llc.GetSerializedSize ();
craigdo@3506
   153
      }
craigdo@3682
   154
      break;
craigdo@3630
   155
    case ILLEGAL:
craigdo@3630
   156
    default:
craigdo@3630
   157
      NS_FATAL_ERROR ("CsmaNetDevice::MtuFromFrameSize(): Unknown packet encapsulation mode");
craigdo@3630
   158
      return 0;
craigdo@3506
   159
    }
craigdo@3682
   160
craigdo@3682
   161
  return newSize;
craigdo@3506
   162
}
craigdo@3506
   163
  
craigdo@3682
   164
  uint32_t
craigdo@3682
   165
CsmaNetDevice::FrameSizeFromMtu (uint32_t mtu)
craigdo@3506
   166
{
craigdo@3506
   167
  NS_LOG_FUNCTION (mtu);
craigdo@3506
   168
craigdo@3682
   169
  uint32_t newSize;
craigdo@3682
   170
craigdo@3506
   171
  switch (m_encapMode) 
craigdo@3506
   172
    {
craigdo@3629
   173
    case DIX:
craigdo@3682
   174
      newSize = mtu + ETHERNET_OVERHEAD;
craigdo@3682
   175
      break;
craigdo@3506
   176
    case LLC: 
craigdo@3506
   177
      {
craigdo@3506
   178
        LlcSnapHeader llc;
craigdo@3682
   179
        newSize = mtu + ETHERNET_OVERHEAD + llc.GetSerializedSize ();
craigdo@3506
   180
      }
craigdo@3682
   181
      break;
craigdo@3630
   182
    case ILLEGAL:
craigdo@3630
   183
    default:
craigdo@3630
   184
      NS_FATAL_ERROR ("CsmaNetDevice::FrameSizeFromMtu(): Unknown packet encapsulation mode");
craigdo@3630
   185
      return 0;
craigdo@3506
   186
    }
craigdo@3506
   187
craigdo@3682
   188
  return newSize;
craigdo@3506
   189
}
craigdo@3506
   190
craigdo@3506
   191
  void 
craigdo@3506
   192
CsmaNetDevice::SetEncapsulationMode (enum EncapsulationMode mode)
craigdo@3506
   193
{
craigdo@3506
   194
  NS_LOG_FUNCTION (mode);
craigdo@3506
   195
craigdo@3506
   196
  m_encapMode = mode;
craigdo@3629
   197
  m_mtu = MtuFromFrameSize (m_frameSize);
craigdo@3506
   198
craigdo@3506
   199
  NS_LOG_LOGIC ("m_encapMode = " << m_encapMode);
craigdo@3629
   200
  NS_LOG_LOGIC ("m_frameSize = " << m_frameSize);
craigdo@3506
   201
  NS_LOG_LOGIC ("m_mtu = " << m_mtu);
craigdo@3506
   202
}
craigdo@3506
   203
craigdo@3506
   204
  CsmaNetDevice::EncapsulationMode
craigdo@3506
   205
CsmaNetDevice::GetEncapsulationMode (void)
craigdo@3506
   206
{
craigdo@3506
   207
  NS_LOG_FUNCTION_NOARGS ();
craigdo@3506
   208
  return m_encapMode;
craigdo@3506
   209
}
craigdo@3506
   210
  
craigdo@3629
   211
  bool
craigdo@3629
   212
CsmaNetDevice::SetMtu (uint16_t mtu)
craigdo@3506
   213
{
craigdo@3506
   214
  NS_LOG_FUNCTION (mtu);
craigdo@3506
   215
craigdo@3682
   216
  uint32_t newFrameSize = FrameSizeFromMtu (mtu);
craigdo@3682
   217
craigdo@3682
   218
  if (newFrameSize > std::numeric_limits<uint16_t>::max ())
craigdo@3682
   219
    {
craigdo@3682
   220
      NS_LOG_WARN ("CsmaNetDevice::SetMtu(): Frame size overflow, MTU not set.");
craigdo@3682
   221
      return false;
craigdo@3682
   222
    }
craigdo@3682
   223
craigdo@3682
   224
  m_frameSize = newFrameSize;
craigdo@3506
   225
  m_mtu = mtu;
craigdo@3506
   226
craigdo@3506
   227
  NS_LOG_LOGIC ("m_encapMode = " << m_encapMode);
craigdo@3629
   228
  NS_LOG_LOGIC ("m_frameSize = " << m_frameSize);
craigdo@3506
   229
  NS_LOG_LOGIC ("m_mtu = " << m_mtu);
craigdo@3629
   230
craigdo@3629
   231
  return true;
craigdo@3506
   232
}
craigdo@3506
   233
craigdo@3506
   234
  uint16_t
craigdo@3629
   235
CsmaNetDevice::GetMtu (void) const
craigdo@3506
   236
{
craigdo@3506
   237
  NS_LOG_FUNCTION_NOARGS ();
craigdo@3506
   238
  return m_mtu;
craigdo@3506
   239
}
craigdo@3506
   240
craigdo@3629
   241
  void 
craigdo@3629
   242
CsmaNetDevice::SetFrameSize (uint16_t frameSize)
craigdo@3506
   243
{
craigdo@3629
   244
  NS_LOG_FUNCTION (frameSize);
craigdo@3506
   245
craigdo@3629
   246
  m_frameSize = frameSize;
craigdo@3629
   247
  m_mtu = MtuFromFrameSize (frameSize);
craigdo@3506
   248
craigdo@3506
   249
  NS_LOG_LOGIC ("m_encapMode = " << m_encapMode);
craigdo@3629
   250
  NS_LOG_LOGIC ("m_frameSize = " << m_frameSize);
craigdo@3506
   251
  NS_LOG_LOGIC ("m_mtu = " << m_mtu);
craigdo@3506
   252
}
craigdo@3506
   253
craigdo@3506
   254
  uint16_t
craigdo@3629
   255
CsmaNetDevice::GetFrameSize (void) const
craigdo@3506
   256
{
craigdo@3629
   257
  return m_frameSize;
craigdo@3506
   258
}
craigdo@3506
   259
craigdo@3257
   260
  void 
mathieu@2655
   261
CsmaNetDevice::SetAddress (Mac48Address self)
mathieu@2655
   262
{
craigdo@3476
   263
  NS_LOG_FUNCTION (self);
mathieu@2655
   264
  m_address = self;
mathieu@2655
   265
}
mathieu@2655
   266
craigdo@3257
   267
  void
craigdo@1276
   268
CsmaNetDevice::SetSendEnable (bool sendEnable)
emmanuelle@977
   269
{
craigdo@3476
   270
  NS_LOG_FUNCTION (sendEnable);
emmanuelle@977
   271
  m_sendEnable = sendEnable;
emmanuelle@977
   272
}
emmanuelle@977
   273
craigdo@3257
   274
  void
craigdo@1276
   275
CsmaNetDevice::SetReceiveEnable (bool receiveEnable)
emmanuelle@977
   276
{
craigdo@3476
   277
  NS_LOG_FUNCTION (receiveEnable);
emmanuelle@977
   278
  m_receiveEnable = receiveEnable;
emmanuelle@977
   279
}
craigdo@1504
   280
craigdo@3257
   281
  bool
craigdo@1276
   282
CsmaNetDevice::IsSendEnabled (void)
emmanuelle@977
   283
{
mathieu@2983
   284
  NS_LOG_FUNCTION_NOARGS ();
craigdo@3504
   285
  return m_sendEnable;
emmanuelle@977
   286
}
emmanuelle@977
   287
craigdo@3257
   288
  bool
craigdo@1276
   289
CsmaNetDevice::IsReceiveEnabled (void)
emmanuelle@977
   290
{
mathieu@2983
   291
  NS_LOG_FUNCTION_NOARGS ();
craigdo@3504
   292
  return m_receiveEnable;
emmanuelle@977
   293
}
emmanuelle@977
   294
craigdo@3257
   295
  void 
craigdo@1276
   296
CsmaNetDevice::SetInterframeGap (Time t)
emmanuelle@977
   297
{
craigdo@3476
   298
  NS_LOG_FUNCTION (t);
emmanuelle@977
   299
  m_tInterframeGap = t;
emmanuelle@977
   300
}
emmanuelle@977
   301
craigdo@3257
   302
  void 
craigdo@3504
   303
CsmaNetDevice::SetBackoffParams (Time slotTime, uint32_t minSlots, uint32_t maxSlots, uint32_t ceiling, uint32_t maxRetries)
emmanuelle@977
   304
{
craigdo@3476
   305
  NS_LOG_FUNCTION (slotTime << minSlots << maxSlots << ceiling << maxRetries);
emmanuelle@977
   306
  m_backoff.m_slotTime = slotTime;
emmanuelle@977
   307
  m_backoff.m_minSlots = minSlots;
emmanuelle@977
   308
  m_backoff.m_maxSlots = maxSlots;
emmanuelle@977
   309
  m_backoff.m_ceiling = ceiling;
emmanuelle@977
   310
  m_backoff.m_maxRetries = maxRetries;
emmanuelle@977
   311
}
craigdo@1504
   312
craigdo@3257
   313
  void 
craigdo@3504
   314
CsmaNetDevice::AddHeader (Ptr<Packet> p,   Mac48Address source,  Mac48Address dest,  uint16_t protocolNumber)
emmanuelle@977
   315
{
craigdo@3476
   316
  NS_LOG_FUNCTION (p << source << dest << protocolNumber);
craigdo@3257
   317
mathieu@995
   318
  EthernetHeader header (false);
craigdo@3257
   319
  header.SetSource (source);
craigdo@3257
   320
  header.SetDestination (dest);
craigdo@3257
   321
mathieu@995
   322
  EthernetTrailer trailer;
mathieu@995
   323
craigdo@3476
   324
  NS_LOG_LOGIC ("p->GetSize () = " << p->GetSize ());
craigdo@3506
   325
  NS_LOG_LOGIC ("m_encapMode = " << m_encapMode);
craigdo@3476
   326
  NS_LOG_LOGIC ("m_mtu = " << m_mtu);
craigdo@3629
   327
  NS_LOG_LOGIC ("m_frameSize = " << m_frameSize);
craigdo@3476
   328
tomh@1001
   329
  uint16_t lengthType = 0;
mathieu@995
   330
  switch (m_encapMode) 
emmanuelle@977
   331
    {
craigdo@3629
   332
    case DIX:
craigdo@3630
   333
      NS_LOG_LOGIC ("Encapsulating packet as DIX (type interpretation)");
craigdo@3504
   334
      //
craigdo@3630
   335
      // This corresponds to the type interpretation of the lengthType field as in the old Ethernet Blue Book.
craigdo@3504
   336
      //
mathieu@995
   337
      lengthType = protocolNumber;
mathieu@995
   338
      break;
craigdo@3476
   339
    case LLC: 
craigdo@3476
   340
      {
craigdo@3476
   341
        NS_LOG_LOGIC ("Encapsulating packet as LLC (length interpretation)");
craigdo@3476
   342
craigdo@3476
   343
        LlcSnapHeader llc;
craigdo@3476
   344
        llc.SetType (protocolNumber);
craigdo@3476
   345
        p->AddHeader (llc);
craigdo@3504
   346
        //
craigdo@3504
   347
        // This corresponds to the length interpretation of the lengthType field,
craigdo@3630
   348
        // but with an LLC/SNAP header added to the payload as in IEEE 802.2
craigdo@3504
   349
        //      
craigdo@3477
   350
        lengthType = p->GetSize ();
craigdo@3629
   351
        NS_ASSERT_MSG (lengthType <= m_frameSize - 18,
craigdo@3476
   352
          "CsmaNetDevice::AddHeader(): 802.3 Length/Type field with LLC/SNAP: "
craigdo@3629
   353
          "length interpretation must not exceed device frame size minus overhead");
craigdo@3476
   354
      }
craigdo@3476
   355
      break;
craigdo@3630
   356
    case ILLEGAL:
craigdo@3630
   357
    default:
craigdo@3630
   358
      NS_FATAL_ERROR ("CsmaNetDevice::AddHeader(): Unknown packet encapsulation mode");
mathieu@995
   359
      break;
emmanuelle@977
   360
    }
craigdo@3257
   361
craigdo@3476
   362
  NS_LOG_LOGIC ("header.SetLengthType (" << lengthType << ")");
mathieu@995
   363
  header.SetLengthType (lengthType);
craigdo@3257
   364
  p->AddHeader (header);
craigdo@3257
   365
craigdo@3257
   366
  trailer.CalcFcs (p);
craigdo@3257
   367
  p->AddTrailer (trailer);
emmanuelle@977
   368
}
craigdo@1504
   369
craigdo@3257
   370
  bool 
mathieu@1866
   371
CsmaNetDevice::ProcessHeader (Ptr<Packet> p, uint16_t & param)
emmanuelle@977
   372
{
craigdo@3476
   373
  NS_LOG_FUNCTION (p << param);
craigdo@3476
   374
mathieu@995
   375
  EthernetTrailer trailer;
mathieu@995
   376
      
craigdo@3257
   377
  p->RemoveTrailer (trailer);
craigdo@3257
   378
  trailer.CheckFcs (p);
emmanuelle@977
   379
craigdo@3257
   380
  EthernetHeader header (false);
craigdo@3257
   381
  p->RemoveHeader (header);
craigdo@3257
   382
craigdo@3257
   383
  if ((header.GetDestination () != GetBroadcast ()) &&
craigdo@3257
   384
      (header.GetDestination () != GetAddress ()))
emmanuelle@977
   385
    {
mathieu@995
   386
      return false;
mathieu@995
   387
    }
mathieu@995
   388
mathieu@995
   389
  switch (m_encapMode)
mathieu@995
   390
    {
craigdo@3629
   391
    case DIX:
craigdo@3257
   392
      param = header.GetLengthType ();
mathieu@995
   393
      break;
craigdo@3630
   394
    case LLC: 
craigdo@3630
   395
      {
craigdo@3630
   396
        LlcSnapHeader llc;
craigdo@3630
   397
        p->RemoveHeader (llc);
craigdo@3630
   398
        param = llc.GetType ();
craigdo@3630
   399
      } 
craigdo@3630
   400
      break;
craigdo@3630
   401
    case ILLEGAL:
craigdo@3630
   402
    default:
craigdo@3630
   403
      NS_FATAL_ERROR ("CsmaNetDevice::ProcessHeader(): Unknown packet encapsulation mode");
mathieu@995
   404
      break;
emmanuelle@977
   405
    }
mathieu@995
   406
  return true;
emmanuelle@977
   407
}
emmanuelle@977
   408
craigdo@3257
   409
  void
craigdo@1276
   410
CsmaNetDevice::TransmitStart ()
emmanuelle@977
   411
{
mathieu@2983
   412
  NS_LOG_FUNCTION_NOARGS ();
craigdo@3476
   413
mathieu@1866
   414
  NS_LOG_LOGIC ("m_currentPkt=" << m_currentPkt);
mathieu@1866
   415
  NS_LOG_LOGIC ("UID is " << m_currentPkt->GetUid ());
craigdo@3504
   416
  //
craigdo@3504
   417
  // This function is called to start the process of transmitting a packet.
craigdo@3504
   418
  // We need to tell the channel that we've started wiggling the wire and
craigdo@3504
   419
  // schedule an event that will be executed when it's time to tell the 
craigdo@3504
   420
  // channel that we're done wiggling the wire.
craigdo@3504
   421
  //
craigdo@3257
   422
  NS_ASSERT_MSG ((m_txMachineState == READY) || (m_txMachineState == BACKOFF), 
craigdo@3504
   423
                 "Must be READY to transmit. Tx state is: " << m_txMachineState);
emmanuelle@977
   424
craigdo@3504
   425
  //
craigdo@3504
   426
  // Only transmit if send side of net device is enabled
craigdo@3504
   427
  //
craigdo@3257
   428
  if (IsSendEnabled () == false)
craigdo@3257
   429
    {
craigdo@3257
   430
      return;
craigdo@3257
   431
    }
emmanuelle@977
   432
craigdo@3257
   433
  if (m_channel->GetState () != IDLE)
craigdo@3257
   434
    {
craigdo@3504
   435
      //
craigdo@3504
   436
      // The channel is busy -- backoff and rechedule TransmitStart ()
craigdo@3504
   437
      //
emmanuelle@977
   438
      m_txMachineState = BACKOFF;
craigdo@3257
   439
craigdo@3257
   440
      if (m_backoff.MaxRetriesReached ())
craigdo@3257
   441
        { 
craigdo@3504
   442
          //
craigdo@3504
   443
          // Too many retries, abort transmission of packet
craigdo@3504
   444
          //
craigdo@3257
   445
          TransmitAbort ();
mathieu@997
   446
        } 
mathieu@997
   447
      else 
mathieu@997
   448
        {
craigdo@3257
   449
          m_backoff.IncrNumRetries ();
craigdo@3257
   450
          Time backoffTime = m_backoff.GetBackoffTime ();
emmanuelle@977
   451
craigdo@3504
   452
          NS_LOG_LOGIC ("Channel busy, backing off for " << backoffTime.GetSeconds () << " sec");
emmanuelle@977
   453
craigdo@3504
   454
          Simulator::Schedule (backoffTime, &CsmaNetDevice::TransmitStart, this);
emmanuelle@977
   455
        }
mathieu@997
   456
    } 
mathieu@997
   457
  else 
mathieu@997
   458
    {
craigdo@3504
   459
      //
craigdo@3504
   460
      // The channel is free, transmit the packet
craigdo@3504
   461
      //
emmanuelle@977
   462
      m_txMachineState = BUSY;
craigdo@3257
   463
      Time tEvent = Seconds (m_bps.CalculateTxTime (m_currentPkt->GetSize ()));
emmanuelle@977
   464
      
craigdo@3504
   465
      NS_LOG_LOGIC ("Schedule TransmitCompleteEvent in " << tEvent.GetSeconds () << "sec");
emmanuelle@977
   466
      
craigdo@3504
   467
      Simulator::Schedule (tEvent, &CsmaNetDevice::TransmitCompleteEvent, this);
craigdo@3257
   468
craigdo@3257
   469
      if (m_channel->TransmitStart (m_currentPkt, m_deviceId) == false)
emmanuelle@977
   470
        {
craigdo@3504
   471
          NS_LOG_WARN ("Channel transmit start did not work at " << tEvent.GetSeconds () << "sec");
emmanuelle@977
   472
          m_txMachineState = READY;
mathieu@997
   473
        } 
mathieu@997
   474
      else 
mathieu@997
   475
        {
craigdo@3504
   476
          //
craigdo@3504
   477
          // Transmission succeeded, reset the backoff time parameters.
craigdo@3504
   478
          //
craigdo@3257
   479
          m_backoff.ResetBackoffTime ();
emmanuelle@977
   480
        }
emmanuelle@977
   481
    }
emmanuelle@977
   482
}
emmanuelle@977
   483
emmanuelle@977
   484
craigdo@3257
   485
  void
craigdo@1276
   486
CsmaNetDevice::TransmitAbort (void)
emmanuelle@977
   487
{
mathieu@2983
   488
  NS_LOG_FUNCTION_NOARGS ();
craigdo@3476
   489
mathieu@1866
   490
  NS_LOG_LOGIC ("Pkt UID is " << m_currentPkt->GetUid () << ")");
emmanuelle@977
   491
craigdo@3504
   492
  //
craigdo@3504
   493
  // Since we were transmitting a packet, that packet had better be on the transmit queue.
craigdo@3504
   494
  //
mathieu@1866
   495
  m_currentPkt = m_queue->Dequeue ();
craigdo@3504
   496
  NS_ASSERT_MSG (m_currentPkt != 0, "No Packet on queue during CsmaNetDevice::TransmitAbort()");
craigdo@3257
   497
craigdo@3504
   498
  //
craigdo@3504
   499
  // The last one failed.  Let's try to transmit the next one (if there)
craigdo@3504
   500
  //
craigdo@3257
   501
  m_backoff.ResetBackoffTime ();
emmanuelle@977
   502
  m_txMachineState = READY;
emmanuelle@977
   503
  TransmitStart ();
emmanuelle@977
   504
}
emmanuelle@977
   505
craigdo@3257
   506
  void
craigdo@1276
   507
CsmaNetDevice::TransmitCompleteEvent (void)
emmanuelle@977
   508
{
mathieu@2983
   509
  NS_LOG_FUNCTION_NOARGS ();
craigdo@3476
   510
craigdo@3504
   511
  //
craigdo@3504
   512
  // This function is called to finish the  process of transmitting a packet.
craigdo@3504
   513
  // We need to tell the channel that we've stopped wiggling the wire and
craigdo@3504
   514
  // schedule an event that will be executed when it's time to re-enable
craigdo@3504
   515
  // the transmitter after the interframe gap.
craigdo@3504
   516
  //
craigdo@3257
   517
  NS_ASSERT_MSG (m_txMachineState == BUSY, "Must be BUSY if transmitting");
craigdo@3257
   518
  NS_ASSERT (m_channel->GetState () == TRANSMITTING);
emmanuelle@977
   519
  m_txMachineState = GAP;
emmanuelle@977
   520
mathieu@1866
   521
  NS_LOG_LOGIC ("Pkt UID is " << m_currentPkt->GetUid () << ")");
emmanuelle@977
   522
  m_channel->TransmitEnd (); 
emmanuelle@977
   523
craigdo@3504
   524
  NS_LOG_LOGIC ("Schedule TransmitReadyEvent in " << m_tInterframeGap.GetSeconds () << "sec");
emmanuelle@977
   525
craigdo@3504
   526
  Simulator::Schedule (m_tInterframeGap, &CsmaNetDevice::TransmitReadyEvent, this);
emmanuelle@977
   527
}
emmanuelle@977
   528
craigdo@3257
   529
  void
craigdo@1276
   530
CsmaNetDevice::TransmitReadyEvent (void)
emmanuelle@977
   531
{
mathieu@2983
   532
  NS_LOG_FUNCTION_NOARGS ();
craigdo@3476
   533
craigdo@3504
   534
  //
craigdo@3504
   535
  // This function is called to enable the transmitter after the interframe
craigdo@3504
   536
  // gap has passed.  If there are pending transmissions, we use this opportunity
craigdo@3504
   537
  // to start the next transmit.
craigdo@3504
   538
  //
craigdo@3257
   539
  NS_ASSERT_MSG (m_txMachineState == GAP, "Must be in interframe gap");
emmanuelle@977
   540
  m_txMachineState = READY;
emmanuelle@977
   541
craigdo@3504
   542
  //
craigdo@3504
   543
  // Get the next packet from the queue for transmitting
craigdo@3504
   544
  //
craigdo@3257
   545
  if (m_queue->IsEmpty ())
mathieu@1308
   546
    {
mathieu@1308
   547
      return;
mathieu@1308
   548
    }
mathieu@1308
   549
  else
mathieu@1308
   550
    {
mathieu@1866
   551
      m_currentPkt = m_queue->Dequeue ();
craigdo@3504
   552
      NS_ASSERT_MSG (m_currentPkt != 0, "CsmaNetDevice::TransmitReadyEvent(): IsEmpty false but no Packet on queue?");
mathieu@1308
   553
      TransmitStart ();
mathieu@1308
   554
    }
emmanuelle@977
   555
}
emmanuelle@977
   556
craigdo@3476
   557
  bool
craigdo@1276
   558
CsmaNetDevice::Attach (Ptr<CsmaChannel> ch)
emmanuelle@977
   559
{
mathieu@2983
   560
  NS_LOG_FUNCTION (this << &ch);
emmanuelle@977
   561
emmanuelle@977
   562
  m_channel = ch;
emmanuelle@977
   563
craigdo@3257
   564
  m_deviceId = m_channel->Attach (this);
craigdo@3257
   565
craigdo@3504
   566
  //
craigdo@3504
   567
  // The channel provides us with the transmitter data rate.
craigdo@3504
   568
  //
emmanuelle@977
   569
  m_bps = m_channel->GetDataRate ();
emmanuelle@977
   570
craigdo@3504
   571
  //
craigdo@3504
   572
  // We use the Ethernet interframe gap of 96 bit times.
craigdo@3504
   573
  //
craigdo@3257
   574
  m_tInterframeGap = Seconds (m_bps.CalculateTxTime (96/8));
craigdo@3257
   575
craigdo@3504
   576
  //
craigdo@3504
   577
  // This device is up whenever a channel is attached to it.
craigdo@3504
   578
  //
emmanuelle@977
   579
  NotifyLinkUp ();
emmanuelle@977
   580
  return true;
emmanuelle@977
   581
}
emmanuelle@977
   582
craigdo@3257
   583
  void
craigdo@3011
   584
CsmaNetDevice::SetQueue (Ptr<Queue> q)
emmanuelle@977
   585
{
craigdo@3476
   586
  NS_LOG_FUNCTION (q);
emmanuelle@977
   587
  m_queue = q;
emmanuelle@977
   588
}
emmanuelle@977
   589
craigdo@3257
   590
  void
craigdo@3257
   591
CsmaNetDevice::SetReceiveErrorModel (Ptr<ErrorModel> em)
tomh@1820
   592
{
mathieu@2983
   593
  NS_LOG_FUNCTION (em);
tomh@1820
   594
  m_receiveErrorModel = em; 
tomh@1820
   595
}
tomh@1820
   596
craigdo@3504
   597
  void
gjc@3447
   598
CsmaNetDevice::Receive (Ptr<Packet> packet, Ptr<CsmaNetDevice> senderDevice)
emmanuelle@977
   599
{
craigdo@3476
   600
  NS_LOG_FUNCTION (packet << senderDevice);
craigdo@3257
   601
  NS_LOG_LOGIC ("UID is " << packet->GetUid ());
craigdo@1504
   602
vincent@3852
   603
  /* IPv6 support*/
vincent@3852
   604
  uint8_t mac[6];
vincent@3852
   605
  Mac48Address multicast6AllNodes("33:33:00:00:00:01");
vincent@3852
   606
  Mac48Address multicast6AllRouters("33:33:00:00:00:02");
vincent@3852
   607
  Mac48Address multicast6AllHosts("33:33:00:00:00:03");
vincent@3852
   608
  Mac48Address multicast6Node; /* multicast address addressed to our MAC address */
vincent@3852
   609
vincent@3852
   610
  /* generate IPv6 multicast ethernet destination that nodes will accept */
vincent@3852
   611
  GetAddress().CopyTo(mac);
vincent@3852
   612
  mac[0]=0x33;
vincent@3852
   613
  mac[1]=0x33;
vincent@3852
   614
  /* mac[2]=0xff; */
vincent@3852
   615
  multicast6Node.CopyFrom(mac);
vincent@3852
   616
craigdo@3504
   617
  //
craigdo@3504
   618
  // We never forward up packets that we sent. Real devices don't do this since
craigdo@3504
   619
  // their receivers are disabled during send, so we don't. Drop the packet
craigdo@3504
   620
  // silently (no tracing) since it would really never get here in a real device.
craigdo@3504
   621
  // 
gjc@3447
   622
  if (senderDevice == this)
gjc@3447
   623
    {
gjc@3447
   624
      return;
gjc@3447
   625
    }
gjc@3447
   626
craigdo@3504
   627
  // 
craigdo@3504
   628
  // Only receive if the send side of net device is enabled
craigdo@3504
   629
  //
craigdo@3257
   630
  if (IsReceiveEnabled () == false)
mathieu@1186
   631
    {
mathieu@1866
   632
      m_dropTrace (packet);
craigdo@1210
   633
      return;
mathieu@1186
   634
    }
emmanuelle@977
   635
craigdo@3504
   636
  //
craigdo@3504
   637
  // Trace sinks will expect complete packets, not packets without some of the
craigdo@3504
   638
  // headers.
craigdo@3504
   639
  //
craigdo@3326
   640
  Ptr<Packet> originalPacket = packet->Copy ();
craigdo@3326
   641
craigdo@3257
   642
  EthernetTrailer trailer;
craigdo@3257
   643
  packet->RemoveTrailer (trailer);
craigdo@3257
   644
  trailer.CheckFcs (packet);
craigdo@3257
   645
craigdo@3257
   646
  EthernetHeader header (false);
craigdo@3257
   647
  packet->RemoveHeader (header);
craigdo@3257
   648
craigdo@3257
   649
  NS_LOG_LOGIC ("Pkt source is " << header.GetSource ());
craigdo@1504
   650
  NS_LOG_LOGIC ("Pkt destination is " << header.GetDestination ());
craigdo@3257
   651
mathieu@1870
   652
  if (m_receiveErrorModel && m_receiveErrorModel->IsCorrupt (packet) )
tomh@1820
   653
    {
tomh@1820
   654
      NS_LOG_LOGIC ("Dropping pkt due to error model ");
tomh@1820
   655
      m_dropTrace (packet);
tomh@1820
   656
    }
tomh@1820
   657
  else
tomh@1820
   658
    {
craigdo@3504
   659
      //
craigdo@3504
   660
      // variable <protocol> must be initialized to avoid a compiler warning in the RAW case that breaks the optimized build.
craigdo@3504
   661
      //
tomh@1820
   662
      uint16_t protocol = 0;
mathieu@1186
   663
tomh@1820
   664
      switch (m_encapMode)
tomh@1820
   665
        {
craigdo@3629
   666
        case DIX:
craigdo@3257
   667
          protocol = header.GetLengthType ();
tomh@1820
   668
          break;
tomh@1820
   669
        case LLC: 
tomh@1820
   670
          {
tomh@1820
   671
            LlcSnapHeader llc;
mathieu@1870
   672
            packet->RemoveHeader (llc);
tomh@1820
   673
            protocol = llc.GetType ();
tomh@1820
   674
          } 
tomh@1820
   675
          break;
craigdo@3630
   676
        case ILLEGAL:
craigdo@3630
   677
        default:
craigdo@3630
   678
          NS_FATAL_ERROR ("CsmaNetDevice::Receive(): Unknown packet encapsulation mode");
tomh@1820
   679
          break;
tomh@1820
   680
        }
gjc@3438
   681
gjc@3448
   682
      PacketType packetType;
gjc@3448
   683
      
mathieu@3549
   684
      if (header.GetDestination ().IsBroadcast ())
gjc@3438
   685
        {
gjc@3448
   686
          packetType = PACKET_BROADCAST;
gjc@3448
   687
          m_rxTrace (originalPacket);
gjc@3438
   688
        }
vincent@3852
   689
      else if (header.GetDestination ().IsMulticast () ||
vincent@3852
   690
          header.GetDestination() == multicast6Node ||
vincent@3852
   691
          header.GetDestination() == multicast6AllNodes ||
vincent@3852
   692
          header.GetDestination() == multicast6AllRouters ||
vincent@3852
   693
          header.GetDestination() == multicast6AllHosts)
gjc@3448
   694
        {
gjc@3448
   695
          packetType = PACKET_MULTICAST;          
gjc@3448
   696
          m_rxTrace (originalPacket);
gjc@3448
   697
        }
mathieu@3549
   698
      else if (header.GetDestination () == m_address)
gjc@3448
   699
        {
gjc@3448
   700
          packetType = PACKET_HOST;
gjc@3448
   701
          m_rxTrace (originalPacket);
gjc@3448
   702
        }
gjc@3448
   703
      else
gjc@3448
   704
        {
gjc@3448
   705
          packetType = PACKET_OTHERHOST;
gjc@3448
   706
        }
gjc@3448
   707
      
gjc@3460
   708
      if (!m_promiscRxCallback.IsNull ())
gjc@3460
   709
        {
craigdo@3504
   710
          m_promiscRxCallback (this, packet, protocol, header.GetSource (), header.GetDestination (), packetType);
gjc@3460
   711
        }
gjc@3460
   712
gjc@3460
   713
      if (packetType != PACKET_OTHERHOST)
gjc@3460
   714
        {
gjc@3460
   715
          m_rxCallback (this, packet, protocol, header.GetSource ());
gjc@3460
   716
        }
emmanuelle@977
   717
    }
emmanuelle@977
   718
}
emmanuelle@977
   719
craigdo@3257
   720
  Ptr<Queue>
craigdo@3257
   721
CsmaNetDevice::GetQueue (void) const 
mathieu@2470
   722
{ 
mathieu@2983
   723
  NS_LOG_FUNCTION_NOARGS ();
mathieu@2470
   724
  return m_queue;
mathieu@2470
   725
}
mathieu@2470
   726
craigdo@3257
   727
  void
mathieu@2470
   728
CsmaNetDevice::NotifyLinkUp (void)
mathieu@2470
   729
{
craigdo@3476
   730
  NS_LOG_FUNCTION_NOARGS ();
craigdo@3476
   731
mathieu@2470
   732
  m_linkUp = true;
craigdo@3257
   733
  if (m_linkChangeCallback.IsNull () == false)
mathieu@2470
   734
    {
mathieu@2470
   735
      m_linkChangeCallback ();
mathieu@2470
   736
    }
mathieu@2470
   737
}
mathieu@2470
   738
craigdo@3257
   739
  void 
craigdo@3257
   740
CsmaNetDevice::SetName (const std::string name)
mathieu@2470
   741
{
craigdo@3476
   742
  NS_LOG_FUNCTION (name);
mathieu@2470
   743
  m_name = name;
mathieu@2470
   744
}
craigdo@3257
   745
craigdo@3257
   746
  std::string 
craigdo@3257
   747
CsmaNetDevice::GetName (void) const
mathieu@2470
   748
{
craigdo@3476
   749
  NS_LOG_FUNCTION_NOARGS ();
mathieu@2470
   750
  return m_name;
mathieu@2470
   751
}
craigdo@3257
   752
craigdo@3257
   753
  void 
craigdo@3257
   754
CsmaNetDevice::SetIfIndex (const uint32_t index)
mathieu@2470
   755
{
craigdo@3476
   756
  NS_LOG_FUNCTION (index);
mathieu@2470
   757
  m_ifIndex = index;
mathieu@2470
   758
}
craigdo@3257
   759
craigdo@3257
   760
  uint32_t 
craigdo@3257
   761
CsmaNetDevice::GetIfIndex (void) const
mathieu@2470
   762
{
craigdo@3476
   763
  NS_LOG_FUNCTION_NOARGS ();
mathieu@2470
   764
  return m_ifIndex;
mathieu@2470
   765
}
craigdo@3257
   766
craigdo@3257
   767
  Ptr<Channel> 
mathieu@2470
   768
CsmaNetDevice::GetChannel (void) const
mathieu@2470
   769
{
craigdo@3476
   770
  NS_LOG_FUNCTION_NOARGS ();
mathieu@2470
   771
  return m_channel;
mathieu@2470
   772
}
craigdo@3257
   773
craigdo@3257
   774
  Address 
mathieu@2470
   775
CsmaNetDevice::GetAddress (void) const
mathieu@2470
   776
{
craigdo@3476
   777
  NS_LOG_FUNCTION_NOARGS ();
mathieu@2470
   778
  return m_address;
mathieu@2470
   779
}
craigdo@3257
   780
craigdo@3257
   781
  bool 
mathieu@2470
   782
CsmaNetDevice::IsLinkUp (void) const
mathieu@2470
   783
{
craigdo@3476
   784
  NS_LOG_FUNCTION_NOARGS ();
mathieu@2470
   785
  return m_linkUp;
mathieu@2470
   786
}
craigdo@3257
   787
craigdo@3257
   788
  void 
mathieu@2470
   789
CsmaNetDevice::SetLinkChangeCallback (Callback<void> callback)
mathieu@2470
   790
{
craigdo@3476
   791
  NS_LOG_FUNCTION (&callback);
mathieu@2470
   792
  m_linkChangeCallback = callback;
mathieu@2470
   793
}
craigdo@3257
   794
craigdo@3257
   795
  bool 
mathieu@2470
   796
CsmaNetDevice::IsBroadcast (void) const
mathieu@2470
   797
{
craigdo@3476
   798
  NS_LOG_FUNCTION_NOARGS ();
mathieu@2470
   799
  return true;
mathieu@2470
   800
}
craigdo@3257
   801
craigdo@3257
   802
  Address
mathieu@2470
   803
CsmaNetDevice::GetBroadcast (void) const
mathieu@2470
   804
{
craigdo@3476
   805
  NS_LOG_FUNCTION_NOARGS ();
mathieu@2470
   806
  return Mac48Address ("ff:ff:ff:ff:ff:ff");
mathieu@2470
   807
}
craigdo@3257
   808
craigdo@3257
   809
  bool 
mathieu@2470
   810
CsmaNetDevice::IsMulticast (void) const
mathieu@2470
   811
{
craigdo@3476
   812
  NS_LOG_FUNCTION_NOARGS ();
tomh@2795
   813
  return true;
mathieu@2470
   814
}
craigdo@3257
   815
craigdo@3257
   816
  Address 
craigdo@3841
   817
CsmaNetDevice::GetMulticast (Ipv4Address multicastGroup) const
craigdo@1443
   818
{
craigdo@3476
   819
  NS_LOG_FUNCTION (multicastGroup);
craigdo@1443
   820
mathieu@3549
   821
  Mac48Address ad = Mac48Address::GetMulticast (multicastGroup);
craigdo@3504
   822
craigdo@3504
   823
  //
craigdo@3504
   824
  // Implicit conversion (operator Address ()) is defined for Mac48Address, so
craigdo@3504
   825
  // use it by just returning the EUI-48 address which is automagically converted
craigdo@3504
   826
  // to an Address.
craigdo@3504
   827
  //
mathieu@3549
   828
  NS_LOG_LOGIC ("multicast address is " << ad);
craigdo@1443
   829
mathieu@3549
   830
  return ad;
craigdo@1443
   831
}
craigdo@3257
   832
craigdo@3257
   833
  bool 
mathieu@2470
   834
CsmaNetDevice::IsPointToPoint (void) const
mathieu@2470
   835
{
craigdo@3476
   836
  NS_LOG_FUNCTION_NOARGS ();
mathieu@2470
   837
  return false;
mathieu@2470
   838
}
craigdo@3257
   839
craigdo@3504
   840
  bool
craigdo@3504
   841
CsmaNetDevice::Send (Ptr<Packet> packet,const Address& dest, uint16_t protocolNumber)
gjc@3442
   842
{
craigdo@3476
   843
  NS_LOG_FUNCTION (packet << dest << protocolNumber);
gjc@3442
   844
  return SendFrom (packet, m_address, dest, protocolNumber);
gjc@3442
   845
}
gjc@3442
   846
craigdo@3504
   847
  bool
craigdo@3504
   848
CsmaNetDevice::SendFrom (Ptr<Packet> packet, const Address& src, const Address& dest, uint16_t protocolNumber)
mathieu@2470
   849
{
craigdo@3476
   850
  NS_LOG_FUNCTION (packet << src << dest << protocolNumber);
mathieu@2470
   851
  NS_LOG_LOGIC ("p=" << packet);
mathieu@2470
   852
  NS_LOG_LOGIC ("UID is " << packet->GetUid () << ")");
craigdo@1443
   853
mathieu@2470
   854
  NS_ASSERT (IsLinkUp ());
mathieu@2470
   855
craigdo@3504
   856
  //
craigdo@3504
   857
  // Only transmit if send side of net device is enabled
craigdo@3504
   858
  //
craigdo@3257
   859
  if (IsSendEnabled () == false)
mathieu@2470
   860
    {
mathieu@2470
   861
      return false;
mathieu@2470
   862
    }
craigdo@3257
   863
craigdo@3257
   864
  Mac48Address destination = Mac48Address::ConvertFrom (dest);
gjc@3442
   865
  Mac48Address source = Mac48Address::ConvertFrom (src);
gjc@3442
   866
  AddHeader (packet, source, destination, protocolNumber);
craigdo@3257
   867
craigdo@3504
   868
  //
craigdo@3504
   869
  // Place the packet to be sent on the send queue
craigdo@3504
   870
  //
craigdo@3257
   871
  if (m_queue->Enqueue(packet) == false)
craigdo@3257
   872
    {
craigdo@3257
   873
      return false;
craigdo@3257
   874
    }
craigdo@3504
   875
craigdo@3504
   876
  //
craigdo@3504
   877
  // If the device is idle, we need to start a transmission. Otherwise,
craigdo@3504
   878
  // the transmission will be started when the current packet finished
craigdo@3504
   879
  // transmission (see TransmitCompleteEvent)
craigdo@3504
   880
  //
mathieu@2470
   881
  if (m_txMachineState == READY) 
mathieu@2470
   882
    {
craigdo@3504
   883
      //
craigdo@3504
   884
      // The next packet to be transmitted goes in m_currentPkt
craigdo@3504
   885
      //
mathieu@2470
   886
      m_currentPkt = m_queue->Dequeue ();
mathieu@2470
   887
      if (m_currentPkt != 0)
mathieu@2470
   888
        {
craigdo@3257
   889
          TransmitStart ();
mathieu@2470
   890
        }
mathieu@2470
   891
    }
mathieu@2470
   892
  return true;
mathieu@2470
   893
}
craigdo@3257
   894
craigdo@3257
   895
  Ptr<Node> 
mathieu@2470
   896
CsmaNetDevice::GetNode (void) const
mathieu@2470
   897
{
craigdo@3476
   898
  NS_LOG_FUNCTION_NOARGS ();
mathieu@2470
   899
  return m_node;
mathieu@2470
   900
}
craigdo@3257
   901
craigdo@3257
   902
  void 
mathieu@2600
   903
CsmaNetDevice::SetNode (Ptr<Node> node)
mathieu@2600
   904
{
craigdo@3476
   905
  NS_LOG_FUNCTION (node);
craigdo@3476
   906
mathieu@2600
   907
  m_node = node;
gjc@3436
   908
  int count = -1;
gjc@3436
   909
  if (m_name.size () == 0)
gjc@3436
   910
    {
gjc@3436
   911
      for (uint32_t i = 0; i < node->GetNDevices (); i++)
gjc@3436
   912
        {
gjc@3436
   913
          Ptr<NetDevice> dev = node->GetDevice (i);
gjc@3436
   914
          if (dynamic_cast<CsmaNetDevice*> (PeekPointer (dev)))
gjc@3436
   915
            {
gjc@3436
   916
              count++;
gjc@3436
   917
              if (dev == this)
gjc@3436
   918
                {
gjc@3436
   919
                  break;
gjc@3436
   920
                }
gjc@3436
   921
            }
gjc@3436
   922
        }
gjc@3436
   923
      std::ostringstream s;
gjc@3436
   924
      s << "eth" << count;
gjc@3436
   925
      m_name = s.str ();
gjc@3436
   926
    }
mathieu@2600
   927
}
craigdo@3257
   928
craigdo@3257
   929
  bool 
mathieu@2470
   930
CsmaNetDevice::NeedsArp (void) const
mathieu@2470
   931
{
craigdo@3476
   932
  NS_LOG_FUNCTION_NOARGS ();
craigdo@3630
   933
  return true;
mathieu@2470
   934
}
craigdo@3257
   935
craigdo@3257
   936
  void 
mathieu@2470
   937
CsmaNetDevice::SetReceiveCallback (NetDevice::ReceiveCallback cb)
mathieu@2470
   938
{
craigdo@3476
   939
  NS_LOG_FUNCTION (&cb);
mathieu@2470
   940
  m_rxCallback = cb;
emmanuelle@977
   941
}
emmanuelle@977
   942
vincent@3852
   943
Address CsmaNetDevice::GetMulticast (Ipv6Address addr) const
vincent@3852
   944
{
vincent@3852
   945
  Mac48Address ad = Mac48Address::GetMulticast (addr);
vincent@3852
   946
vincent@3852
   947
  NS_LOG_LOGIC("MAC IPv6 multicast address is " << ad);
vincent@3852
   948
  return ad;
vincent@3852
   949
}
vincent@3852
   950
craigdo@3504
   951
  void 
gjc@3460
   952
CsmaNetDevice::SetPromiscReceiveCallback (NetDevice::PromiscReceiveCallback cb)
gjc@3460
   953
{
craigdo@3476
   954
  NS_LOG_FUNCTION (&cb);
gjc@3460
   955
  m_promiscRxCallback = cb;
gjc@3460
   956
}
gjc@3460
   957
craigdo@3504
   958
  bool 
mathieu@3584
   959
CsmaNetDevice::SupportsSendFrom () const
gjc@3460
   960
{
craigdo@3476
   961
  NS_LOG_FUNCTION_NOARGS ();
gjc@3460
   962
  return true;
gjc@3460
   963
}
gjc@3460
   964
emmanuelle@977
   965
} // namespace ns3