View | Details | Raw Unified | Return to bug 844
Collapse All | Expand All

(-)a/src/common/packet-tag-list.h (-142 / +1 lines)
 Lines 1-142    Link Here 
1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
1
/home/quincy/code/ns3/common/packet-tag-list.h
2
/*
3
 * Copyright (c) 2006 INRIA
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License version 2 as
7
 * published by the Free Software Foundation;
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software
16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 *
18
 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19
 */
20
#ifndef PACKET_TAG_LIST_H
21
#define PACKET_TAG_LIST_H
22
23
#include <stdint.h>
24
#include <ostream>
25
#include "ns3/type-id.h"
26
27
namespace ns3 {
28
29
class Tag;
30
31
/**
32
 * \ingroup constants
33
 * \brief Tag maximum size
34
 * The maximum size (in bytes) of a Tag is stored
35
 * in this constant.
36
 */
37
#define PACKET_TAG_MAX_SIZE 20
38
39
class PacketTagList 
40
{
41
public:
42
  struct TagData {
43
    uint8_t data[PACKET_TAG_MAX_SIZE];
44
    struct TagData *next;
45
    TypeId tid;
46
    uint32_t count;
47
  };
48
49
  inline PacketTagList ();
50
  inline PacketTagList (PacketTagList const &o);
51
  inline PacketTagList &operator = (PacketTagList const &o);
52
  inline ~PacketTagList ();
53
54
  void Add (Tag const&tag) const;
55
  bool Remove (Tag &tag);
56
  bool Peek (Tag &tag) const;
57
  inline void RemoveAll (void);
58
59
  const struct PacketTagList::TagData *Head (void) const;
60
61
private:
62
63
  bool Remove (TypeId tid);
64
  struct PacketTagList::TagData *AllocData (void) const;
65
  void FreeData (struct TagData *data) const;
66
67
  static struct PacketTagList::TagData *g_free;
68
  static uint32_t g_nfree;
69
70
  struct TagData *m_next;
71
};
72
73
} // namespace ns3
74
75
/****************************************************
76
 *  Implementation of inline methods for performance
77
 ****************************************************/
78
79
namespace ns3 {
80
81
PacketTagList::PacketTagList ()
82
  : m_next ()
83
{}
84
85
PacketTagList::PacketTagList (PacketTagList const &o)
86
  : m_next (o.m_next)
87
{
88
  if (m_next != 0) 
89
    {
90
      m_next->count++;
91
    }
92
}
93
94
PacketTagList &
95
PacketTagList::operator = (PacketTagList const &o)
96
{
97
  // self assignment
98
  if (m_next == o.m_next) 
99
    {
100
      return *this;
101
    }
102
  RemoveAll ();
103
  m_next = o.m_next;
104
  if (m_next != 0) 
105
    {
106
      m_next->count++;
107
    }
108
  return *this;
109
}
110
111
PacketTagList::~PacketTagList ()
112
{
113
  RemoveAll ();
114
}
115
116
void
117
PacketTagList::RemoveAll (void)
118
{
119
  struct TagData *prev = 0;
120
  for (struct TagData *cur = m_next; cur != 0; cur = cur->next) 
121
    {
122
      cur->count--;
123
      if (cur->count > 0) 
124
        {
125
          break;
126
        }
127
      if (prev != 0) 
128
        {
129
          FreeData (prev);
130
        }
131
      prev = cur;
132
    }
133
  if (prev != 0) 
134
    {
135
      FreeData (prev);
136
    }
137
  m_next = 0;
138
}
139
140
} // namespace ns3
141
142
#endif /* PACKET_TAG_LIST_H */
(-)a/src/devices/wifi/mac-low.cc (-1258 / +1 lines)
 Lines 1-1258    Link Here 
1
/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
1
/home/quincy/code/ns3/devices/wifi/mac-low.cc
2
/*
3
 * Copyright (c) 2005,2006 INRIA
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License version 2 as 
7
 * published by the Free Software Foundation;
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software
16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 *
18
 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19
 */
20
21
#include "ns3/assert.h"
22
#include "ns3/packet.h"
23
#include "ns3/simulator.h"
24
#include "ns3/tag.h"
25
#include "ns3/log.h"
26
#include "ns3/node.h"
27
28
#include "mac-low.h"
29
#include "wifi-phy.h"
30
#include "wifi-mac-trailer.h"
31
32
NS_LOG_COMPONENT_DEFINE ("MacLow");
33
34
#undef NS_LOG_APPEND_CONTEXT
35
#define NS_LOG_APPEND_CONTEXT std::clog << "[mac=" << m_self << "] "
36
37
38
namespace ns3 {
39
40
class SnrTag : public Tag
41
{
42
public:
43
44
  static TypeId GetTypeId (void);
45
  virtual TypeId GetInstanceTypeId (void) const;
46
47
  virtual uint32_t GetSerializedSize (void) const;
48
  virtual void Serialize (TagBuffer i) const;
49
  virtual void Deserialize (TagBuffer i);
50
  virtual void Print (std::ostream &os) const;
51
52
  void Set (double snr);
53
  double Get (void) const;
54
private:
55
  double m_snr;
56
};
57
58
TypeId 
59
SnrTag::GetTypeId (void)
60
{
61
  static TypeId tid = TypeId ("ns3::SnrTag")
62
    .SetParent<Tag> ()
63
    .AddConstructor<SnrTag> ()
64
    .AddAttribute ("Snr", "The snr of the last packet received",
65
                   DoubleValue (0.0),
66
                   MakeDoubleAccessor (&SnrTag::Get),
67
                   MakeDoubleChecker<double> ())
68
    ;
69
  return tid;
70
}
71
TypeId 
72
SnrTag::GetInstanceTypeId (void) const
73
{
74
  return GetTypeId ();
75
}
76
77
uint32_t 
78
SnrTag::GetSerializedSize (void) const
79
{
80
  return sizeof (double);
81
}
82
void 
83
SnrTag::Serialize (TagBuffer i) const
84
{
85
  i.WriteDouble (m_snr);
86
}
87
void 
88
SnrTag::Deserialize (TagBuffer i)
89
{
90
  m_snr = i.ReadDouble ();
91
}
92
void 
93
SnrTag::Print (std::ostream &os) const
94
{
95
  os << "Snr=" << m_snr;
96
}
97
void 
98
SnrTag::Set (double snr)
99
{
100
  m_snr = snr;
101
}
102
double 
103
SnrTag::Get (void) const
104
{
105
  return m_snr;
106
}
107
108
109
MacLowTransmissionListener::MacLowTransmissionListener ()
110
{}
111
MacLowTransmissionListener::~MacLowTransmissionListener ()
112
{}
113
MacLowDcfListener::MacLowDcfListener ()
114
{}
115
MacLowDcfListener::~MacLowDcfListener ()
116
{}
117
118
MacLowTransmissionParameters::MacLowTransmissionParameters ()
119
  : m_nextSize (0),
120
    m_waitAck (ACK_NONE),
121
    m_sendRts (false),
122
    m_overrideDurationId (Seconds (0))
123
{}
124
void 
125
MacLowTransmissionParameters::EnableNextData (uint32_t size)
126
{
127
  m_nextSize = size;
128
}
129
void 
130
MacLowTransmissionParameters::DisableNextData (void)
131
{
132
  m_nextSize = 0;
133
}
134
void 
135
MacLowTransmissionParameters::EnableOverrideDurationId (Time durationId)
136
{
137
  m_overrideDurationId = durationId;
138
}
139
void 
140
MacLowTransmissionParameters::DisableOverrideDurationId (void)
141
{
142
  m_overrideDurationId = Seconds (0);
143
}
144
void 
145
MacLowTransmissionParameters::EnableSuperFastAck (void)
146
{
147
  m_waitAck = ACK_SUPER_FAST;
148
}
149
void 
150
MacLowTransmissionParameters::EnableFastAck (void)
151
{
152
  m_waitAck = ACK_FAST;
153
}
154
void 
155
MacLowTransmissionParameters::EnableAck (void)
156
{
157
  m_waitAck = ACK_NORMAL;
158
}
159
void 
160
MacLowTransmissionParameters::DisableAck (void)
161
{
162
  m_waitAck = ACK_NONE;
163
}
164
void 
165
MacLowTransmissionParameters::EnableRts (void)
166
{
167
  m_sendRts = true;
168
}
169
void 
170
MacLowTransmissionParameters::DisableRts (void)
171
{
172
  m_sendRts = false;
173
}
174
bool 
175
MacLowTransmissionParameters::MustWaitAck (void) const
176
{
177
  return (m_waitAck != ACK_NONE);
178
}
179
bool 
180
MacLowTransmissionParameters::MustWaitNormalAck (void) const
181
{
182
  return (m_waitAck == ACK_NORMAL);
183
}
184
bool 
185
MacLowTransmissionParameters::MustWaitFastAck (void) const
186
{
187
  return (m_waitAck == ACK_FAST);
188
}
189
bool 
190
MacLowTransmissionParameters::MustWaitSuperFastAck (void) const
191
{
192
  return (m_waitAck == ACK_SUPER_FAST);
193
}
194
bool 
195
MacLowTransmissionParameters::MustSendRts (void) const
196
{
197
  return m_sendRts;
198
}
199
bool 
200
MacLowTransmissionParameters::HasDurationId (void) const
201
{
202
  return (m_overrideDurationId != Seconds (0));
203
}
204
Time
205
MacLowTransmissionParameters::GetDurationId (void) const
206
{
207
  NS_ASSERT (m_overrideDurationId != Seconds (0));
208
  return m_overrideDurationId;
209
}
210
bool 
211
MacLowTransmissionParameters::HasNextPacket (void) const
212
{
213
  return (m_nextSize != 0);
214
}
215
uint32_t 
216
MacLowTransmissionParameters::GetNextPacketSize (void) const
217
{
218
  NS_ASSERT (HasNextPacket ());
219
  return m_nextSize;
220
}
221
222
std::ostream &operator << (std::ostream &os, const MacLowTransmissionParameters &params)
223
{
224
  os << "[" 
225
     << "send rts=" << params.m_sendRts << ", "
226
     << "next size=" << params.m_nextSize << ", "
227
     << "dur=" << params.m_overrideDurationId << ", "
228
     << "ack=";
229
  switch (params.m_waitAck) {
230
  case MacLowTransmissionParameters::ACK_NONE:
231
    os << "none";
232
    break;
233
  case MacLowTransmissionParameters::ACK_NORMAL:
234
    os << "normal";
235
    break;
236
  case MacLowTransmissionParameters::ACK_FAST:
237
    os << "fast";
238
    break;
239
  case MacLowTransmissionParameters::ACK_SUPER_FAST:
240
    os << "super-fast";
241
    break;
242
  }
243
  os << "]";
244
  return os;
245
}
246
247
248
/***************************************************************
249
 *         Listener for PHY events. Forwards to MacLow
250
 ***************************************************************/
251
252
253
class PhyMacLowListener : public ns3::WifiPhyListener {
254
public:
255
  PhyMacLowListener (ns3::MacLow *macLow)
256
    : m_macLow (macLow) {}
257
  virtual ~PhyMacLowListener () {}
258
  virtual void NotifyRxStart (Time duration) {}
259
  virtual void NotifyRxEndOk (void) {}
260
  virtual void NotifyRxEndError (void) {}
261
  virtual void NotifyTxStart (Time duration) {}
262
  virtual void NotifyMaybeCcaBusyStart (Time duration) {}
263
  virtual void NotifySwitchingStart (Time duration) { 
264
    m_macLow->NotifySwitchingStartNow (duration);
265
  }
266
private:
267
  ns3::MacLow *m_macLow;
268
};
269
270
271
MacLow::MacLow ()
272
  : m_normalAckTimeoutEvent (),
273
    m_fastAckTimeoutEvent (),
274
    m_superFastAckTimeoutEvent (),
275
    m_fastAckFailedTimeoutEvent (),
276
    m_ctsTimeoutEvent (),
277
    m_sendCtsEvent (),
278
    m_sendAckEvent (),
279
    m_sendDataEvent (),
280
    m_waitSifsEvent (),
281
    m_currentPacket (0),
282
    m_listener (0)
283
{
284
  NS_LOG_FUNCTION (this);
285
  m_lastNavDuration = Seconds (0);
286
  m_lastNavStart = Seconds (0);
287
}
288
289
MacLow::~MacLow ()
290
{
291
  NS_LOG_FUNCTION (this);
292
}
293
294
void 
295
MacLow::SetupPhyMacLowListener (Ptr<WifiPhy> phy)
296
{
297
  m_phyMacLowListener = new PhyMacLowListener (this); 
298
  phy->RegisterListener (m_phyMacLowListener);
299
}
300
301
302
void 
303
MacLow::DoDispose (void)
304
{
305
  NS_LOG_FUNCTION (this);
306
  m_normalAckTimeoutEvent.Cancel ();
307
  m_fastAckTimeoutEvent.Cancel ();
308
  m_superFastAckTimeoutEvent.Cancel ();
309
  m_fastAckFailedTimeoutEvent.Cancel ();
310
  m_ctsTimeoutEvent.Cancel ();
311
  m_sendCtsEvent.Cancel ();
312
  m_sendAckEvent.Cancel ();
313
  m_sendDataEvent.Cancel ();
314
  m_waitSifsEvent.Cancel ();
315
  m_phy = 0;
316
  m_stationManager = 0;
317
  delete m_phyMacLowListener;
318
  m_phyMacLowListener = 0;
319
}
320
321
void
322
MacLow::CancelAllEvents (void)
323
{
324
  NS_LOG_FUNCTION (this);
325
  bool oneRunning = false;
326
  if (m_normalAckTimeoutEvent.IsRunning ()) 
327
    {
328
      m_normalAckTimeoutEvent.Cancel ();
329
      oneRunning = true;
330
    }
331
  if (m_fastAckTimeoutEvent.IsRunning ()) 
332
    {
333
      m_fastAckTimeoutEvent.Cancel ();
334
      oneRunning = true;
335
    }
336
  if (m_superFastAckTimeoutEvent.IsRunning ()) 
337
    {
338
      m_superFastAckTimeoutEvent.Cancel ();
339
      oneRunning = true;
340
    }
341
  if (m_fastAckFailedTimeoutEvent.IsRunning ()) 
342
    {
343
      m_fastAckFailedTimeoutEvent.Cancel ();
344
      oneRunning = true;
345
    }
346
  if (m_ctsTimeoutEvent.IsRunning ()) 
347
    {
348
      m_ctsTimeoutEvent.Cancel ();
349
      oneRunning = true;
350
    }
351
  if (m_sendCtsEvent.IsRunning ()) 
352
    {
353
      m_sendCtsEvent.Cancel ();
354
      oneRunning = true;
355
    }
356
  if (m_sendAckEvent.IsRunning ()) 
357
    {
358
      m_sendAckEvent.Cancel ();
359
      oneRunning = true;
360
    }
361
  if (m_sendDataEvent.IsRunning ()) 
362
    {
363
      m_sendDataEvent.Cancel ();
364
      oneRunning = true;
365
    }
366
  if (m_waitSifsEvent.IsRunning ()) 
367
    {
368
      m_waitSifsEvent.Cancel ();
369
      oneRunning = true;
370
    }
371
  if (oneRunning && m_listener != 0) 
372
    {
373
      m_listener->Cancel ();
374
      m_listener = 0;
375
    }
376
}
377
378
void
379
MacLow::SetPhy (Ptr<WifiPhy> phy)
380
{
381
  m_phy = phy;
382
  m_phy->SetReceiveOkCallback (MakeCallback (&MacLow::ReceiveOk, this));
383
  m_phy->SetReceiveErrorCallback (MakeCallback (&MacLow::ReceiveError, this));
384
  SetupPhyMacLowListener(phy); 
385
}
386
void 
387
MacLow::SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> manager)
388
{
389
  m_stationManager = manager;
390
}
391
392
void 
393
MacLow::SetAddress (Mac48Address ad)
394
{
395
  m_self = ad;
396
}
397
void 
398
MacLow::SetAckTimeout (Time ackTimeout)
399
{
400
  m_ackTimeout = ackTimeout;
401
}
402
void 
403
MacLow::SetCtsTimeout (Time ctsTimeout)
404
{
405
  m_ctsTimeout = ctsTimeout;
406
}
407
void
408
MacLow::SetSifs (Time sifs)
409
{
410
  m_sifs = sifs;
411
}
412
void 
413
MacLow::SetSlotTime (Time slotTime)
414
{
415
  m_slotTime = slotTime;
416
}
417
void 
418
MacLow::SetPifs (Time pifs)
419
{
420
  m_pifs = pifs;
421
}
422
void
423
MacLow::SetBssid (Mac48Address bssid)
424
{
425
  m_bssid = bssid;
426
}
427
Mac48Address 
428
MacLow::GetAddress (void) const
429
{
430
  return m_self;
431
}
432
Time 
433
MacLow::GetAckTimeout (void) const
434
{
435
  return m_ackTimeout;
436
}
437
Time 
438
MacLow::GetCtsTimeout (void) const
439
{
440
  return m_ctsTimeout;
441
}
442
Time
443
MacLow::GetSifs (void) const
444
{
445
  return m_sifs;
446
}
447
Time 
448
MacLow::GetSlotTime (void) const
449
{
450
  return m_slotTime;
451
}
452
Time 
453
MacLow::GetPifs (void) const
454
{
455
  return m_pifs;
456
}
457
Mac48Address 
458
MacLow::GetBssid (void) const
459
{
460
  return m_bssid;
461
}
462
463
void 
464
MacLow::SetRxCallback (Callback<void,Ptr<Packet>,const WifiMacHeader *> callback)
465
{
466
  m_rxCallback = callback;
467
}
468
void 
469
MacLow::RegisterDcfListener (MacLowDcfListener *listener)
470
{
471
  m_dcfListeners.push_back (listener);
472
}
473
474
475
void 
476
MacLow::StartTransmission (Ptr<const Packet> packet, 
477
                           const WifiMacHeader* hdr, 
478
                           MacLowTransmissionParameters params,
479
                           MacLowTransmissionListener *listener)
480
{
481
  NS_LOG_FUNCTION (this << packet << hdr << params << listener);
482
  /* m_currentPacket is not NULL because someone started
483
   * a transmission and was interrupted before one of:
484
   *   - ctsTimeout
485
   *   - sendDataAfterCTS
486
   * expired. This means that one of these timers is still
487
   * running. They are all cancelled below anyway by the 
488
   * call to CancelAllEvents (because of at least one
489
   * of these two timer) which will trigger a call to the
490
   * previous listener's cancel method.
491
   *
492
   * This typically happens because the high-priority 
493
   * QapScheduler has taken access to the channel from
494
   * one of the Edca of the QAP.
495
   */
496
  m_currentPacket = packet->Copy ();
497
  m_currentHdr = *hdr;
498
  CancelAllEvents ();
499
  m_listener = listener;
500
  m_txParams = params;
501
502
  //NS_ASSERT (m_phy->IsStateIdle ());
503
504
  NS_LOG_DEBUG ("startTx size="<< GetSize (m_currentPacket, &m_currentHdr) << 
505
            ", to=" << m_currentHdr.GetAddr1()<<", listener="<<m_listener);
506
507
  if (m_txParams.MustSendRts ()) 
508
    {
509
      SendRtsForPacket ();
510
    } 
511
  else 
512
    {
513
      SendDataPacket ();
514
    }
515
516
  /* When this method completes, we have taken ownership of the medium. */
517
  NS_ASSERT (m_phy->IsStateTx ());  
518
}
519
520
void
521
MacLow::ReceiveError (Ptr<const Packet> packet, double rxSnr)
522
{
523
  NS_LOG_FUNCTION (this << packet << rxSnr);
524
  NS_LOG_DEBUG ("rx failed ");
525
  if (m_txParams.MustWaitFastAck ()) 
526
    {
527
      NS_ASSERT (m_fastAckFailedTimeoutEvent.IsExpired ());
528
      m_fastAckFailedTimeoutEvent = Simulator::Schedule (GetSifs (), 
529
                                                         &MacLow::FastAckFailedTimeout, this);
530
    }
531
  return;
532
}
533
534
void 
535
MacLow::NotifySwitchingStartNow (Time duration)
536
{
537
  NS_LOG_DEBUG ("switching channel. Cancelling MAC pending events"); 
538
  m_stationManager->Reset();
539
  CancelAllEvents(); 
540
  if (m_navCounterResetCtsMissed.IsRunning ())
541
    {
542
      m_navCounterResetCtsMissed.Cancel();
543
    }
544
  m_lastNavStart = Simulator::Now (); 
545
  m_lastNavDuration = Seconds (0);
546
  m_currentPacket = 0;
547
  m_listener = 0;
548
}
549
550
void 
551
MacLow::ReceiveOk (Ptr<Packet> packet, double rxSnr, WifiMode txMode, WifiPreamble preamble)
552
{
553
  NS_LOG_FUNCTION (this << packet << rxSnr << txMode << preamble);
554
  /* A packet is received from the PHY.
555
   * When we have handled this packet,
556
   * we handle any packet present in the
557
   * packet queue.
558
   */
559
  WifiMacHeader hdr;
560
  packet->RemoveHeader (hdr);
561
  
562
  bool isPrevNavZero = IsNavZero ();
563
  NS_LOG_DEBUG ("duration/id=" << hdr.GetDuration ());
564
  NotifyNav (hdr, txMode, preamble);
565
  if (hdr.IsRts ()) 
566
    {
567
      /* see section 9.2.5.7 802.11-1999
568
       * A STA that is addressed by an RTS frame shall transmit a CTS frame after a SIFS 
569
       * period if the NAV at the STA receiving the RTS frame indicates that the medium is 
570
       * idle. If the NAV at the STA receiving the RTS indicates the medium is not idle, 
571
       * that STA shall not respond to the RTS frame.
572
       */
573
      if (isPrevNavZero &&
574
          hdr.GetAddr1 () == m_self) 
575
        {
576
          NS_LOG_DEBUG ("rx RTS from=" << hdr.GetAddr2 () << ", schedule CTS");
577
          NS_ASSERT (m_sendCtsEvent.IsExpired ());
578
          WifiRemoteStation *station = GetStation (hdr.GetAddr2 ());
579
          station->ReportRxOk (rxSnr, txMode);
580
          m_sendCtsEvent = Simulator::Schedule (GetSifs (),
581
                                                &MacLow::SendCtsAfterRts, this,
582
                                                hdr.GetAddr2 (), 
583
                                                hdr.GetDuration (),
584
                                                txMode,
585
                                                rxSnr);
586
        } 
587
      else 
588
        {
589
          NS_LOG_DEBUG ("rx RTS from=" << hdr.GetAddr2 () << ", cannot schedule CTS");
590
        }
591
    } 
592
  else if (hdr.IsCts () &&
593
           hdr.GetAddr1 () == m_self &&
594
           m_ctsTimeoutEvent.IsRunning () &&
595
           m_currentPacket != 0) 
596
    {
597
      NS_LOG_DEBUG ("receive cts from="<<m_currentHdr.GetAddr1 ());
598
      SnrTag tag;
599
      packet->RemovePacketTag (tag);
600
      WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
601
      station->ReportRxOk (rxSnr, txMode);
602
      station->ReportRtsOk (rxSnr, txMode, tag.Get ());
603
      
604
      m_ctsTimeoutEvent.Cancel ();
605
      NotifyCtsTimeoutResetNow ();
606
      m_listener->GotCts (rxSnr, txMode);
607
      NS_ASSERT (m_sendDataEvent.IsExpired ());
608
      m_sendDataEvent = Simulator::Schedule (GetSifs (), 
609
                                             &MacLow::SendDataAfterCts, this, 
610
                                             hdr.GetAddr1 (),
611
                                             hdr.GetDuration (),
612
                                             txMode);
613
    } 
614
  else if (hdr.IsAck () &&
615
           hdr.GetAddr1 () == m_self &&
616
           (m_normalAckTimeoutEvent.IsRunning () || 
617
            m_fastAckTimeoutEvent.IsRunning () ||
618
            m_superFastAckTimeoutEvent.IsRunning ()) &&
619
           m_txParams.MustWaitAck ()) 
620
    {
621
      NS_LOG_DEBUG ("receive ack from="<<m_currentHdr.GetAddr1 ());
622
      SnrTag tag;
623
      packet->RemovePacketTag (tag);
624
      WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
625
      station->ReportRxOk (rxSnr, txMode);
626
      station->ReportDataOk (rxSnr, txMode, tag.Get ());
627
      bool gotAck = false;
628
      if (m_txParams.MustWaitNormalAck () &&
629
          m_normalAckTimeoutEvent.IsRunning ()) 
630
        {
631
          m_normalAckTimeoutEvent.Cancel ();
632
          NotifyAckTimeoutResetNow ();
633
          gotAck = true;
634
        }
635
      if (m_txParams.MustWaitFastAck () &&
636
          m_fastAckTimeoutEvent.IsRunning ()) 
637
        {
638
          m_fastAckTimeoutEvent.Cancel ();
639
          NotifyAckTimeoutResetNow ();
640
          gotAck = true;
641
        }
642
      if (gotAck) 
643
        {
644
          m_listener->GotAck (rxSnr, txMode);
645
        }
646
      if (m_txParams.HasNextPacket ()) 
647
        {
648
          m_waitSifsEvent = Simulator::Schedule (GetSifs (), 
649
                                                 &MacLow::WaitSifsAfterEndTx, this);
650
        }
651
    } 
652
  else if (hdr.IsCtl ()) 
653
    {
654
      NS_LOG_DEBUG ("rx drop " << hdr.GetTypeString ());
655
    } 
656
  else if (hdr.GetAddr1 () == m_self) 
657
    {
658
      WifiRemoteStation *station = GetStation (hdr.GetAddr2 ());
659
      station->ReportRxOk (rxSnr, txMode);
660
      
661
      if (hdr.IsQosData () && hdr.IsQosNoAck ()) 
662
        {
663
          NS_LOG_DEBUG ("rx unicast/noAck from="<<hdr.GetAddr2 ());
664
        } 
665
      else if (hdr.IsData () || hdr.IsMgt ()) 
666
        {
667
          NS_LOG_DEBUG ("rx unicast/sendAck from=" << hdr.GetAddr2 ());
668
          NS_ASSERT (m_sendAckEvent.IsExpired ());
669
          m_sendAckEvent = Simulator::Schedule (GetSifs (),
670
                                                &MacLow::SendAckAfterData, this,
671
                                                hdr.GetAddr2 (), 
672
                                                hdr.GetDuration (),
673
                                                txMode,
674
                                                rxSnr);
675
        }
676
      goto rxPacket;
677
    } 
678
  else if (hdr.GetAddr1 ().IsGroup ())
679
    {
680
      if (hdr.IsData () || hdr.IsMgt ())
681
        {
682
          NS_LOG_DEBUG ("rx group from=" << hdr.GetAddr2 ());
683
          goto rxPacket;
684
        }
685
      else
686
        {
687
          // DROP
688
        }
689
    }
690
  else 
691
    {
692
      //NS_LOG_DEBUG_VERBOSE ("rx not-for-me from %d", GetSource (packet));
693
    }
694
  return;
695
 rxPacket:
696
  WifiMacTrailer fcs;
697
  packet->RemoveTrailer (fcs);
698
  m_rxCallback (packet, &hdr);
699
  return;
700
}
701
702
uint32_t 
703
MacLow::GetAckSize (void) const
704
{
705
  WifiMacHeader ack;
706
  ack.SetType (WIFI_MAC_CTL_ACK);
707
  return ack.GetSize () + 4;
708
}
709
uint32_t 
710
MacLow::GetRtsSize (void) const
711
{
712
  WifiMacHeader rts;
713
  rts.SetType (WIFI_MAC_CTL_RTS);
714
  return rts.GetSize () + 4;
715
}
716
Time
717
MacLow::GetAckDuration (Mac48Address to, WifiMode dataTxMode) const
718
{
719
  WifiMode ackMode = GetAckTxModeForData (to, dataTxMode);
720
  return m_phy->CalculateTxDuration (GetAckSize (), ackMode, WIFI_PREAMBLE_LONG);
721
}
722
Time
723
MacLow::GetCtsDuration (Mac48Address to, WifiMode rtsTxMode) const
724
{
725
  WifiMode ctsMode = GetCtsTxModeForRts (to, rtsTxMode);
726
  return m_phy->CalculateTxDuration (GetCtsSize (), ctsMode, WIFI_PREAMBLE_LONG);
727
}
728
uint32_t 
729
MacLow::GetCtsSize (void) const
730
{
731
  WifiMacHeader cts;
732
  cts.SetType (WIFI_MAC_CTL_CTS);
733
  return cts.GetSize () + 4;
734
}
735
uint32_t 
736
MacLow::GetSize (Ptr<const Packet> packet, const WifiMacHeader *hdr) const
737
{
738
  WifiMacTrailer fcs;
739
  return packet->GetSize () + hdr->GetSize () + fcs.GetSerializedSize ();
740
}
741
742
WifiMode
743
MacLow::GetRtsTxMode (Ptr<const Packet> packet, const WifiMacHeader *hdr) const
744
{
745
  Mac48Address to = hdr->GetAddr1 ();
746
  return GetStation (to)->GetRtsMode (packet);
747
}
748
WifiMode
749
MacLow::GetDataTxMode (Ptr<const Packet> packet, const WifiMacHeader *hdr) const
750
{
751
  Mac48Address to = hdr->GetAddr1 ();
752
  WifiMacTrailer fcs;
753
  uint32_t size =  packet->GetSize () + hdr->GetSize () + fcs.GetSerializedSize ();
754
  return GetStation (to)->GetDataMode (packet, size);
755
}
756
757
WifiMode
758
MacLow::GetCtsTxModeForRts (Mac48Address to, WifiMode rtsTxMode) const
759
{
760
  return GetStation (to)->GetCtsMode (rtsTxMode);
761
}
762
WifiMode
763
MacLow::GetAckTxModeForData (Mac48Address to, WifiMode dataTxMode) const
764
{
765
  return GetStation (to)->GetAckMode (dataTxMode);
766
}
767
768
769
Time
770
MacLow::CalculateOverallTxTime (Ptr<const Packet> packet,
771
                                const WifiMacHeader* hdr, 
772
                                const MacLowTransmissionParameters& params) const
773
{
774
  Time txTime = Seconds (0);
775
  WifiMode rtsMode = GetRtsTxMode (packet, hdr);
776
  WifiMode dataMode = GetDataTxMode (packet, hdr);
777
  if (params.MustSendRts ()) 
778
    {
779
      txTime += m_phy->CalculateTxDuration (GetRtsSize (), rtsMode, WIFI_PREAMBLE_LONG);
780
      txTime += GetCtsDuration (hdr->GetAddr1 (), rtsMode);
781
      txTime += GetSifs () * Scalar (2);
782
    }
783
  uint32_t dataSize = GetSize (packet, hdr);
784
  txTime += m_phy->CalculateTxDuration (dataSize, dataMode, WIFI_PREAMBLE_LONG);
785
  if (params.MustWaitAck ())
786
    {
787
      txTime += GetSifs ();
788
      txTime += GetAckDuration (hdr->GetAddr1 (), dataMode);
789
    }
790
  return txTime;
791
}
792
793
Time
794
MacLow::CalculateTransmissionTime (Ptr<const Packet> packet,
795
                                   const WifiMacHeader* hdr, 
796
                                   const MacLowTransmissionParameters& params) const
797
{
798
  Time txTime = CalculateOverallTxTime (packet, hdr, params);
799
  if (params.HasNextPacket ()) 
800
    {
801
      WifiMode dataMode = GetDataTxMode (packet, hdr);
802
      txTime += GetSifs ();
803
      txTime += m_phy->CalculateTxDuration (params.GetNextPacketSize (), dataMode, WIFI_PREAMBLE_LONG);
804
    }
805
  return txTime;
806
}
807
808
void
809
MacLow::NotifyNav (const WifiMacHeader &hdr, WifiMode txMode, WifiPreamble preamble)
810
{
811
  NS_ASSERT (m_lastNavStart <= Simulator::Now ());
812
  Time duration = hdr.GetDuration ();
813
814
  if (hdr.IsCfpoll () &&
815
      hdr.GetAddr2 () == m_bssid) 
816
    {
817
      // see section 9.3.2.2 802.11-1999
818
      DoNavResetNow (duration);
819
      return;
820
    }
821
  // XXX Note that we should also handle CF_END specially here
822
  // but we don't for now because we do not generate them.
823
  else if (hdr.GetAddr1 () != m_self)
824
    {
825
      // see section 9.2.5.4 802.11-1999
826
      bool navUpdated = DoNavStartNow (duration);
827
      if (hdr.IsRts () && navUpdated)
828
        {
829
          /**
830
           * A STA that used information from an RTS frame as the most recent basis to update its NAV setting 
831
           * is permitted to reset its NAV if no PHY-RXSTART.indication is detected from the PHY during a 
832
           * period with a duration of (2 * aSIFSTime) + (CTS_Time) + (2 * aSlotTime) starting at the 
833
           * PHY-RXEND.indication corresponding to the detection of the RTS frame. The “CTS_Time” shall 
834
           * be calculated using the length of the CTS frame and the data rate at which the RTS frame 
835
           * used for the most recent NAV update was received.
836
           */
837
          WifiMacHeader cts;
838
          cts.SetType (WIFI_MAC_CTL_CTS);
839
          Time navCounterResetCtsMissedDelay = 
840
            m_phy->CalculateTxDuration (cts.GetSerializedSize (), txMode, preamble) +
841
            Scalar (2) * GetSifs () + Scalar (2) * GetSlotTime ();
842
          m_navCounterResetCtsMissed = Simulator::Schedule (navCounterResetCtsMissedDelay,
843
                                                            &MacLow::NavCounterResetCtsMissed, this,
844
                                                            Simulator::Now ());
845
        }
846
    }
847
}
848
849
void
850
MacLow::NavCounterResetCtsMissed (Time rtsEndRxTime)
851
{
852
  if (m_phy->GetLastRxStartTime () > rtsEndRxTime)
853
    {
854
      DoNavResetNow (Seconds (0.0));
855
    }
856
}
857
858
void
859
MacLow::DoNavResetNow (Time duration)
860
{
861
  for (DcfListenersCI i = m_dcfListeners.begin (); i != m_dcfListeners.end (); i++) 
862
    {
863
      (*i)->NavReset (duration);
864
    }
865
  m_lastNavStart = Simulator::Now ();
866
  m_lastNavStart = duration;
867
}
868
bool
869
MacLow::DoNavStartNow (Time duration)
870
{
871
  for (DcfListenersCI i = m_dcfListeners.begin (); i != m_dcfListeners.end (); i++) 
872
    {
873
      (*i)->NavStart (duration);
874
    }
875
  Time newNavEnd = Simulator::Now () + duration;
876
  Time oldNavEnd = m_lastNavStart + m_lastNavDuration;
877
  if (newNavEnd > oldNavEnd)
878
    {
879
      m_lastNavStart = Simulator::Now ();
880
      m_lastNavDuration = duration;
881
      return true;
882
    }
883
  return false;
884
}
885
void
886
MacLow::NotifyAckTimeoutStartNow (Time duration)
887
{
888
  for (DcfListenersCI i = m_dcfListeners.begin (); i != m_dcfListeners.end (); i++) 
889
    {
890
      (*i)->AckTimeoutStart (duration);
891
    }
892
}
893
void
894
MacLow::NotifyAckTimeoutResetNow ()
895
{
896
  for (DcfListenersCI i = m_dcfListeners.begin (); i != m_dcfListeners.end (); i++) 
897
    {
898
      (*i)->AckTimeoutReset ();
899
    }
900
}
901
void
902
MacLow::NotifyCtsTimeoutStartNow (Time duration)
903
{
904
  for (DcfListenersCI i = m_dcfListeners.begin (); i != m_dcfListeners.end (); i++) 
905
    {
906
      (*i)->CtsTimeoutStart (duration);
907
    }
908
}
909
void
910
MacLow::NotifyCtsTimeoutResetNow ()
911
{
912
  for (DcfListenersCI i = m_dcfListeners.begin (); i != m_dcfListeners.end (); i++) 
913
    {
914
      (*i)->CtsTimeoutReset ();
915
    }
916
}
917
918
void
919
MacLow::ForwardDown (Ptr<const Packet> packet, const WifiMacHeader* hdr, 
920
                     WifiMode txMode)
921
{
922
  NS_LOG_FUNCTION (this << packet << hdr << txMode);
923
  NS_LOG_DEBUG ("send " << hdr->GetTypeString () <<
924
            ", to=" << hdr->GetAddr1 () <<
925
            ", size=" << packet->GetSize () <<
926
            ", mode=" << txMode <<
927
            ", duration=" << hdr->GetDuration () <<
928
            ", seq=0x"<< std::hex << m_currentHdr.GetSequenceControl () << std::dec);
929
  m_phy->SendPacket (packet, txMode, WIFI_PREAMBLE_LONG, 0);
930
}
931
932
void
933
MacLow::CtsTimeout (void)
934
{
935
  NS_LOG_FUNCTION (this);
936
  NS_LOG_DEBUG ("cts timeout");
937
  // XXX: should check that there was no rx start before now.
938
  // we should restart a new cts timeout now until the expected
939
  // end of rx if there was a rx start before now.
940
  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
941
  station->ReportRtsFailed ();
942
  m_currentPacket = 0;
943
  MacLowTransmissionListener *listener = m_listener;
944
  m_listener = 0;
945
  listener->MissedCts ();
946
}
947
void
948
MacLow::NormalAckTimeout (void)
949
{
950
  NS_LOG_FUNCTION (this);
951
  NS_LOG_DEBUG ("normal ack timeout");
952
  // XXX: should check that there was no rx start before now.
953
  // we should restart a new ack timeout now until the expected
954
  // end of rx if there was a rx start before now.
955
  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
956
  station->ReportDataFailed ();
957
  MacLowTransmissionListener *listener = m_listener;
958
  m_listener = 0;
959
  listener->MissedAck ();
960
}
961
void
962
MacLow::FastAckTimeout (void)
963
{
964
  NS_LOG_FUNCTION (this);
965
  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
966
  station->ReportDataFailed ();
967
  MacLowTransmissionListener *listener = m_listener;
968
  m_listener = 0;
969
  if (m_phy->IsStateIdle ()) 
970
    {
971
      NS_LOG_DEBUG ("fast Ack idle missed");
972
      listener->MissedAck ();
973
    }
974
  else
975
    {
976
      NS_LOG_DEBUG ("fast Ack ok");
977
    }
978
}
979
void
980
MacLow::SuperFastAckTimeout ()
981
{
982
  NS_LOG_FUNCTION (this);
983
  WifiRemoteStation *station = GetStation (m_currentHdr.GetAddr1 ());
984
  station->ReportDataFailed ();
985
  MacLowTransmissionListener *listener = m_listener;
986
  m_listener = 0;
987
  if (m_phy->IsStateIdle ()) 
988
    {
989
      NS_LOG_DEBUG ("super fast Ack failed");
990
      listener->MissedAck ();
991
    } 
992
  else 
993
    {
994
      NS_LOG_DEBUG ("super fast Ack ok");
995
      listener->GotAck (0.0, WifiMode ());
996
    }
997
}
998
999
void
1000
MacLow::SendRtsForPacket (void)
1001
{
1002
  NS_LOG_FUNCTION (this);
1003
  /* send an RTS for this packet. */
1004
  WifiMacHeader rts;
1005
  rts.SetType (WIFI_MAC_CTL_RTS);
1006
  rts.SetDsNotFrom ();
1007
  rts.SetDsNotTo ();
1008
  rts.SetNoRetry ();
1009
  rts.SetNoMoreFragments ();
1010
  rts.SetAddr1 (m_currentHdr.GetAddr1 ());
1011
  rts.SetAddr2 (m_self);
1012
  WifiMode rtsTxMode = GetRtsTxMode (m_currentPacket, &m_currentHdr);
1013
  Time duration = Seconds (0);
1014
  if (m_txParams.HasDurationId ()) 
1015
    {
1016
      duration += m_txParams.GetDurationId ();
1017
    } 
1018
  else 
1019
    {
1020
      WifiMode dataTxMode = GetDataTxMode (m_currentPacket, &m_currentHdr);
1021
      duration += GetSifs ();
1022
      duration += GetCtsDuration (m_currentHdr.GetAddr1 (), rtsTxMode);
1023
      duration += GetSifs ();
1024
      duration += m_phy->CalculateTxDuration (GetSize (m_currentPacket, &m_currentHdr), 
1025
                                              dataTxMode, WIFI_PREAMBLE_LONG);
1026
      duration += GetSifs ();
1027
      duration += GetAckDuration (m_currentHdr.GetAddr1 (), dataTxMode);
1028
    }
1029
  rts.SetDuration (duration);
1030
1031
  Time txDuration = m_phy->CalculateTxDuration (GetRtsSize (), rtsTxMode, WIFI_PREAMBLE_LONG);
1032
  Time timerDelay = txDuration + GetCtsTimeout ();
1033
1034
  NS_ASSERT (m_ctsTimeoutEvent.IsExpired ());
1035
  NotifyCtsTimeoutStartNow (timerDelay);
1036
  m_ctsTimeoutEvent = Simulator::Schedule (timerDelay, &MacLow::CtsTimeout, this);
1037
1038
  Ptr<Packet> packet = Create<Packet> ();
1039
  packet->AddHeader (rts);
1040
  WifiMacTrailer fcs;
1041
  packet->AddTrailer (fcs);
1042
1043
  ForwardDown (packet, &rts, rtsTxMode);
1044
}
1045
1046
void
1047
MacLow::StartDataTxTimers (void)
1048
{
1049
  WifiMode dataTxMode = GetDataTxMode (m_currentPacket, &m_currentHdr);
1050
  Time txDuration = m_phy->CalculateTxDuration (GetSize (m_currentPacket, &m_currentHdr), dataTxMode, WIFI_PREAMBLE_LONG);
1051
  if (m_txParams.MustWaitNormalAck ()) 
1052
    {
1053
      Time timerDelay = txDuration + GetAckTimeout ();
1054
      NS_ASSERT (m_normalAckTimeoutEvent.IsExpired ());
1055
      NotifyAckTimeoutStartNow (timerDelay);
1056
      m_normalAckTimeoutEvent = Simulator::Schedule (timerDelay, &MacLow::NormalAckTimeout, this);
1057
    } 
1058
  else if (m_txParams.MustWaitFastAck ()) 
1059
    {
1060
      Time timerDelay = txDuration + GetPifs ();
1061
      NS_ASSERT (m_fastAckTimeoutEvent.IsExpired ());
1062
      NotifyAckTimeoutStartNow (timerDelay);
1063
      m_fastAckTimeoutEvent = Simulator::Schedule (timerDelay, &MacLow::FastAckTimeout, this);
1064
    } 
1065
  else if (m_txParams.MustWaitSuperFastAck ()) 
1066
    {
1067
      Time timerDelay = txDuration + GetPifs ();
1068
      NS_ASSERT (m_superFastAckTimeoutEvent.IsExpired ());
1069
      NotifyAckTimeoutStartNow (timerDelay);
1070
      m_superFastAckTimeoutEvent = Simulator::Schedule (timerDelay, 
1071
                                                        &MacLow::SuperFastAckTimeout, this);
1072
    } 
1073
  else if (m_txParams.HasNextPacket ()) 
1074
    {
1075
      Time delay = txDuration + GetSifs ();
1076
      NS_ASSERT (m_waitSifsEvent.IsExpired ());
1077
      m_waitSifsEvent = Simulator::Schedule (delay, &MacLow::WaitSifsAfterEndTx, this);
1078
    } 
1079
  else 
1080
    {
1081
      // since we do not expect any timer to be triggered.
1082
      m_listener = 0;
1083
    }
1084
}
1085
1086
void
1087
MacLow::SendDataPacket (void)
1088
{
1089
  NS_LOG_FUNCTION (this);
1090
  /* send this packet directly. No RTS is needed. */
1091
  StartDataTxTimers ();
1092
1093
  WifiMode dataTxMode = GetDataTxMode (m_currentPacket, &m_currentHdr);
1094
  Time duration = Seconds (0.0);
1095
  if (m_txParams.HasDurationId ()) 
1096
    {
1097
      duration += m_txParams.GetDurationId ();
1098
    } 
1099
  else 
1100
    {
1101
      if (m_txParams.MustWaitAck ()) 
1102
        {
1103
          duration += GetSifs ();
1104
          duration += GetAckDuration (m_currentHdr.GetAddr1 (), dataTxMode);
1105
        }
1106
      if (m_txParams.HasNextPacket ()) 
1107
        {
1108
          duration += GetSifs ();
1109
          duration += m_phy->CalculateTxDuration (m_txParams.GetNextPacketSize (), 
1110
                                                  dataTxMode, WIFI_PREAMBLE_LONG);
1111
          if (m_txParams.MustWaitAck ()) 
1112
            {
1113
              duration += GetSifs ();
1114
              duration += GetAckDuration (m_currentHdr.GetAddr1 (), dataTxMode);
1115
            }
1116
        }
1117
    }
1118
  m_currentHdr.SetDuration (duration);
1119
1120
  m_currentPacket->AddHeader (m_currentHdr);
1121
  WifiMacTrailer fcs;
1122
  m_currentPacket->AddTrailer (fcs);
1123
1124
  ForwardDown (m_currentPacket, &m_currentHdr, dataTxMode);
1125
  m_currentPacket = 0;
1126
}
1127
1128
bool 
1129
MacLow::IsNavZero (void) const
1130
{
1131
  if (m_lastNavStart + m_lastNavDuration < Simulator::Now ()) 
1132
    {
1133
      return true;
1134
    } 
1135
  else 
1136
    {
1137
      return false;
1138
    }
1139
}
1140
1141
WifiRemoteStation *
1142
MacLow::GetStation (Mac48Address ad) const
1143
{
1144
  return m_stationManager->Lookup (ad);
1145
}
1146
1147
void
1148
MacLow::SendCtsAfterRts (Mac48Address source, Time duration, WifiMode rtsTxMode, double rtsSnr)
1149
{
1150
  NS_LOG_FUNCTION (this << source << duration << rtsTxMode << rtsSnr);
1151
  /* send a CTS when you receive a RTS 
1152
   * right after SIFS.
1153
   */
1154
  WifiMode ctsTxMode = GetCtsTxModeForRts (source, rtsTxMode);
1155
  WifiMacHeader cts;
1156
  cts.SetType (WIFI_MAC_CTL_CTS);
1157
  cts.SetDsNotFrom ();
1158
  cts.SetDsNotTo ();
1159
  cts.SetNoMoreFragments ();
1160
  cts.SetNoRetry ();
1161
  cts.SetAddr1 (source);
1162
  duration -= GetCtsDuration (source, rtsTxMode);
1163
  duration -= GetSifs ();
1164
  NS_ASSERT (duration >= MicroSeconds (0));
1165
  cts.SetDuration (duration);
1166
1167
  Ptr<Packet> packet = Create<Packet> ();
1168
  packet->AddHeader (cts);
1169
  WifiMacTrailer fcs;
1170
  packet->AddTrailer (fcs);
1171
1172
  struct SnrTag tag;
1173
  tag.Set (rtsSnr);
1174
  packet->AddPacketTag (tag);
1175
1176
  ForwardDown (packet, &cts, ctsTxMode);
1177
}
1178
1179
void
1180
MacLow::SendDataAfterCts (Mac48Address source, Time duration, WifiMode txMode)
1181
{
1182
  NS_LOG_FUNCTION (this);
1183
  /* send the third step in a 
1184
   * RTS/CTS/DATA/ACK hanshake 
1185
   */
1186
  NS_ASSERT (m_currentPacket != 0);
1187
  StartDataTxTimers ();
1188
1189
  WifiMode dataTxMode = GetDataTxMode (m_currentPacket, &m_currentHdr);
1190
  Time newDuration = Seconds (0);
1191
  newDuration += GetSifs ();
1192
  newDuration += GetAckDuration (m_currentHdr.GetAddr1 (), dataTxMode);
1193
  Time txDuration = m_phy->CalculateTxDuration (GetSize (m_currentPacket, &m_currentHdr), 
1194
                                                dataTxMode, WIFI_PREAMBLE_LONG);
1195
  duration -= txDuration;
1196
  duration -= GetSifs ();
1197
1198
  duration = std::max (duration, newDuration);
1199
  NS_ASSERT (duration >= MicroSeconds (0));
1200
  m_currentHdr.SetDuration (duration);
1201
1202
  m_currentPacket->AddHeader (m_currentHdr);
1203
  WifiMacTrailer fcs;
1204
  m_currentPacket->AddTrailer (fcs);
1205
1206
  ForwardDown (m_currentPacket, &m_currentHdr, dataTxMode);
1207
  m_currentPacket = 0;
1208
}
1209
1210
void 
1211
MacLow::WaitSifsAfterEndTx (void)
1212
{
1213
  m_listener->StartNext ();
1214
}
1215
1216
void
1217
MacLow::FastAckFailedTimeout (void)
1218
{
1219
  NS_LOG_FUNCTION (this);
1220
  MacLowTransmissionListener *listener = m_listener;
1221
  m_listener = 0;
1222
  listener->MissedAck ();
1223
  NS_LOG_DEBUG ("fast Ack busy but missed");
1224
}
1225
1226
void
1227
MacLow::SendAckAfterData (Mac48Address source, Time duration, WifiMode dataTxMode, double dataSnr)
1228
{
1229
  NS_LOG_FUNCTION (this);
1230
  /* send an ACK when you receive 
1231
   * a packet after SIFS. 
1232
   */
1233
  WifiMode ackTxMode = GetAckTxModeForData (source, dataTxMode);
1234
  WifiMacHeader ack;
1235
  ack.SetType (WIFI_MAC_CTL_ACK);
1236
  ack.SetDsNotFrom ();
1237
  ack.SetDsNotTo ();
1238
  ack.SetNoRetry ();
1239
  ack.SetNoMoreFragments ();
1240
  ack.SetAddr1 (source);
1241
  duration -= GetAckDuration (source, dataTxMode);
1242
  duration -= GetSifs ();
1243
  NS_ASSERT (duration >= MicroSeconds (0));
1244
  ack.SetDuration (duration);
1245
1246
  Ptr<Packet> packet = Create<Packet> ();
1247
  packet->AddHeader (ack);
1248
  WifiMacTrailer fcs;
1249
  packet->AddTrailer (fcs);
1250
1251
  struct SnrTag tag;
1252
  tag.Set (dataSnr);
1253
  packet->AddPacketTag (tag);
1254
1255
  ForwardDown (packet, &ack, ackTxMode);
1256
}
1257
1258
} // namespace ns3
(-)a/src/devices/wifi/mac-low.h (-454 / +1 lines)
 Lines 1-454    Link Here 
1
/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
1
/home/quincy/code/ns3/devices/wifi/mac-low.h
2
/*
3
 * Copyright (c) 2005, 2006 INRIA
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License version 2 as 
7
 * published by the Free Software Foundation;
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software
16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 *
18
 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19
 */
20
#ifndef MAC_LOW_H
21
#define MAC_LOW_H
22
23
#include <vector>
24
#include <stdint.h>
25
#include <ostream>
26
27
#include "wifi-mac-header.h"
28
#include "wifi-mode.h"
29
#include "wifi-preamble.h"
30
#include "wifi-remote-station-manager.h"
31
#include "ns3/mac48-address.h"
32
#include "ns3/callback.h"
33
#include "ns3/event-id.h"
34
#include "ns3/packet.h"
35
#include "ns3/nstime.h"
36
37
namespace ns3 {
38
39
class WifiPhy;
40
class WifiMac;
41
42
/**
43
 * \brief listen to events coming from ns3::MacLow.
44
 */
45
class MacLowTransmissionListener {
46
public:
47
  MacLowTransmissionListener ();
48
  virtual ~MacLowTransmissionListener ();
49
50
  /**
51
   * \param snr the snr of the cts
52
   * \param txMode the txMode of the cts
53
   *
54
   * ns3::MacLow received an expected CTS within
55
   * CtsTimeout.
56
   */
57
  virtual void GotCts (double snr, WifiMode txMode) = 0;
58
  /**
59
   * ns3::MacLow did not receive an expected CTS
60
   * within CtsTimeout.
61
   */
62
  virtual void MissedCts (void) = 0;
63
  /**
64
   * \param snr the snr of the ack
65
   * \param txMode the transmission mode of the ack
66
   *
67
   * ns3::MacLow received an expected ACL within
68
   * AckTimeout. The <i>snr</i> and <i>txMode</i>
69
   * arguments are not valid when SUPER_FAST_ACK is 
70
   * used.
71
   */
72
  virtual void GotAck (double snr, WifiMode txMode) = 0;
73
  /**
74
   * ns3::MacLow did not receive an expected ACK within
75
   * AckTimeout.
76
   */
77
  virtual void MissedAck (void) = 0;
78
  /**
79
   * Invoked when ns3::MacLow wants to start a new transmission
80
   * as configured by MacLowTransmissionParameters::EnableNextData.
81
   * The listener is expected to call again MacLow::StartTransmission
82
   * with the "next" data to send.
83
   */
84
  virtual void StartNext (void) = 0;
85
86
  /**
87
   * Invoked if this transmission was canceled 
88
   * one way or another. When this method is invoked,
89
   * you can assume that the packet has not been passed
90
   * down the stack to the PHY.
91
   */
92
  virtual void Cancel (void) = 0;
93
};
94
95
96
/**
97
 * \brief listen to NAV events
98
 *
99
 * This class is typically connected to an instance of ns3::Dcf
100
 * and calls to its methods are forwards to the corresponding
101
 * ns3::Dcf methods.
102
 */
103
class MacLowDcfListener {
104
public:
105
  MacLowDcfListener ();
106
  virtual ~MacLowDcfListener ();
107
  /**
108
   * \param duration duration of NAV timer
109
   */
110
  virtual void NavStart (Time duration) = 0;
111
  /**
112
   * \param duration duration of NAV timer
113
   */
114
  virtual void NavReset (Time duration) = 0;
115
  virtual void AckTimeoutStart (Time duration) = 0;
116
  virtual void AckTimeoutReset () = 0;
117
  virtual void CtsTimeoutStart (Time duration) = 0;
118
  virtual void CtsTimeoutReset () = 0;
119
};
120
121
/**
122
 * \brief control how a packet is transmitted.
123
 *
124
 * The ns3::MacLow::StartTransmission method expects
125
 * an instance of this class to describe how the packet
126
 * should be transmitted.
127
 */
128
class MacLowTransmissionParameters {
129
public:
130
  MacLowTransmissionParameters ();
131
    
132
  /**
133
   * Wait ACKTimeout for an ACK. If we get an ACK
134
   * on time, call MacLowTransmissionListener::GotAck.
135
   * Call MacLowTransmissionListener::MissedAck otherwise.
136
   */
137
  void EnableAck (void);
138
  /**
139
   *   - wait PIFS after end-of-tx. If idle, call
140
   *     MacLowTransmissionListener::MissedAck.
141
   *   - if busy at end-of-tx+PIFS, wait end-of-rx
142
   *   - if Ack ok at end-of-rx, call 
143
   *     MacLowTransmissionListener::GotAck.
144
   *   - if Ack not ok at end-of-rx, report call 
145
   *     MacLowTransmissionListener::MissedAck
146
   *     at end-of-rx+SIFS.
147
   *
148
   * This is really complicated but it is needed for
149
   * proper HCCA support.
150
   */
151
  void EnableFastAck (void);
152
  /** 
153
   *  - if busy at end-of-tx+PIFS, call 
154
   *    MacLowTransmissionListener::GotAck
155
   *  - if idle at end-of-tx+PIFS, call
156
   *    MacLowTransmissionListener::MissedAck
157
   */
158
  void EnableSuperFastAck (void);
159
  /**
160
   * Send a RTS, and wait CTSTimeout for a CTS. If we get a 
161
   * CTS on time, call MacLowTransmissionListener::GotCts
162
   * and send data. Otherwise, call MacLowTransmissionListener::MissedCts
163
   * and do not send data.
164
   */
165
  void EnableRts (void);
166
  /**
167
   * \param size size of next data to send after current packet is
168
   *        sent.
169
   *
170
   * Add the transmission duration of the next data to the 
171
   * durationId of the outgoing packet and call 
172
   * MacLowTransmissionListener::StartNext at the end of 
173
   * the current transmission + SIFS.
174
   */
175
  void EnableNextData (uint32_t size);
176
  
177
  /**
178
   * \param durationId the value to set in the duration/Id field of
179
   *        the outgoing packet.
180
   *
181
   * Ignore all other durationId calculation and simply force the 
182
   * packet's durationId field to this value.
183
   */
184
  void EnableOverrideDurationId (Time durationId);
185
  
186
  /**
187
   * Do not wait for Ack after data transmission. Typically
188
   * used for Broadcast and multicast frames.
189
   */
190
  void DisableAck (void);
191
  /**
192
   * Do not send rts and wait for cts before sending data.
193
   */
194
  void DisableRts (void);
195
  /**
196
   * Do not attempt to send data burst after current transmission
197
   */
198
  void DisableNextData (void);
199
  /**
200
   * Do not force the duration/id field of the packet: its
201
   * value is automatically calculated by the MacLow before
202
   * calling WifiPhy::Send.
203
   */
204
  void DisableOverrideDurationId (void);
205
206
  /**
207
   * \returns true if must wait for ACK after data transmission,
208
   *          false otherwise.
209
   *
210
   * This methods returns true when any of MustWaitNormalAck,
211
   * MustWaitFastAck, or MustWaitSuperFastAck return true.
212
   */
213
  bool MustWaitAck (void) const;
214
  /**
215
   * \returns true if normal ACK protocol should be used, false
216
   *          otherwise.
217
   *
218
   * \sa EnableAck
219
   */
220
  bool MustWaitNormalAck (void) const;
221
  /**
222
   * \returns true if fast ack protocol should be used, false 
223
   *          otherwise.
224
   *
225
   * \sa EnableFastAck
226
   */
227
  bool MustWaitFastAck (void) const;
228
  /**
229
   * \returns true if super fast ack protocol should be used, false 
230
   *          otherwise.
231
   *
232
   * \sa EnableSuperFastAck
233
   */
234
  bool MustWaitSuperFastAck (void) const;
235
  /**
236
   * \returns true if RTS should be sent and CTS waited for before 
237
   *          sending data, false otherwise.
238
   */
239
  bool MustSendRts (void) const;
240
  /**
241
   * \returns true if a duration/id was forced with 
242
   *         EnableOverrideDurationId, false otherwise.
243
   */
244
  bool HasDurationId (void) const;
245
  /**
246
   * \returns the duration/id forced by EnableOverrideDurationId
247
   */
248
  Time GetDurationId (void) const;
249
  /**
250
   * \returns true if EnableNextData was called, false otherwise.
251
   */
252
  bool HasNextPacket (void) const;
253
  /**
254
   * \returns the size specified by EnableNextData.
255
   */
256
  uint32_t GetNextPacketSize (void) const;
257
258
private:
259
  friend std::ostream &operator << (std::ostream &os, const MacLowTransmissionParameters &params);
260
  uint32_t m_nextSize;
261
  enum {
262
    ACK_NONE,
263
    ACK_NORMAL,
264
    ACK_FAST,
265
    ACK_SUPER_FAST
266
  } m_waitAck;
267
  bool m_sendRts;
268
  Time m_overrideDurationId;
269
};
270
271
std::ostream &operator << (std::ostream &os, const MacLowTransmissionParameters &params);
272
273
274
/**
275
 * \brief handle RTS/CTS/DATA/ACK transactions.
276
 */
277
class MacLow : public Object {
278
public:
279
  typedef Callback<void, Ptr<Packet>, const WifiMacHeader*> MacLowRxCallback;
280
281
  MacLow ();
282
  virtual ~MacLow ();
283
284
  void SetPhy (Ptr<WifiPhy> phy);
285
  void SetWifiRemoteStationManager (Ptr<WifiRemoteStationManager> manager);
286
287
  void SetAddress (Mac48Address ad);
288
  void SetAckTimeout (Time ackTimeout);
289
  void SetCtsTimeout (Time ctsTimeout);
290
  void SetSifs (Time sifs);
291
  void SetSlotTime (Time slotTime);
292
  void SetPifs (Time pifs);
293
  void SetBssid (Mac48Address ad);
294
  Mac48Address GetAddress (void) const;
295
  Time GetAckTimeout (void) const;
296
  Time GetCtsTimeout (void) const;
297
  Time GetSifs (void) const;
298
  Time GetSlotTime (void) const;
299
  Time GetPifs (void) const;
300
  Mac48Address GetBssid (void) const;
301
302
  /**
303
   * \param callback the callback which receives every incoming packet.
304
   *
305
   * This callback typically forwards incoming packets to
306
   * an instance of ns3::MacRxMiddle.
307
   */
308
  void SetRxCallback (Callback<void,Ptr<Packet>,const WifiMacHeader *> callback);
309
  /**
310
   * \param listener listen to NAV events for every incoming
311
   *        and outgoing packet.
312
   */
313
  void RegisterDcfListener (MacLowDcfListener *listener);
314
315
  /**
316
   * \param packet to send (does not include the 802.11 MAC header and checksum)
317
   * \param hdr header associated to the packet to send.
318
   * \param parameters transmission parameters of packet.
319
   *
320
   * This transmission time includes the time required for
321
   * the next packet transmission if one was selected.
322
   */
323
  Time CalculateTransmissionTime (Ptr<const Packet> packet,
324
                                  const WifiMacHeader* hdr, 
325
                                  const MacLowTransmissionParameters& parameters) const;
326
327
  /**
328
   * \param packet packet to send
329
   * \param hdr 802.11 header for packet to send
330
   * \param parameters the transmission parameters to use for this packet.
331
   * \param listener listen to transmission events.
332
   *
333
   * Start the transmission of the input packet and notify the listener
334
   * of transmission events.
335
   */
336
  void StartTransmission (Ptr<const Packet> packet, 
337
                          const WifiMacHeader* hdr, 
338
                          MacLowTransmissionParameters parameters,
339
                          MacLowTransmissionListener *listener);
340
341
  /**
342
   * \param packet packet received
343
   * \param rxSnr snr of packet received
344
   * \param txMode transmission mode of packet received
345
   * \param preamble type of preamble used for the packet received
346
   *
347
   * This method is typically invoked by the lower PHY layer to notify
348
   * the MAC layer that a packet was successfully received.
349
   */
350
  void ReceiveOk (Ptr<Packet> packet, double rxSnr, WifiMode txMode, WifiPreamble preamble);
351
  /**
352
   * \param packet packet received.
353
   * \param rxSnr snr of packet received.
354
   *
355
   * This method is typically invoked by the lower PHY layer to notify
356
   * the MAC layer that a packet was unsuccessfully received.
357
   */
358
  void ReceiveError (Ptr<const Packet> packet, double rxSnr);
359
  /**
360
   * \param duration switching delay duration.
361
   *
362
   * This method is typically invoked by the PhyMacLowListener to notify
363
   * the MAC layer that a channel switching occured. When a channel switching
364
   * occurs, pending MAC transmissions (RTS, CTS, DATA and ACK) are cancelled.
365
   */
366
  void NotifySwitchingStartNow (Time duration); 
367
private:
368
  void CancelAllEvents (void);
369
  uint32_t GetAckSize (void) const;
370
  uint32_t GetRtsSize (void) const;
371
  uint32_t GetCtsSize (void) const;
372
  uint32_t GetSize (Ptr<const Packet> packet, const WifiMacHeader *hdr) const;
373
  Time NowUs (void) const;
374
  WifiRemoteStation *GetStation (Mac48Address to) const;
375
  void ForwardDown (Ptr<const Packet> packet, const WifiMacHeader *hdr, 
376
                    WifiMode txMode);
377
  Time CalculateOverallTxTime (Ptr<const Packet> packet,
378
                               const WifiMacHeader* hdr, 
379
                               const MacLowTransmissionParameters &params) const;
380
  WifiMode GetRtsTxMode (Ptr<const Packet> packet, const WifiMacHeader *hdr) const;
381
  WifiMode GetDataTxMode (Ptr<const Packet> packet, const WifiMacHeader *hdr) const;
382
  WifiMode GetCtsTxModeForRts (Mac48Address to, WifiMode rtsTxMode) const;
383
  WifiMode GetAckTxModeForData (Mac48Address to, WifiMode dataTxMode) const;
384
  Time GetCtsDuration (Mac48Address to, WifiMode rtsTxMode) const;
385
  Time GetAckDuration (Mac48Address to, WifiMode dataTxMode) const;
386
  void NotifyNav (const WifiMacHeader &hdr, WifiMode txMode, WifiPreamble preamble);
387
  void DoNavResetNow (Time duration);
388
  bool DoNavStartNow (Time duration);
389
  bool IsNavZero (void) const;
390
  void NotifyAckTimeoutStartNow (Time duration);
391
  void NotifyAckTimeoutResetNow ();
392
  void NotifyCtsTimeoutStartNow (Time duration);
393
  void NotifyCtsTimeoutResetNow ();
394
  void MaybeCancelPrevious (void);
395
  
396
  void NavCounterResetCtsMissed (Time rtsEndRxTime);
397
  void NormalAckTimeout (void);
398
  void FastAckTimeout (void);
399
  void SuperFastAckTimeout (void);
400
  void FastAckFailedTimeout (void);
401
  void CtsTimeout (void);
402
  void SendCtsAfterRts (Mac48Address source, Time duration, WifiMode txMode, double rtsSnr);
403
  void SendAckAfterData (Mac48Address source, Time duration, WifiMode txMode, double rtsSnr);
404
  void SendDataAfterCts (Mac48Address source, Time duration, WifiMode txMode);
405
  void WaitSifsAfterEndTx (void);
406
407
  void SendRtsForPacket (void);
408
  void SendDataPacket (void);
409
  void SendCurrentTxPacket (void);
410
  void StartDataTxTimers (void);
411
  virtual void DoDispose (void);
412
413
  void SetupPhyMacLowListener (Ptr<WifiPhy> phy); 
414
415
  Ptr<WifiPhy> m_phy;
416
  Ptr<WifiRemoteStationManager> m_stationManager;
417
  MacLowRxCallback m_rxCallback;
418
  typedef std::vector<MacLowDcfListener *>::const_iterator DcfListenersCI;
419
  typedef std::vector<MacLowDcfListener *> DcfListeners;
420
  DcfListeners m_dcfListeners;
421
422
  EventId m_normalAckTimeoutEvent;
423
  EventId m_fastAckTimeoutEvent;
424
  EventId m_superFastAckTimeoutEvent;
425
  EventId m_fastAckFailedTimeoutEvent;
426
  EventId m_ctsTimeoutEvent;
427
  EventId m_sendCtsEvent;
428
  EventId m_sendAckEvent;
429
  EventId m_sendDataEvent;
430
  EventId m_waitSifsEvent;
431
  EventId m_navCounterResetCtsMissed;
432
433
  Ptr<Packet> m_currentPacket;
434
  WifiMacHeader m_currentHdr;
435
  MacLowTransmissionParameters m_txParams;
436
  MacLowTransmissionListener *m_listener;
437
  Mac48Address m_self;
438
  Mac48Address m_bssid;
439
  Time m_ackTimeout;
440
  Time m_ctsTimeout;
441
  Time m_sifs;
442
  Time m_slotTime;
443
  Time m_pifs;
444
445
  Time m_lastNavStart;
446
  Time m_lastNavDuration;
447
448
  // Listerner needed to monitor when a channel switching occurs. 
449
  class PhyMacLowListener *m_phyMacLowListener; 
450
};
451
452
} // namespace ns3
453
454
#endif /* MAC_LOW_H */
(-)a/src/devices/wifi/propagation-loss-model.cc (-546 / +1 lines)
 Lines 1-546    Link Here 
1
/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
1
/home/quincy/code/ns3/devices/wifi/propagation-loss-model.cc
2
/*
3
 * Copyright (c) 2005,2006,2007 INRIA
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License version 2 as 
7
 * published by the Free Software Foundation;
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software
16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 *
18
 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19
 * Contributions: Timo Bingmann <timo.bingmann@student.kit.edu>
20
 */
21
22
#include "propagation-loss-model.h"
23
#include "ns3/log.h"
24
#include "ns3/mobility-model.h"
25
#include "ns3/boolean.h"
26
#include "ns3/double.h"
27
#include <math.h>
28
29
NS_LOG_COMPONENT_DEFINE ("PropagationLossModel");
30
31
namespace ns3 {
32
33
// ------------------------------------------------------------------------- //
34
35
NS_OBJECT_ENSURE_REGISTERED (PropagationLossModel);
36
37
TypeId 
38
PropagationLossModel::GetTypeId (void)
39
{
40
  static TypeId tid = TypeId ("ns3::PropagationLossModel")
41
    .SetParent<Object> ()
42
    ;
43
  return tid;
44
}
45
46
PropagationLossModel::PropagationLossModel ()
47
  : m_next (0)
48
{}
49
50
PropagationLossModel::~PropagationLossModel ()
51
{}
52
53
void 
54
PropagationLossModel::SetNext (Ptr<PropagationLossModel> next)
55
{
56
  m_next = next;
57
}
58
59
double 
60
PropagationLossModel::CalcRxPower (double txPowerDbm,
61
                                   Ptr<MobilityModel> a,
62
                                   Ptr<MobilityModel> b) const
63
{
64
  double self = DoCalcRxPower (txPowerDbm, a, b);
65
  if (m_next != 0)
66
    {
67
      self = m_next->CalcRxPower (self, a, b);
68
    }
69
  return self;
70
}
71
72
// ------------------------------------------------------------------------- //
73
74
NS_OBJECT_ENSURE_REGISTERED (RandomPropagationLossModel);
75
76
TypeId 
77
RandomPropagationLossModel::GetTypeId (void)
78
{
79
  static TypeId tid = TypeId ("ns3::RandomPropagationLossModel")
80
    .SetParent<PropagationLossModel> ()
81
    .AddConstructor<RandomPropagationLossModel> ()
82
    .AddAttribute ("Variable", "The random variable used to pick a loss everytime CalcRxPower is invoked.",
83
                   RandomVariableValue (ConstantVariable (1.0)),
84
                   MakeRandomVariableAccessor (&RandomPropagationLossModel::m_variable),
85
                   MakeRandomVariableChecker ())
86
    ;
87
  return tid;
88
}
89
RandomPropagationLossModel::RandomPropagationLossModel ()
90
  : PropagationLossModel ()
91
{}
92
93
RandomPropagationLossModel::~RandomPropagationLossModel ()
94
{}
95
96
double 
97
RandomPropagationLossModel::DoCalcRxPower (double txPowerDbm,
98
                                           Ptr<MobilityModel> a,
99
                                           Ptr<MobilityModel> b) const
100
{
101
  double rxc = -m_variable.GetValue ();
102
  NS_LOG_DEBUG ("attenuation coefficent="<<rxc<<"Db");
103
  return txPowerDbm + rxc;
104
}
105
106
// ------------------------------------------------------------------------- //
107
108
NS_OBJECT_ENSURE_REGISTERED (FriisPropagationLossModel);
109
110
const double FriisPropagationLossModel::PI = 3.14159265358979323846;
111
112
TypeId 
113
FriisPropagationLossModel::GetTypeId (void)
114
{
115
  static TypeId tid = TypeId ("ns3::FriisPropagationLossModel")
116
    .SetParent<PropagationLossModel> ()
117
    .AddConstructor<FriisPropagationLossModel> ()
118
    .AddAttribute ("Lambda", 
119
                   "The wavelength  (default is 5.15 GHz at 300 000 km/s).",
120
                   DoubleValue (300000000.0 / 5.150e9),
121
                   MakeDoubleAccessor (&FriisPropagationLossModel::m_lambda),
122
                   MakeDoubleChecker<double> ())
123
    .AddAttribute ("SystemLoss", "The system loss",
124
                   DoubleValue (1.0),
125
                   MakeDoubleAccessor (&FriisPropagationLossModel::m_systemLoss),
126
                   MakeDoubleChecker<double> ())
127
    .AddAttribute ("MinDistance", 
128
                   "The distance under which the propagation model refuses to give results (m)",
129
                   DoubleValue (0.5),
130
                   MakeDoubleAccessor (&FriisPropagationLossModel::SetMinDistance,
131
                                       &FriisPropagationLossModel::GetMinDistance),
132
                   MakeDoubleChecker<double> ())
133
    ;
134
  return tid;
135
}
136
137
FriisPropagationLossModel::FriisPropagationLossModel ()
138
{}
139
void 
140
FriisPropagationLossModel::SetSystemLoss (double systemLoss)
141
{
142
  m_systemLoss = systemLoss;
143
}
144
double 
145
FriisPropagationLossModel::GetSystemLoss (void) const
146
{
147
  return m_systemLoss;
148
}
149
void 
150
FriisPropagationLossModel::SetMinDistance (double minDistance)
151
{
152
  m_minDistance = minDistance;
153
}
154
double 
155
FriisPropagationLossModel::GetMinDistance (void) const
156
{
157
  return m_minDistance;
158
}
159
void 
160
FriisPropagationLossModel::SetLambda (double frequency, double speed)
161
{
162
  m_lambda = speed / frequency;
163
}
164
void 
165
FriisPropagationLossModel::SetLambda (double lambda)
166
{
167
  m_lambda = lambda;
168
}
169
double 
170
FriisPropagationLossModel::GetLambda (void) const
171
{
172
  return m_lambda;
173
}
174
175
double 
176
FriisPropagationLossModel::DbmToW (double dbm) const
177
{
178
  double mw = pow(10.0,dbm/10.0);
179
  return mw / 1000.0;
180
}
181
182
double
183
FriisPropagationLossModel::DbmFromW (double w) const
184
{
185
  double dbm = log10 (w * 1000.0) * 10.0;
186
  return dbm;
187
}
188
189
double 
190
FriisPropagationLossModel::DoCalcRxPower (double txPowerDbm,
191
                                          Ptr<MobilityModel> a,
192
                                          Ptr<MobilityModel> b) const
193
{
194
  /*
195
   * Friis free space equation:
196
   * where Pt, Gr, Gr and P are in Watt units
197
   * L is in meter units.
198
   *
199
   *    P     Gt * Gr * (lambda^2)
200
   *   --- = ---------------------
201
   *    Pt     (4 * pi * d)^2 * L
202
   *
203
   * Gt: tx gain (unit-less)
204
   * Gr: rx gain (unit-less)
205
   * Pt: tx power (W)
206
   * d: distance (m)
207
   * L: system loss
208
   * lambda: wavelength (m)
209
   *
210
   * Here, we ignore tx and rx gain and the input and output values 
211
   * are in dB or dBm:
212
   *
213
   *                           lambda^2
214
   * rx = tx +  10 log10 (-------------------)
215
   *                       (4 * pi * d)^2 * L
216
   *
217
   * rx: rx power (dB)
218
   * tx: tx power (dB)
219
   * d: distance (m)
220
   * L: system loss (unit-less)
221
   * lambda: wavelength (m)
222
   */
223
  double distance = a->GetDistanceFrom (b);
224
  if (distance <= m_minDistance)
225
    {
226
      return txPowerDbm;
227
    }
228
  double numerator = m_lambda * m_lambda;
229
  double denominator = 16 * PI * PI * distance * distance * m_systemLoss;
230
  double pr = 10 * log10 (numerator / denominator);
231
  NS_LOG_DEBUG ("distance="<<distance<<"m, attenuation coefficient="<<pr<<"dB");
232
  return txPowerDbm + pr;
233
}
234
235
// ------------------------------------------------------------------------- //
236
237
NS_OBJECT_ENSURE_REGISTERED (LogDistancePropagationLossModel);
238
239
TypeId
240
LogDistancePropagationLossModel::GetTypeId (void)
241
{
242
  static TypeId tid = TypeId ("ns3::LogDistancePropagationLossModel")
243
    .SetParent<PropagationLossModel> ()
244
    .AddConstructor<LogDistancePropagationLossModel> ()
245
    .AddAttribute ("Exponent",
246
                   "The exponent of the Path Loss propagation model",
247
                   DoubleValue (3.0),
248
                   MakeDoubleAccessor (&LogDistancePropagationLossModel::m_exponent),
249
                   MakeDoubleChecker<double> ())
250
    .AddAttribute ("ReferenceDistance",
251
                   "The distance at which the reference loss is calculated (m)",
252
                   DoubleValue (1.0),
253
                   MakeDoubleAccessor (&LogDistancePropagationLossModel::m_referenceDistance),
254
                   MakeDoubleChecker<double> ())
255
    .AddAttribute ("ReferenceLoss",
256
                   "The reference loss at reference distance (dB). (Default is Friis at 1m with 5.15 GHz)",
257
                   DoubleValue (46.6777),
258
                   MakeDoubleAccessor (&LogDistancePropagationLossModel::m_referenceLoss),
259
                   MakeDoubleChecker<double> ())
260
    ;
261
  return tid;
262
                   
263
}
264
265
LogDistancePropagationLossModel::LogDistancePropagationLossModel ()
266
{}
267
268
void 
269
LogDistancePropagationLossModel::SetPathLossExponent (double n)
270
{
271
  m_exponent = n;
272
}
273
void 
274
LogDistancePropagationLossModel::SetReference (double referenceDistance, double referenceLoss)
275
{
276
  m_referenceDistance = referenceDistance;
277
  m_referenceLoss = referenceLoss;
278
}
279
double 
280
LogDistancePropagationLossModel::GetPathLossExponent (void) const
281
{
282
  return m_exponent;
283
}
284
  
285
double 
286
LogDistancePropagationLossModel::DoCalcRxPower (double txPowerDbm,
287
                                                Ptr<MobilityModel> a,
288
                                                Ptr<MobilityModel> b) const
289
{
290
  double distance = a->GetDistanceFrom (b);
291
  if (distance <= m_referenceDistance)
292
    {
293
      return txPowerDbm;
294
    }
295
  /**
296
   * The formula is:
297
   * rx = 10 * log (Pr0(tx)) - n * 10 * log (d/d0)
298
   *
299
   * Pr0: rx power at reference distance d0 (W)
300
   * d0: reference distance: 1.0 (m)
301
   * d: distance (m)
302
   * tx: tx power (dB)
303
   * rx: dB
304
   *
305
   * Which, in our case is:
306
   *
307
   * rx = rx0(tx) - 10 * n * log (d/d0)
308
   */
309
  double pathLossDb = 10 * m_exponent * log10 (distance / m_referenceDistance);
310
  double rxc = -m_referenceLoss - pathLossDb;
311
  NS_LOG_DEBUG ("distance="<<distance<<"m, reference-attenuation="<<-m_referenceLoss<<"dB, "<<
312
		"attenuation coefficient="<<rxc<<"db");
313
  return txPowerDbm + rxc;
314
}
315
316
// ------------------------------------------------------------------------- //
317
318
NS_OBJECT_ENSURE_REGISTERED (ThreeLogDistancePropagationLossModel);
319
320
TypeId
321
ThreeLogDistancePropagationLossModel::GetTypeId (void)
322
{
323
  static TypeId tid = TypeId ("ns3::ThreeLogDistancePropagationLossModel")
324
    .SetParent<PropagationLossModel> ()
325
    .AddConstructor<ThreeLogDistancePropagationLossModel> ()
326
    .AddAttribute ("Distance0",
327
                   "Beginning of the first (near) distance field",
328
                   DoubleValue (1.0),
329
                   MakeDoubleAccessor (&ThreeLogDistancePropagationLossModel::m_distance0),
330
                   MakeDoubleChecker<double> ())
331
    .AddAttribute ("Distance1",
332
                   "Beginning of the second (middle) distance field.",
333
                   DoubleValue (200.0),
334
                   MakeDoubleAccessor (&ThreeLogDistancePropagationLossModel::m_distance1),
335
                   MakeDoubleChecker<double> ())
336
    .AddAttribute ("Distance2",
337
                   "Beginning of the third (far) distance field.",
338
                   DoubleValue (500.0),
339
                   MakeDoubleAccessor (&ThreeLogDistancePropagationLossModel::m_distance2),
340
                   MakeDoubleChecker<double> ())
341
    .AddAttribute ("Exponent0",
342
                   "The exponent for the first field.",
343
                   DoubleValue (1.9),
344
                   MakeDoubleAccessor (&ThreeLogDistancePropagationLossModel::m_exponent0),
345
                   MakeDoubleChecker<double> ())
346
    .AddAttribute ("Exponent1",
347
                   "The exponent for the second field.",
348
                   DoubleValue (3.8),
349
                   MakeDoubleAccessor (&ThreeLogDistancePropagationLossModel::m_exponent1),
350
                   MakeDoubleChecker<double> ())
351
    .AddAttribute ("Exponent2",
352
                   "The exponent for the third field.",
353
                   DoubleValue (3.8),
354
                   MakeDoubleAccessor (&ThreeLogDistancePropagationLossModel::m_exponent2),
355
                   MakeDoubleChecker<double> ())
356
    .AddAttribute ("ReferenceLoss",
357
                   "The reference loss at distance d0 (dB). (Default is Friis at 1m with 5.15 GHz)",
358
                   DoubleValue (46.6777),
359
                   MakeDoubleAccessor (&ThreeLogDistancePropagationLossModel::m_referenceLoss),
360
                   MakeDoubleChecker<double> ())
361
    ;
362
  return tid;
363
                   
364
}
365
366
ThreeLogDistancePropagationLossModel::ThreeLogDistancePropagationLossModel ()
367
{
368
}
369
370
double 
371
ThreeLogDistancePropagationLossModel::DoCalcRxPower (double txPowerDbm,
372
                                                     Ptr<MobilityModel> a,
373
                                                     Ptr<MobilityModel> b) const
374
{
375
  double distance = a->GetDistanceFrom (b);
376
  NS_ASSERT(distance >= 0);
377
378
  // See doxygen comments for the formula and explanation
379
380
  double pathLossDb;
381
382
  if (distance < m_distance0)
383
    {
384
      pathLossDb = 0;
385
    }
386
  else if (distance < m_distance1)
387
    {
388
      pathLossDb = m_referenceLoss
389
        + 10 * m_exponent0 * log10(distance / m_distance0);
390
    }
391
  else if (distance < m_distance2)
392
    {
393
      pathLossDb = m_referenceLoss
394
        + 10 * m_exponent0 * log10(m_distance1 / m_distance0)
395
        + 10 * m_exponent1 * log10(distance / m_distance1);
396
    }
397
  else
398
    {
399
      pathLossDb = m_referenceLoss
400
        + 10 * m_exponent0 * log10(m_distance1 / m_distance0)
401
        + 10 * m_exponent1 * log10(m_distance2 / m_distance1)
402
        + 10 * m_exponent2 * log10(distance / m_distance2);
403
    }
404
405
  NS_LOG_DEBUG ("ThreeLogDistance distance=" << distance << "m, " <<
406
                "attenuation=" << pathLossDb << "dB");
407
408
  return txPowerDbm - pathLossDb;
409
}
410
411
// ------------------------------------------------------------------------- //
412
413
NS_OBJECT_ENSURE_REGISTERED (NakagamiPropagationLossModel);
414
415
TypeId
416
NakagamiPropagationLossModel::GetTypeId (void)
417
{
418
  static TypeId tid = TypeId ("ns3::NakagamiPropagationLossModel")
419
    .SetParent<PropagationLossModel> ()
420
    .AddConstructor<NakagamiPropagationLossModel> ()
421
    .AddAttribute ("Distance1",
422
                   "Beginning of the second distance field. Default is 80m.",
423
                   DoubleValue (80.0),
424
                   MakeDoubleAccessor (&NakagamiPropagationLossModel::m_distance1),
425
                   MakeDoubleChecker<double> ())
426
    .AddAttribute ("Distance2",
427
                   "Beginning of the third distance field. Default is 200m.",
428
                   DoubleValue (200.0),
429
                   MakeDoubleAccessor (&NakagamiPropagationLossModel::m_distance2),
430
                   MakeDoubleChecker<double> ())
431
    .AddAttribute ("m0",
432
                   "m0 for distances smaller than Distance1. Default is 1.5.",
433
                   DoubleValue (1.5),
434
                   MakeDoubleAccessor (&NakagamiPropagationLossModel::m_m0),
435
                   MakeDoubleChecker<double> ())
436
    .AddAttribute ("m1",
437
                   "m1 for distances smaller than Distance2. Default is 0.75.",
438
                   DoubleValue (0.75),
439
                   MakeDoubleAccessor (&NakagamiPropagationLossModel::m_m1),
440
                   MakeDoubleChecker<double> ())
441
    .AddAttribute ("m2",
442
                   "m2 for distances greater than Distance2. Default is 0.75.",
443
                   DoubleValue (0.75),
444
                   MakeDoubleAccessor (&NakagamiPropagationLossModel::m_m2),
445
                   MakeDoubleChecker<double> ())
446
    ;
447
  return tid;
448
                   
449
}
450
451
NakagamiPropagationLossModel::NakagamiPropagationLossModel ()
452
{}
453
454
double 
455
NakagamiPropagationLossModel::DoCalcRxPower (double txPowerDbm,
456
                                             Ptr<MobilityModel> a,
457
                                             Ptr<MobilityModel> b) const
458
{
459
  // select m parameter
460
461
  double distance = a->GetDistanceFrom (b);
462
  NS_ASSERT(distance >= 0);
463
464
  double m;
465
  if (distance < m_distance1)
466
    {
467
      m = m_m0;
468
    }
469
  else if (distance < m_distance2)
470
    {
471
      m = m_m1;
472
    }
473
  else
474
    {
475
      m = m_m2;
476
    }
477
  
478
  // the current power unit is dBm, but Watt is put into the Nakagami /
479
  // Rayleigh distribution.
480
  double powerW = pow(10, (txPowerDbm - 30) / 10);
481
482
  double resultPowerW;
483
484
  // switch between Erlang- and Gamma distributions: this is only for
485
  // speed. (Gamma is equal to Erlang for any positive integer m.)
486
  unsigned int int_m = static_cast<unsigned int>(floor(m));
487
488
  if (int_m == m)
489
    {
490
      resultPowerW = m_erlangRandomVariable.GetValue(int_m, powerW / m);
491
    }
492
  else
493
    {
494
      resultPowerW = m_gammaRandomVariable.GetValue(m, powerW / m);
495
    }
496
497
  double resultPowerDbm = 10 * log10(resultPowerW) + 30;
498
499
  NS_LOG_DEBUG ("Nakagami distance=" << distance << "m, " <<
500
                "power=" << powerW <<"W, " <<
501
                "resultPower=" << resultPowerW << "W=" << resultPowerDbm << "dBm");
502
503
  return resultPowerDbm;
504
}
505
506
// ------------------------------------------------------------------------- //
507
508
NS_OBJECT_ENSURE_REGISTERED (FixedRssLossModel);
509
510
TypeId 
511
FixedRssLossModel::GetTypeId (void)
512
{
513
  static TypeId tid = TypeId ("ns3::FixedRssLossModel")
514
    .SetParent<PropagationLossModel> ()
515
    .AddConstructor<FixedRssLossModel> ()
516
    .AddAttribute ("Rss", "The fixed receiver Rss.",
517
                   DoubleValue (-150.0),
518
                   MakeDoubleAccessor (&FixedRssLossModel::m_rss),
519
                   MakeDoubleChecker<double> ())
520
    ;
521
  return tid;
522
}
523
FixedRssLossModel::FixedRssLossModel ()
524
  : PropagationLossModel ()
525
{}
526
527
FixedRssLossModel::~FixedRssLossModel ()
528
{}
529
530
void 
531
FixedRssLossModel::SetRss (double rss)
532
{
533
  m_rss = rss;
534
}
535
536
double 
537
FixedRssLossModel::DoCalcRxPower (double txPowerDbm,
538
                                           Ptr<MobilityModel> a,
539
                                           Ptr<MobilityModel> b) const
540
{
541
  return m_rss;
542
}
543
544
// ------------------------------------------------------------------------- //
545
546
} // namespace ns3
(-)a/src/devices/wifi/propagation-loss-model.h (-375 / +1 lines)
 Lines 1-375    Link Here 
1
/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
1
/home/quincy/code/ns3/devices/wifi/propagation-loss-model.h
2
/*
3
 * Copyright (c) 2005,2006,2007 INRIA
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License version 2 as 
7
 * published by the Free Software Foundation;
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software
16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 *
18
 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19
 * Contributions: Timo Bingmann <timo.bingmann@student.kit.edu>
20
 * Contributions: Gary Pei <guangyu.pei@boeing.com> for fixed RSS
21
 */
22
23
#ifndef PROPAGATION_LOSS_MODEL_H
24
#define PROPAGATION_LOSS_MODEL_H
25
26
#include "ns3/object.h"
27
#include "ns3/random-variable.h"
28
29
namespace ns3 {
30
31
class MobilityModel;
32
33
/**
34
 * \brief Modelize the propagation loss through a transmission medium
35
 *
36
 * Calculate the receive power (dbm) from a transmit power (dbm)
37
 * and a mobility model for the source and destination positions.
38
 */
39
class PropagationLossModel : public Object
40
{
41
public:
42
  static TypeId GetTypeId (void);
43
44
  PropagationLossModel ();
45
  virtual ~PropagationLossModel ();
46
47
  void SetNext (Ptr<PropagationLossModel> next);
48
49
  /**
50
   * \param txPowerDbm current transmission power (in dBm)
51
   * \param a the mobility model of the source
52
   * \param b the mobility model of the destination
53
   * \returns the reception power after adding/multiplying propagation loss (in dBm)
54
   */
55
  double CalcRxPower (double txPowerDbm,
56
                      Ptr<MobilityModel> a,
57
                      Ptr<MobilityModel> b) const;
58
private:
59
  PropagationLossModel (const PropagationLossModel &o);
60
  PropagationLossModel &operator = (const PropagationLossModel &o);
61
  virtual double DoCalcRxPower (double txPowerDbm,
62
                                Ptr<MobilityModel> a,
63
                                Ptr<MobilityModel> b) const = 0;
64
65
  Ptr<PropagationLossModel> m_next;
66
};
67
68
/**
69
 * \brief The propagation loss follows a random distribution.
70
 */ 
71
class RandomPropagationLossModel : public PropagationLossModel
72
{
73
public:
74
  static TypeId GetTypeId (void);
75
76
  RandomPropagationLossModel ();
77
  virtual ~RandomPropagationLossModel ();
78
79
private:
80
  RandomPropagationLossModel (const RandomPropagationLossModel &o);
81
  RandomPropagationLossModel & operator = (const RandomPropagationLossModel &o);
82
  virtual double DoCalcRxPower (double txPowerDbm,
83
                                Ptr<MobilityModel> a,
84
                                Ptr<MobilityModel> b) const;
85
  RandomVariable m_variable;
86
};
87
88
/**
89
 * \brief a Friis propagation loss model
90
 *
91
 * The Friis propagation loss model was first described in
92
 * "A Note on a Simple Transmission Formula", by 
93
 * "Harald T. Friis".
94
 * 
95
 * The original equation was described as:
96
 *  \f$ \frac{P_r}{P_t} = \frac{A_r A_t}{d^2\lambda^2} \f$
97
 *  with the following equation for the case of an
98
 *  isotropic antenna with no heat loss:
99
 *  \f$ A_{isotr.} = \frac{\lambda^2}{4\pi} \f$
100
 *
101
 * The final equation becomes:
102
 * \f$ \frac{P_r}{P_t} = \frac{\lambda^2}{(4 \pi d)^2} \f$
103
 *
104
 * Modern extensions to this original equation are:
105
 * \f$ P_r = \frac{P_t G_t G_r \lambda^2}{(4 \pi d)^2 L}\f$
106
 *
107
 * With:
108
 *  - \f$ P_r \f$ : reception power (W)
109
 *  - \f$ P_t \f$ : transmission power (W)
110
 *  - \f$ G_t \f$ : transmission gain (unit-less)
111
 *  - \f$ G_r \f$ : reception gain (unit-less)
112
 *  - \f$ \lambda \f$ : wavelength (m)
113
 *  - \f$ d \f$ : distance (m)
114
 *  - \f$ L \f$ : system loss (unit-less)
115
 *
116
 *
117
 * This model is invalid for small distance values.
118
 * The current implementation returns the txpower as the rxpower
119
 * for any distance smaller than MinDistance.
120
 */
121
class FriisPropagationLossModel : public PropagationLossModel
122
{
123
public:
124
  static TypeId GetTypeId (void);
125
  FriisPropagationLossModel ();
126
  /**
127
   * \param frequency (Hz)
128
   * \param speed (m/s)
129
   *
130
   * Set the main wavelength used in the Friis model 
131
   * calculation.
132
   */
133
  void SetLambda (double frequency, double speed);
134
  /**
135
   * \param lambda (m) the wavelength
136
   *
137
   * Set the main wavelength used in the Friis model 
138
   * calculation.
139
   */
140
  void SetLambda (double lambda);
141
  /**
142
   * \param systemLoss (dimension-less)
143
   *
144
   * Set the system loss used by the Friis propagation model.
145
   */
146
  void SetSystemLoss (double systemLoss);
147
148
  /**
149
   * \param minDistance the minimum distance
150
   *
151
   * Below this distance, the txpower is returned
152
   * unmodified as the rxpower.
153
   */
154
  void SetMinDistance (double minDistance);
155
156
  /**
157
   * \returns the minimum distance.
158
   */
159
  double GetMinDistance (void) const;
160
161
  /**
162
   * \returns the current wavelength (m)
163
   */
164
  double GetLambda (void) const;
165
  /**
166
   * \returns the current system loss (dimention-less)
167
   */
168
  double GetSystemLoss (void) const;
169
170
private:
171
  FriisPropagationLossModel (const FriisPropagationLossModel &o);
172
  FriisPropagationLossModel & operator = (const FriisPropagationLossModel &o);
173
  virtual double DoCalcRxPower (double txPowerDbm,
174
                                Ptr<MobilityModel> a,
175
                                Ptr<MobilityModel> b) const;
176
  double DbmToW (double dbm) const;
177
  double DbmFromW (double w) const;
178
179
  static const double PI;
180
  double m_lambda;
181
  double m_systemLoss;
182
  double m_minDistance;
183
};
184
185
/**
186
 * \brief a log distance propagation model.
187
 *
188
 * This model calculates the reception power with a so-called
189
 * log-distance propagation model:
190
 * \f$ L = L_0 + 10 n log_{10}(\frac{d}{d_0})\f$
191
 *
192
 * where:
193
 *  - \f$ n \f$ : the path loss distance exponent
194
 *  - \f$ d_0 \f$ : reference distance (m)
195
 *  - \f$ L_0 \f$ : path loss at reference distance (dB)
196
 *  - \f$ d \f$ : distance (m)
197
 *  - \f$ L \f$ : path loss (dB)
198
 *
199
 * When the path loss is requested at a distance smaller than
200
 * the reference distance, the tx power is returned.
201
 *
202
 */
203
class LogDistancePropagationLossModel : public PropagationLossModel
204
{
205
public:
206
  static TypeId GetTypeId (void);
207
  LogDistancePropagationLossModel ();
208
209
  /**
210
   * \param n the path loss exponent.
211
   * Set the path loss exponent.
212
   */
213
  void SetPathLossExponent (double n);
214
  /** 
215
   * \returns the current path loss exponent.
216
   */
217
  double GetPathLossExponent (void) const;
218
219
  void SetReference (double referenceDistance, double referenceLoss);
220
  
221
private:
222
  LogDistancePropagationLossModel (const LogDistancePropagationLossModel &o);
223
  LogDistancePropagationLossModel & operator = (const LogDistancePropagationLossModel &o);
224
  virtual double DoCalcRxPower (double txPowerDbm,
225
                                Ptr<MobilityModel> a,
226
                                Ptr<MobilityModel> b) const;
227
  static Ptr<PropagationLossModel> CreateDefaultReference (void);
228
229
  double m_exponent;
230
  double m_referenceDistance;
231
  double m_referenceLoss;
232
};
233
234
/**
235
 * \brief A log distance path loss propagation model with three distance
236
 * fields. This model is the same as ns3::LogDistancePropagationLossModel
237
 * except that it has three distance fields: near, middle and far with
238
 * different exponents.
239
 *
240
 * Within each field the reception power is calculated using the log-distance
241
 * propagation equation:
242
 * \f[ L = L_0 + 10 \cdot n_0 log_{10}(\frac{d}{d_0})\f]
243
 * Each field begins where the previous ends and all together form a continuous function.
244
 *
245
 * There are three valid distance fields: near, middle, far. Actually four: the
246
 * first from 0 to the reference distance is invalid and returns txPowerDbm.
247
 *
248
 * \f[ \underbrace{0 \cdots\cdots}_{=0} \underbrace{d_0 \cdots\cdots}_{n_0} \underbrace{d_1 \cdots\cdots}_{n_1} \underbrace{d_2 \cdots\cdots}_{n_2} \infty \f]
249
 *
250
 * Complete formula for the path loss in dB:
251
 *
252
 * \f[\displaystyle L =
253
\begin{cases}
254
0 & d < d_0 \\
255
L_0 + 10 \cdot n_0 \log_{10}(\frac{d}{d_0}) & d_0 \leq d < d_1 \\
256
L_0 + 10 \cdot n_0 \log_{10}(\frac{d_1}{d_0}) + 10 \cdot n_1 \log_{10}(\frac{d}{d_1}) & d_1 \leq d < d_2 \\
257
L_0 + 10 \cdot n_0 \log_{10}(\frac{d_1}{d_0}) + 10 \cdot n_1 \log_{10}(\frac{d_2}{d_1}) + 10 \cdot n_2 \log_{10}(\frac{d}{d_2})& d_2 \leq d
258
\end{cases}\f]
259
 *
260
 * where:
261
 *  - \f$ L \f$ : resulting path loss (dB)
262
 *  - \f$ d \f$ : distance (m)
263
 *  - \f$ d_0, d_1, d_2 \f$ : three distance fields (m)
264
 *  - \f$ n_0, n_1, n_2 \f$ : path loss distance exponent for each field (unitless)
265
 *  - \f$ L_0 \f$ : path loss at reference distance (dB)
266
 *
267
 * When the path loss is requested at a distance smaller than the reference
268
 * distance \f$ d_0 \f$, the tx power (with no path loss) is returned. The
269
 * reference distance defaults to 1m and reference loss defaults to
270
 * ns3::FriisPropagationLossModel with 5.15 GHz and is thus \f$ L_0 \f$ = 46.67 dB.
271
 */
272
273
class ThreeLogDistancePropagationLossModel : public PropagationLossModel
274
{
275
public:
276
  static TypeId GetTypeId (void);
277
  ThreeLogDistancePropagationLossModel ();
278
279
  // Parameters are all accessible via attributes.
280
281
private:
282
  ThreeLogDistancePropagationLossModel (const ThreeLogDistancePropagationLossModel& o);
283
  ThreeLogDistancePropagationLossModel& operator= (const ThreeLogDistancePropagationLossModel& o);
284
285
  virtual double DoCalcRxPower (double txPowerDbm,
286
                                Ptr<MobilityModel> a,
287
                                Ptr<MobilityModel> b) const;
288
289
  double m_distance0;
290
  double m_distance1;
291
  double m_distance2;
292
293
  double m_exponent0;
294
  double m_exponent1;
295
  double m_exponent2;
296
297
  double m_referenceLoss;
298
};
299
300
/**
301
 * \brief Nakagami-m fast fading propagation loss model.
302
 *
303
 * The Nakagami-m distribution is applied to the power level. The probability
304
 * density function is defined as
305
 * \f[ p(x; m, \omega) = \frac{2 m^m}{\Gamma(m) \omega^m} x^{2m - 1} e^{-\frac{m}{\omega} x^2} = 2 x \cdot p_{\text{Gamma}}(x^2, m, \frac{m}{\omega}) \f]
306
 * with \f$ m \f$ the fading depth parameter and \f$ \omega \f$ the average received power.
307
 *
308
 * It is implemented by either a ns3::GammaVariable or a ns3::ErlangVariable
309
 * random variable.
310
 *
311
 * Like in ns3::ThreeLogDistancePropagationLossModel, the m parameter is varied
312
 * over three distance fields:
313
 * \f[ \underbrace{0 \cdots\cdots}_{m_0} \underbrace{d_1 \cdots\cdots}_{m_1} \underbrace{d_2 \cdots\cdots}_{m_2} \infty \f]
314
 *
315
 * For m = 1 the Nakagami-m distribution equals the Rayleigh distribution. Thus
316
 * this model also implements Rayleigh distribution based fast fading.
317
 */
318
319
class NakagamiPropagationLossModel : public PropagationLossModel
320
{
321
public:
322
  static TypeId GetTypeId (void);
323
324
  NakagamiPropagationLossModel ();
325
326
  // Parameters are all accessible via attributes.
327
328
private:
329
  NakagamiPropagationLossModel (const NakagamiPropagationLossModel& o);
330
  NakagamiPropagationLossModel& operator= (const NakagamiPropagationLossModel& o);
331
332
  virtual double DoCalcRxPower (double txPowerDbm,
333
                                Ptr<MobilityModel> a,
334
                                Ptr<MobilityModel> b) const;
335
336
  double m_distance1;
337
  double m_distance2;
338
339
  double m_m0;
340
  double m_m1;
341
  double m_m2;
342
343
  ErlangVariable        m_erlangRandomVariable;
344
  GammaVariable         m_gammaRandomVariable;
345
};
346
347
/**
348
 * \brief The propagation loss is fixed. The user can set received power level.
349
 */ 
350
class FixedRssLossModel : public PropagationLossModel
351
{
352
public:
353
  static TypeId GetTypeId (void);
354
355
  FixedRssLossModel ();
356
  virtual ~FixedRssLossModel ();
357
  /**
358
   * \param rss (dBm) the received signal strength
359
   *
360
   * Set the RSS.
361
   */
362
  void SetRss (double rss);
363
364
private:
365
  FixedRssLossModel (const FixedRssLossModel &o);
366
  FixedRssLossModel & operator = (const FixedRssLossModel &o);
367
  virtual double DoCalcRxPower (double txPowerDbm,
368
                                Ptr<MobilityModel> a,
369
                                Ptr<MobilityModel> b) const;
370
  double m_rss;
371
};
372
373
} // namespace ns3
374
375
#endif /* PROPAGATION_LOSS_MODEL_H */
(-)a/src/devices/wifi/wscript (-122 / +1 lines)
 Lines 1-122    Link Here 
1
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
1
/home/quincy/code/ns3/devices/wifi/wscript
2
3
def build(bld):
4
    obj = bld.create_ns3_module('wifi', ['node'])
5
    obj.source = [
6
        'propagation-delay-model.cc',
7
        'propagation-loss-model.cc',
8
        'propagation-loss-model-test-suite.cc',
9
        'jakes-propagation-loss-model.cc',
10
        'wifi-channel.cc',
11
        'wifi-mode.cc',
12
        'ssid.cc',
13
        'wifi-phy.cc',
14
        'wifi-phy-state-helper.cc',
15
        'error-rate-model.cc',
16
        'yans-error-rate-model.cc',
17
        'interference-helper.cc',
18
        'interference-helper-tx-duration-test.cc',
19
        'yans-wifi-phy.cc',
20
        'yans-wifi-channel.cc',
21
        'wifi-mac-header.cc',
22
        'wifi-mac-trailer.cc',
23
        'mac-low.cc',
24
        'wifi-mac-queue.cc',
25
        'mac-tx-middle.cc',
26
        'mac-rx-middle.cc',
27
        'dca-txop.cc',
28
        'supported-rates.cc',
29
        'capability-information.cc',
30
        'status-code.cc',
31
        'mgt-headers.cc',
32
        'random-stream.cc',
33
        'dcf-manager.cc',
34
        'dcf-manager-test.cc',
35
        'wifi-mac.cc',
36
        'wifi-remote-station-manager.cc',
37
        'adhoc-wifi-mac.cc',
38
        'nqap-wifi-mac.cc',
39
        'nqsta-wifi-mac.cc',
40
        'wifi-net-device.cc',
41
        'arf-wifi-manager.cc',
42
        'aarf-wifi-manager.cc',
43
        'ideal-wifi-manager.cc',
44
        'amrr-wifi-manager.cc',
45
        'onoe-wifi-manager.cc',
46
        'rraa-wifi-manager.cc',
47
        'aarfcd-wifi-manager.cc',
48
        'cara-wifi-manager.cc',
49
        'constant-rate-wifi-manager.cc',
50
        'wifi-test.cc',
51
        'qos-tag.cc',
52
        'qos-utils.cc',
53
        'qadhoc-wifi-mac.cc',
54
        'qap-wifi-mac.cc',
55
        'qsta-wifi-mac.cc',
56
        'edca-txop-n.cc',
57
        'msdu-aggregator.cc',
58
        'amsdu-subframe-header.cc',
59
        'msdu-standard-aggregator.cc',
60
        'minstrel-wifi-manager.cc',
61
        'dcf.cc',
62
        ]
63
    headers = bld.new_task_gen('ns3header')
64
    headers.module = 'wifi'
65
    headers.source = [
66
        'propagation-delay-model.h',
67
        'propagation-loss-model.h',
68
        'jakes-propagation-loss-model.h',
69
        'wifi-net-device.h',
70
        'wifi-channel.h',
71
        'wifi-mode.h',
72
        'ssid.h',
73
        'wifi-preamble.h',
74
	'wifi-phy-standard.h',
75
        'yans-wifi-phy.h',
76
        'yans-wifi-channel.h',
77
        'wifi-phy.h',
78
        'interference-helper.h',
79
        'wifi-remote-station-manager.h',
80
        'arf-wifi-manager.h',
81
        'aarf-wifi-manager.h',
82
        'constant-rate-wifi-manager.h',
83
        'ideal-wifi-manager.h',
84
        'amrr-wifi-manager.h',
85
        'onoe-wifi-manager.h',
86
        'rraa-wifi-manager.h',
87
        'wifi-mac.h',
88
        'adhoc-wifi-mac.h',
89
        'nqsta-wifi-mac.h',
90
        'nqap-wifi-mac.h',
91
        'wifi-phy.h',
92
        'supported-rates.h',
93
        'error-rate-model.h',
94
        'yans-error-rate-model.h',
95
        'dca-txop.h',
96
        'wifi-mac-header.h',
97
        'qadhoc-wifi-mac.h',
98
        'qap-wifi-mac.h',
99
        'qsta-wifi-mac.h',
100
        'qos-utils.h',
101
        'edca-txop-n.h',
102
        'msdu-aggregator.h',
103
        'amsdu-subframe-header.h',
104
        'qos-tag.h',
105
        'mgt-headers.h',
106
        'status-code.h',
107
        'capability-information.h',
108
        'dcf-manager.h',
109
        'mac-rx-middle.h', 
110
        'mac-low.h',
111
        'minstrel-wifi-manager.h',
112
        'dcf.h',
113
        ]
114
115
    if bld.env['ENABLE_GSL']:
116
        obj.uselib = 'GSL GSLCBLAS M'
117
118
    obj = bld.create_ns3_program('wifi-phy-test',
119
        ['core', 'simulator', 'mobility', 'node', 'wifi'])
120
    obj.source = 'wifi-phy-test.cc'
121
122
(-)a/src/devices/wifi/yans-wifi-phy.cc (-1 / +1 lines)
 Lines 726-732    Link Here 
726
{
726
{
727
  NS_ASSERT (m_txPowerBaseDbm <= m_txPowerEndDbm);
727
  NS_ASSERT (m_txPowerBaseDbm <= m_txPowerEndDbm);
728
  NS_ASSERT (m_nTxPower > 0);
728
  NS_ASSERT (m_nTxPower > 0);
729
  double dbm = m_txPowerBaseDbm + power * (m_txPowerEndDbm - m_txPowerBaseDbm) / m_nTxPower;
729
  double dbm = m_txPowerBaseDbm + power * (m_txPowerEndDbm - m_txPowerBaseDbm) / (m_nTxPower == 1 ? 1 : m_nTxPower - 1);
730
  return dbm;
730
  return dbm;
731
}
731
}
732
732
(-)a/src/devices/wifi/yans-wifi-phy.h (-193 / +1 lines)
 Lines 1-193    Link Here 
1
/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
1
/home/quincy/code/ns3/devices/wifi/yans-wifi-phy.h
2
/*
3
 * Copyright (c) 2005,2006 INRIA
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License version 2 as 
7
 * published by the Free Software Foundation;
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software
16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 *
18
 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19
 */
20
21
#ifndef YANS_WIFI_PHY_H
22
#define YANS_WIFI_PHY_H
23
24
#include <stdint.h>
25
#include "ns3/callback.h"
26
#include "ns3/event-id.h"
27
#include "ns3/packet.h"
28
#include "ns3/object.h"
29
#include "ns3/traced-callback.h"
30
#include "ns3/nstime.h"
31
#include "ns3/ptr.h"
32
#include "ns3/random-variable.h"
33
#include "wifi-phy.h"
34
#include "wifi-mode.h"
35
#include "wifi-preamble.h"
36
#include "wifi-phy-standard.h"
37
#include "interference-helper.h"
38
39
40
namespace ns3 {
41
42
class RandomUniform;
43
class RxEvent;
44
class YansWifiChannel;
45
class WifiPhyStateHelper;
46
47
48
/**
49
 * \brief 802.11 PHY layer model
50
 *
51
 * This PHY implements a model of 802.11a. The model
52
 * implemented here is based on the model described
53
 * in "Yet Another Network Simulator", 
54
 * (http://cutebugs.net/files/wns2-yans.pdf).
55
 *
56
 *
57
 * This PHY model depends on a channel loss and delay
58
 * model as provided by the ns3::PropagationLossModel
59
 * and ns3::PropagationDelayModel classes, both of which are
60
 * members of the ns3::YansWifiChannel class.
61
 */
62
class YansWifiPhy : public WifiPhy
63
{
64
public:
65
66
  static TypeId GetTypeId (void);
67
68
  YansWifiPhy ();
69
  virtual ~YansWifiPhy ();
70
71
  void SetChannel (Ptr<YansWifiChannel> channel);
72
  
73
  /** 
74
   * \brief Set channel number. 
75
   * 
76
   * Channel center frequency = Channel starting frequency + 5 MHz * (nch - 1)
77
   *
78
   * where Starting channel frequency is standard-dependent, see SetStandard()
79
   * as defined in IEEE 802.11-2007 17.3.8.3.2.
80
   *
81
   * YansWifiPhy can switch among different channels. Basically, YansWifiPhy 
82
   * has a private attribute m_channelNumber that identifies the channel the 
83
   * PHY operates on. Channel switching cannot interrupt an ongoing transmission.
84
   * When PHY is in TX state, the channel switching is postponed until the end
85
   * of the current transmission. When the PHY is in RX state, the channel 
86
   * switching causes the drop of the synchronized packet. 
87
   */ 
88
  void SetChannelNumber (uint16_t id);
89
  /// Return current channel number, see SetChannelNumber()
90
  uint16_t GetChannelNumber () const;
91
  /// Return current center channel frequency in MHz, see SetСhannelNumber()
92
  double GetChannelFrequencyMhz() const;
93
  
94
  void StartReceivePacket (Ptr<Packet> packet,
95
                           double rxPowerDbm,
96
                           WifiMode mode,
97
                           WifiPreamble preamble);
98
99
  void SetRxNoiseFigure (double noiseFigureDb);
100
  void SetTxPowerStart (double start);
101
  void SetTxPowerEnd (double end);
102
  void SetNTxPower (uint32_t n);
103
  void SetTxGain (double gain);
104
  void SetRxGain (double gain);
105
  void SetEdThreshold (double threshold);
106
  void SetCcaMode1Threshold (double threshold);
107
  void SetErrorRateModel (Ptr<ErrorRateModel> rate);
108
  void SetDevice (Ptr<Object> device);
109
  void SetMobility (Ptr<Object> mobility);
110
  double GetRxNoiseFigure (void) const;
111
  double GetTxGain (void) const;
112
  double GetRxGain (void) const;
113
  double GetEdThreshold (void) const;
114
  double GetCcaMode1Threshold (void) const;
115
  Ptr<ErrorRateModel> GetErrorRateModel (void) const;
116
  Ptr<Object> GetDevice (void) const;
117
  Ptr<Object> GetMobility (void);
118
  
119
  
120
121
122
  virtual double GetTxPowerStart (void) const;
123
  virtual double GetTxPowerEnd (void) const;
124
  virtual uint32_t GetNTxPower (void) const;
125
  virtual void SetReceiveOkCallback (WifiPhy::RxOkCallback callback);
126
  virtual void SetReceiveErrorCallback (WifiPhy::RxErrorCallback callback);
127
  virtual void SendPacket (Ptr<const Packet> packet, WifiMode mode, enum WifiPreamble preamble, uint8_t txPowerLevel);
128
  virtual void RegisterListener (WifiPhyListener *listener);
129
  virtual bool IsStateCcaBusy (void);
130
  virtual bool IsStateIdle (void);
131
  virtual bool IsStateBusy (void);
132
  virtual bool IsStateRx (void);
133
  virtual bool IsStateTx (void);
134
  virtual bool IsStateSwitching (void); 
135
  virtual Time GetStateDuration (void);
136
  virtual Time GetDelayUntilIdle (void);
137
  virtual Time GetLastRxStartTime (void) const;
138
  virtual Time CalculateTxDuration (uint32_t size, WifiMode payloadMode, enum WifiPreamble preamble) const;
139
  virtual uint32_t GetNModes (void) const;
140
  virtual WifiMode GetMode (uint32_t mode) const;
141
  virtual double CalculateSnr (WifiMode txMode, double ber) const;
142
  virtual Ptr<WifiChannel> GetChannel (void) const;
143
  virtual void ConfigureStandard (enum WifiPhyStandard standard);
144
145
private:
146
  typedef std::vector<WifiMode> Modes;
147
148
private:
149
  YansWifiPhy (const YansWifiPhy &o);
150
  virtual void DoDispose (void);
151
  void Configure80211a (void);
152
  void Configure80211b (void);
153
  void Configure80211_10Mhz (void);
154
  void Configure80211_5Mhz ();
155
  void ConfigureHolland (void);
156
  void Configure80211p_CCH (void);
157
  void Configure80211p_SCH (void);
158
  double GetEdThresholdW (void) const;
159
  double DbmToW (double dbm) const;
160
  double DbToRatio (double db) const;
161
  double WToDbm (double w) const;
162
  double RatioToDb (double ratio) const;
163
  double GetPowerDbm (uint8_t power) const;
164
  void EndReceive (Ptr<Packet> packet, Ptr<InterferenceHelper::Event> event);
165
166
private:
167
  double   m_edThresholdW;
168
  double   m_ccaMode1ThresholdW;
169
  double   m_txGainDb;
170
  double   m_rxGainDb;
171
  double   m_txPowerBaseDbm;
172
  double   m_txPowerEndDbm;
173
  uint32_t m_nTxPower;
174
175
  Ptr<YansWifiChannel> m_channel;
176
  uint16_t m_channelNumber;
177
  Ptr<Object> m_device;
178
  Ptr<Object> m_mobility;
179
  Modes m_modes;
180
  EventId m_endRxEvent;
181
  UniformVariable m_random;
182
  /// Standard-dependent center frequency of 0-th channel, MHz 
183
  double m_channelStartingFrequency;
184
  Ptr<WifiPhyStateHelper> m_state;
185
  InterferenceHelper m_interference;
186
  Time m_channelSwitchDelay;
187
188
};
189
190
} // namespace ns3
191
192
193
#endif /* YANS_WIFI_PHY_H */
(-)a/src/helper/wscript (-124 / +1 lines)
 Lines 1-124    Link Here 
1
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
1
/home/quincy/code/ns3/helper/wscript
2
3
def build(bld):
4
    helper = bld.create_ns3_module('helper', ['internet-stack', 'wifi', 'point-to-point', 'csma', 'olsr', 'global-routing', 'onoff', 'packet-sink', 'udp-echo'])
5
    helper.source = [
6
        'node-container.cc',
7
        'net-device-container.cc',
8
        'wifi-helper.cc',
9
        'olsr-helper.cc',
10
        'point-to-point-helper.cc',
11
        'csma-helper.cc',
12
        'mobility-helper.cc',
13
        'ns2-mobility-helper.cc',
14
        'ipv4-address-helper.cc',
15
        'ipv4-static-routing-helper.cc',
16
        'internet-stack-helper.cc',
17
        'application-container.cc',
18
        'on-off-helper.cc',
19
        'packet-sink-helper.cc',
20
        'packet-socket-helper.cc',
21
        'ipv4-interface-container.cc',
22
        'udp-echo-helper.cc',
23
        'bridge-helper.cc',
24
        'yans-wifi-helper.cc',
25
        'v4ping-helper.cc',
26
        'nqos-wifi-mac-helper.cc',
27
        'qos-wifi-mac-helper.cc',
28
        'ipv4-nix-vector-helper.cc',
29
        'ipv4-global-routing-helper.cc',
30
        'ipv4-list-routing-helper.cc',
31
        'ipv4-routing-helper.cc',
32
        'aodv-helper.cc',
33
        'mesh-helper.cc',
34
        'dot11s-installer.cc',
35
        'flame-installer.cc',
36
        'athstats-helper.cc',
37
        'ipv6-address-helper.cc',
38
        'ipv6-interface-container.cc',
39
        'ipv6-static-routing-helper.cc',
40
        'ipv6-list-routing-helper.cc',
41
        'ipv6-routing-helper.cc',
42
        'ping6-helper.cc',
43
        'flow-monitor-helper.cc',
44
        'animation-interface.cc',
45
        'canvas-location.cc',
46
        'point-to-point-dumbbell-helper.cc',
47
        'point-to-point-grid-helper.cc',
48
        'point-to-point-star-helper.cc',
49
        'csma-star-helper.cc',
50
        'udp-client-server-helper.cc',
51
        ]
52
53
    headers = bld.new_task_gen('ns3header')
54
    headers.module = 'helper'
55
    headers.source = [
56
        'node-container.h',
57
        'net-device-container.h',
58
        'wifi-helper.h',
59
        'olsr-helper.h',
60
        'point-to-point-helper.h',
61
        'csma-helper.h',
62
        'mobility-helper.h',
63
        'ns2-mobility-helper.h',
64
        'ipv4-address-helper.h',
65
        'ipv4-static-routing-helper.h',
66
        'internet-stack-helper.h',
67
        'application-container.h',
68
        'on-off-helper.h',
69
        'packet-sink-helper.h',
70
        'packet-socket-helper.h',
71
        'ipv4-interface-container.h',
72
        'udp-echo-helper.h',
73
        'bridge-helper.h',
74
        'yans-wifi-helper.h',
75
        'v4ping-helper.h',
76
        'nqos-wifi-mac-helper.h',
77
        'qos-wifi-mac-helper.h',
78
        'ipv4-nix-vector-helper.h',
79
	'ipv4-global-routing-helper.h',
80
        'ipv4-list-routing-helper.h',
81
        'ipv4-routing-helper.h',
82
        'aodv-helper.h',
83
        'mesh-helper.h',
84
        'mesh-stack-installer.h',
85
        'dot11s-installer.h',
86
        'flame-installer.h',
87
        'athstats-helper.h',
88
        'ipv6-address-helper.h',
89
        'ipv6-interface-container.h',
90
        'ipv6-static-routing-helper.h',
91
        'ipv6-list-routing-helper.h',
92
        'ipv6-routing-helper.h',
93
        'ping6-helper.h',
94
        'flow-monitor-helper.h',
95
        'animation-interface.h',
96
        'canvas-location.h',
97
        'point-to-point-dumbbell-helper.h',
98
        'point-to-point-grid-helper.h',
99
        'point-to-point-star-helper.h',
100
        'csma-star-helper.h',
101
        'udp-client-server-helper.h',
102
        ]
103
104
    env = bld.env_of_name('default')
105
    if env['ENABLE_EMU']:
106
        helper.source.extend([
107
                'emu-helper.cc',
108
                ])
109
        headers.source.extend([
110
                'emu-helper.h',
111
                ])
112
    if env['ENABLE_TAP']:
113
        helper.source.extend([
114
                'tap-bridge-helper.cc',
115
                ])
116
        headers.source.extend([
117
                'tap-bridge-helper.h',
118
                ])
119
120
def configure(conf):
121
    conf.check(header_name='sys/socket.h', define_name='HAVE_SYS_SOCKET_H')
122
    conf.check(header_name='netinet/in.h', define_name='HAVE_NETINET_IN_H')
123
    conf.write_config_header('ns3/net-anim-config.h', top=True)
124
(-)a/src/helper/yans-wifi-helper.h (-346 / +1 lines)
 Lines 1-346    Link Here 
1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
1
/home/quincy/code/ns3/helper/yans-wifi-helper.h
2
/*
3
 * Copyright (c) 2008 INRIA
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License version 2 as
7
 * published by the Free Software Foundation;
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software
16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 *
18
 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19
 */
20
#ifndef YANS_WIFI_HELPER_H
21
#define YANS_WIFI_HELPER_H
22
23
#include "wifi-helper.h"
24
#include "ns3/yans-wifi-channel.h"
25
26
namespace ns3 {
27
28
/**
29
 * \brief manage and create wifi channel objects for the yans model.
30
 *
31
 * The intent of this class is to make it easy to create a channel object
32
 * which implements the yans channel model. The yans channel model is described
33
 * in "Yet Another Network Simulator", http://cutebugs.net/files/wns2-yans.pdf
34
 */
35
class YansWifiChannelHelper
36
{
37
public:
38
  /**
39
   * Create a channel helper without any parameter set. The user must set
40
   * them all to be able to call Create later.
41
   */
42
  YansWifiChannelHelper ();
43
44
  /**
45
   * Create a channel helper in a default working state. By default, we create
46
   * a channel model with a propagation delay equal to a constant, the speed of light,
47
   * and a propagation loss based on a log distance model with a reference loss of 46.6777 dB
48
   * at reference distance of 1m.
49
   */
50
  static YansWifiChannelHelper Default (void);
51
52
  /**
53
   * \param name the name of the model to add
54
   * \param n0 the name of the attribute to set
55
   * \param v0 the value of the attribute to set
56
   * \param n1 the name of the attribute to set
57
   * \param v1 the value of the attribute to set
58
   * \param n2 the name of the attribute to set
59
   * \param v2 the value of the attribute to set
60
   * \param n3 the name of the attribute to set
61
   * \param v3 the value of the attribute to set
62
   * \param n4 the name of the attribute to set
63
   * \param v4 the value of the attribute to set
64
   * \param n5 the name of the attribute to set
65
   * \param v5 the value of the attribute to set
66
   * \param n6 the name of the attribute to set
67
   * \param v6 the value of the attribute to set
68
   * \param n7 the name of the attribute to set
69
   * \param v7 the value of the attribute to set
70
   *
71
   * Add a propagation loss model to the set of currently-configured loss models.
72
   * This method is additive to allow you to construct complex propagation loss models
73
   * such as a log distance + jakes model, etc.
74
   */
75
  void AddPropagationLoss (std::string name,
76
			   std::string n0 = "", const AttributeValue &v0 = EmptyAttributeValue (),
77
			   std::string n1 = "", const AttributeValue &v1 = EmptyAttributeValue (),
78
			   std::string n2 = "", const AttributeValue &v2 = EmptyAttributeValue (),
79
			   std::string n3 = "", const AttributeValue &v3 = EmptyAttributeValue (),
80
			   std::string n4 = "", const AttributeValue &v4 = EmptyAttributeValue (),
81
			   std::string n5 = "", const AttributeValue &v5 = EmptyAttributeValue (),
82
			   std::string n6 = "", const AttributeValue &v6 = EmptyAttributeValue (),
83
			   std::string n7 = "", const AttributeValue &v7 = EmptyAttributeValue ());
84
  /**
85
   * \param name the name of the model to set
86
   * \param n0 the name of the attribute to set
87
   * \param v0 the value of the attribute to set
88
   * \param n1 the name of the attribute to set
89
   * \param v1 the value of the attribute to set
90
   * \param n2 the name of the attribute to set
91
   * \param v2 the value of the attribute to set
92
   * \param n3 the name of the attribute to set
93
   * \param v3 the value of the attribute to set
94
   * \param n4 the name of the attribute to set
95
   * \param v4 the value of the attribute to set
96
   * \param n5 the name of the attribute to set
97
   * \param v5 the value of the attribute to set
98
   * \param n6 the name of the attribute to set
99
   * \param v6 the value of the attribute to set
100
   * \param n7 the name of the attribute to set
101
   * \param v7 the value of the attribute to set
102
   *
103
   * Configure a propagation delay for this channel.
104
   */
105
  void SetPropagationDelay (std::string name,
106
			    std::string n0 = "", const AttributeValue &v0 = EmptyAttributeValue (),
107
			    std::string n1 = "", const AttributeValue &v1 = EmptyAttributeValue (),
108
			    std::string n2 = "", const AttributeValue &v2 = EmptyAttributeValue (),
109
			    std::string n3 = "", const AttributeValue &v3 = EmptyAttributeValue (),
110
			    std::string n4 = "", const AttributeValue &v4 = EmptyAttributeValue (),
111
			    std::string n5 = "", const AttributeValue &v5 = EmptyAttributeValue (),
112
			    std::string n6 = "", const AttributeValue &v6 = EmptyAttributeValue (),
113
			    std::string n7 = "", const AttributeValue &v7 = EmptyAttributeValue ());
114
115
  /**
116
   * \returns a new channel
117
   *
118
   * Create a channel based on the configuration parameters set previously.
119
   */
120
  Ptr<YansWifiChannel> Create (void) const;
121
122
private:
123
  std::vector<ObjectFactory> m_propagationLoss;
124
  ObjectFactory m_propagationDelay;
125
};
126
127
/**
128
 * \brief Make it easy to create and manage PHY objects for the yans model.
129
 *
130
 * The yans PHY model is described in "Yet Another Network Simulator", 
131
 * http://cutebugs.net/files/wns2-yans.pdf
132
 *
133
 * The Pcap and ascii traces generated by the EnableAscii and EnablePcap methods defined
134
 * in this class correspond to PHY-level traces. 
135
 */
136
class YansWifiPhyHelper : public WifiPhyHelper
137
{
138
public:
139
  /**
140
   * Create a phy helper without any parameter set. The user must set
141
   * them all to be able to call Install later.
142
   */
143
  YansWifiPhyHelper ();
144
145
  /**
146
   * Create a phy helper in a default working state.
147
   */
148
  static YansWifiPhyHelper Default (void);
149
150
  /**
151
   * \param channel the channel to associate to this helper
152
   *
153
   * Every PHY created by a call to Install is associated to this channel.
154
   */
155
  void SetChannel (Ptr<YansWifiChannel> channel);
156
  /**
157
   * \param channelName The name of the channel to associate to this helper
158
   *
159
   * Every PHY created by a call to Install is associated to this channel.
160
   */
161
  void SetChannel (std::string channelName);
162
  /**
163
   * \param name the name of the attribute to set
164
   * \param v the value of the attribute
165
   *
166
   * Set an attribute of the underlying PHY object.
167
   */
168
  void Set (std::string name, const AttributeValue &v);
169
  /**
170
   * \param name the name of the error rate model to set.
171
   * \param n0 the name of the attribute to set
172
   * \param v0 the value of the attribute to set
173
   * \param n1 the name of the attribute to set
174
   * \param v1 the value of the attribute to set
175
   * \param n2 the name of the attribute to set
176
   * \param v2 the value of the attribute to set
177
   * \param n3 the name of the attribute to set
178
   * \param v3 the value of the attribute to set
179
   * \param n4 the name of the attribute to set
180
   * \param v4 the value of the attribute to set
181
   * \param n5 the name of the attribute to set
182
   * \param v5 the value of the attribute to set
183
   * \param n6 the name of the attribute to set
184
   * \param v6 the value of the attribute to set
185
   * \param n7 the name of the attribute to set
186
   * \param v7 the value of the attribute to set
187
   *
188
   * Set the error rate model and its attributes to use when Install is called.
189
   */
190
  void SetErrorRateModel (std::string name,
191
                          std::string n0 = "", const AttributeValue &v0 = EmptyAttributeValue (),
192
                          std::string n1 = "", const AttributeValue &v1 = EmptyAttributeValue (),
193
                          std::string n2 = "", const AttributeValue &v2 = EmptyAttributeValue (),
194
                          std::string n3 = "", const AttributeValue &v3 = EmptyAttributeValue (),
195
                          std::string n4 = "", const AttributeValue &v4 = EmptyAttributeValue (),
196
                          std::string n5 = "", const AttributeValue &v5 = EmptyAttributeValue (),
197
                          std::string n6 = "", const AttributeValue &v6 = EmptyAttributeValue (),
198
                          std::string n7 = "", const AttributeValue &v7 = EmptyAttributeValue ());
199
200
  /**
201
   * PCAP formats 
202
   * 
203
   */
204
  enum PcapFormat {   
205
    PCAP_FORMAT_80211          = 1,
206
    PCAP_FORMAT_80211_PRISM    = 2,
207
    PCAP_FORMAT_80211_RADIOTAP = 3,
208
  };
209
  
210
  /** 
211
   * Set the format of PCAP traces to be used. This function has to be
212
   * called before EnablePcap(), so that the header of the pcap file
213
   * can be written correctly.
214
   *
215
   * In madwifi, this corresponds to setting
216
   * /proc/sys/net/ath0/dev_type to a particular value. See
217
   * http://madwifi-project.org/wiki/UserDocs/MonitorModeInterface for
218
   * more information.
219
   * 
220
   * @param format the PcapFormat to be used
221
   */
222
  void SetPcapFormat (enum PcapFormat format);
223
224
  /**
225
   * \param filename filename prefix to use for pcap files.
226
   * \param nodeid the id of the node to generate pcap output for.
227
   * \param deviceid the id of the device to generate pcap output for.
228
   *
229
   * Generate a pcap file which contains the link-level data observed
230
   * by the specified deviceid within the specified nodeid. The pcap
231
   * data is stored in the file prefix-nodeid-deviceid.pcap. By
232
   * default, no PHY layer information is provided. An optional header
233
   * with PHY layer information, such as the radiotap or the prism
234
   * header, can be used by invoking SetPcapFormat().
235
   *
236
   * This method should be invoked after the network topology has 
237
   * been fully constructed.
238
   */
239
  void EnablePcap (std::string filename, uint32_t nodeid, uint32_t deviceid);
240
241
  /**
242
   * \param filename filename prefix to use for pcap files.
243
   * \param nd Net device on which you want to enable tracing.
244
   *
245
   * Enable pcap output on each input device which is of the
246
   * ns3::WifiNetDevice type.
247
   */
248
   void EnablePcap (std::string filename, Ptr<NetDevice> nd);
249
250
  /**
251
   * \param filename filename prefix to use for pcap files.
252
   * \param ndName Name of net device on which you want to enable tracing.
253
   *
254
   * Enable pcap output on each input device which is of the
255
   * ns3::WifiNetDevice type.
256
   */
257
   void EnablePcap (std::string filename, std::string ndName);
258
259
  /**
260
   * \param filename filename prefix to use for pcap files.
261
   * \param d container of devices of type ns3::WifiNetDevice
262
   *
263
   * Enable pcap output on each input device which is of the
264
   * ns3::WifiNetDevice type.
265
   */
266
   void EnablePcap (std::string filename, NetDeviceContainer d);
267
268
  /**
269
   * \param filename filename prefix to use for pcap files.
270
   * \param n container of nodes.
271
   *
272
   * Enable pcap output on each device which is of the
273
   * ns3::WifiNetDevice type and which is located in one of the 
274
   * input nodes.
275
   */
276
   void EnablePcap (std::string filename, NodeContainer n);
277
278
  /**
279
   * \param filename filename prefix to use for pcap files.
280
   *
281
   * Enable pcap output on each device which is of the
282
   * ns3::WifiNetDevice type
283
   */
284
   void EnablePcapAll (std::string filename);
285
286
  /**
287
   * \param os output stream
288
   * \param nodeid the id of the node to generate ascii output for.
289
   * \param deviceid the id of the device to generate ascii output for.
290
   *
291
   * Enable ascii output on the specified deviceid within the
292
   * specified nodeid if it is of type ns3::WifiNetDevice and dump 
293
   * that to the specified stdc++ output stream.
294
   */
295
  static void EnableAscii (std::ostream &os, uint32_t nodeid, uint32_t deviceid);
296
297
  /**
298
   * \param os output stream
299
   * \param d device container
300
   *
301
   * Enable ascii output on each device which is of the
302
   * ns3::WifiNetDevice type and which is located in the input
303
   * device container and dump that to the specified
304
   * stdc++ output stream.
305
   */
306
  static void EnableAscii (std::ostream &os, NetDeviceContainer d);
307
308
  /**
309
   * \param os output stream
310
   * \param n node container
311
   *
312
   * Enable ascii output on each device which is of the
313
   * ns3::WifiNetDevice type and which is located in one
314
   * of the input node and dump that to the specified
315
   * stdc++ output stream.
316
   */
317
  static void EnableAscii (std::ostream &os, NodeContainer n);
318
319
  /**
320
   * \param os output stream
321
   *
322
   * Enable ascii output on each device which is of the
323
   * ns3::WifiNetDevice type and dump that to the specified
324
   * stdc++ output stream.
325
   */
326
  static void EnableAsciiAll (std::ostream &os);
327
328
private:
329
  /**
330
   * \param node the node on which we wish to create a wifi PHY
331
   * \param device the device within which this PHY will be created
332
   * \returns a newly-created PHY object.
333
   *
334
   * This method implements the pure virtual method defined in \ref ns3::WifiPhyHelper.
335
   */
336
  virtual Ptr<WifiPhy> Create (Ptr<Node> node, Ptr<WifiNetDevice> device) const;
337
338
  ObjectFactory m_phy;
339
  ObjectFactory m_errorRateModel;
340
  Ptr<YansWifiChannel> m_channel;
341
  enum PcapFormat m_pcapFormat;
342
};
343
344
} // namespace ns3
345
346
#endif /* YANS_WIFI_HELPER_H */
(-)a/src/node/packet-socket.cc (-460 / +1 lines)
 Lines 1-460    Link Here 
1
/* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
1
/home/quincy/code/ns3/node/packet-socket.cc
2
/*
3
 * Copyright (c) 2007 Emmanuelle Laprise, INRIA
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License version 2 as
7
 * published by the Free Software Foundation;
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software
16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 *
18
 * Authors: Emmanuelle Laprise <emmanuelle.laprise@bluekazoo.ca>
19
 *          Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
20
 */
21
22
#include "packet-socket.h"
23
#include "packet-socket-address.h"
24
#include "ns3/log.h"
25
#include "ns3/node.h"
26
#include "ns3/packet.h"
27
#include "ns3/uinteger.h"
28
#include "ns3/trace-source-accessor.h"
29
30
#include <algorithm>
31
32
NS_LOG_COMPONENT_DEFINE ("PacketSocket");
33
34
namespace ns3 {
35
36
TypeId
37
PacketSocket::GetTypeId (void)
38
{
39
  static TypeId tid = TypeId ("ns3::PacketSocket")
40
    .SetParent<Socket> ()
41
    .AddConstructor<PacketSocket> ()
42
    .AddTraceSource ("Drop", "Drop packet due to receive buffer overflow",
43
                     MakeTraceSourceAccessor (&PacketSocket::m_dropTrace))
44
    .AddAttribute ("RcvBufSize",
45
                   "PacketSocket maximum receive buffer size (bytes)",
46
                   UintegerValue (0xffffffffl),
47
                   MakeUintegerAccessor (&PacketSocket::m_rcvBufSize),
48
                   MakeUintegerChecker<uint32_t> ())
49
    ;
50
  return tid;
51
}
52
53
PacketSocket::PacketSocket () : m_rxAvailable (0)
54
{
55
  NS_LOG_FUNCTION (this);
56
  m_state = STATE_OPEN;
57
  m_shutdownSend = false;
58
  m_shutdownRecv = false;
59
  m_errno = ERROR_NOTERROR;
60
  m_isSingleDevice = false;
61
  m_device = 0;
62
}
63
64
void 
65
PacketSocket::SetNode (Ptr<Node> node)
66
{
67
  NS_LOG_FUNCTION (this << node);
68
  m_node = node;
69
}
70
71
PacketSocket::~PacketSocket ()
72
{
73
  NS_LOG_FUNCTION (this);
74
}
75
76
void 
77
PacketSocket::DoDispose (void)
78
{
79
  NS_LOG_FUNCTION (this);
80
  m_device = 0;
81
}
82
83
enum Socket::SocketErrno
84
PacketSocket::GetErrno (void) const
85
{
86
  NS_LOG_FUNCTION (this);
87
  return m_errno;
88
}
89
90
Ptr<Node>
91
PacketSocket::GetNode (void) const
92
{
93
  NS_LOG_FUNCTION (this);
94
  return m_node;
95
}
96
97
int
98
PacketSocket::Bind (void)
99
{
100
  NS_LOG_FUNCTION (this);
101
  PacketSocketAddress address;
102
  address.SetProtocol (0);
103
  address.SetAllDevices ();
104
  return DoBind (address);
105
}
106
107
int
108
PacketSocket::Bind (const Address &address)
109
{ 
110
  NS_LOG_FUNCTION (this << address);
111
  if (!PacketSocketAddress::IsMatchingType (address))
112
    {
113
      m_errno = ERROR_INVAL;
114
      return -1;
115
    }
116
  PacketSocketAddress ad = PacketSocketAddress::ConvertFrom (address);
117
  return DoBind (ad);
118
}
119
120
int
121
PacketSocket::DoBind (const PacketSocketAddress &address)
122
{
123
  NS_LOG_FUNCTION (this << address);
124
  if (m_state == STATE_BOUND ||
125
      m_state == STATE_CONNECTED)
126
    {
127
      m_errno = ERROR_INVAL;
128
      return -1;
129
    }
130
  if (m_state == STATE_CLOSED)
131
    {
132
      m_errno = ERROR_BADF;
133
      return -1;
134
    }
135
  Ptr<NetDevice> dev ;
136
  if (address.IsSingleDevice ())
137
    {
138
      dev = m_node->GetDevice (address.GetSingleDevice ());
139
    }
140
  else
141
    {
142
      dev = 0;
143
    }
144
  m_node->RegisterProtocolHandler (MakeCallback (&PacketSocket::ForwardUp, this),
145
                                   address.GetProtocol (), dev);
146
  m_state = STATE_BOUND;
147
  m_protocol = address.GetProtocol ();
148
  m_isSingleDevice = address.IsSingleDevice ();
149
  m_device = address.GetSingleDevice ();
150
  return 0;
151
}
152
153
int
154
PacketSocket::ShutdownSend (void)
155
{
156
  NS_LOG_FUNCTION (this);
157
  if (m_state == STATE_CLOSED)
158
    {
159
      m_errno = ERROR_BADF;
160
      return -1;
161
    }
162
  m_shutdownSend = true;
163
  return 0;
164
}
165
166
int
167
PacketSocket::ShutdownRecv (void)
168
{
169
  NS_LOG_FUNCTION (this);
170
  if (m_state == STATE_CLOSED)
171
    {
172
      m_errno = ERROR_BADF;
173
      return -1;
174
    }
175
  m_shutdownRecv = true;
176
  return 0;
177
}
178
179
int
180
PacketSocket::Close(void)
181
{
182
  NS_LOG_FUNCTION (this);
183
  if (m_state == STATE_CLOSED)
184
    {
185
      m_errno = ERROR_BADF;
186
      return -1;
187
    }
188
  m_state = STATE_CLOSED;
189
  m_shutdownSend = true;
190
  m_shutdownRecv = true;
191
  return 0;
192
}
193
194
int
195
PacketSocket::Connect(const Address &ad)
196
{
197
  NS_LOG_FUNCTION (this << ad);
198
  PacketSocketAddress address;
199
  if (m_state == STATE_CLOSED)
200
    {
201
      m_errno = ERROR_BADF;
202
      goto error;
203
    }
204
  if (m_state == STATE_OPEN)
205
    {
206
      // connect should happen _after_ bind.
207
      m_errno = ERROR_INVAL; // generic error condition.
208
      goto error;
209
    }
210
  if (m_state == STATE_CONNECTED)
211
    {
212
      m_errno = ERROR_ISCONN;
213
      goto error;
214
    }
215
  if (!PacketSocketAddress::IsMatchingType (ad))
216
    {
217
      m_errno = ERROR_AFNOSUPPORT;
218
      goto error;
219
    }
220
  m_destAddr = ad;
221
  m_state = STATE_CONNECTED;
222
  NotifyConnectionSucceeded ();
223
  return 0;
224
 error:
225
  NotifyConnectionFailed ();
226
  return -1;
227
}
228
int 
229
PacketSocket::Listen(void)
230
{
231
  m_errno = Socket::ERROR_OPNOTSUPP;
232
  return -1;
233
}
234
235
int
236
PacketSocket::Send (Ptr<Packet> p, uint32_t flags)
237
{
238
  NS_LOG_FUNCTION (this << p << flags);
239
  if (m_state == STATE_OPEN ||
240
      m_state == STATE_BOUND)
241
    {
242
      m_errno = ERROR_NOTCONN;
243
      return -1;
244
    }
245
  return SendTo (p, flags, m_destAddr);
246
}
247
248
uint32_t
249
PacketSocket::GetMinMtu (PacketSocketAddress ad) const
250
{
251
  if (ad.IsSingleDevice ())
252
    {
253
      Ptr<NetDevice> device = m_node->GetDevice (ad.GetSingleDevice ());
254
      return device->GetMtu ();
255
    }
256
  else
257
    {
258
      uint32_t minMtu = 0xffff;
259
      for (uint32_t i = 0; i < m_node->GetNDevices (); i++)
260
        {
261
          Ptr<NetDevice> device = m_node->GetDevice (i);
262
          minMtu = std::min (minMtu, (uint32_t)device->GetMtu ());
263
        }
264
      return minMtu;
265
    }
266
}
267
268
uint32_t 
269
PacketSocket::GetTxAvailable (void) const
270
{
271
  if (m_state == STATE_CONNECTED)
272
    {
273
      PacketSocketAddress ad = PacketSocketAddress::ConvertFrom (m_destAddr);      
274
      return GetMinMtu (ad);
275
    }
276
  // If we are not connected, we return a 'safe' value by default.
277
  return 0xffff;
278
}
279
280
int
281
PacketSocket::SendTo (Ptr<Packet> p, uint32_t flags, const Address &address)
282
{
283
  NS_LOG_FUNCTION (this << p << flags << address);
284
  PacketSocketAddress ad;
285
  if (m_state == STATE_CLOSED)
286
    {
287
      NS_LOG_LOGIC ("ERROR_BADF");
288
      m_errno = ERROR_BADF;
289
      return -1;
290
    }
291
  if (m_shutdownSend)
292
    {
293
      NS_LOG_LOGIC ("ERROR_SHUTDOWN");
294
      m_errno = ERROR_SHUTDOWN;
295
      return -1;
296
    }
297
  if (!PacketSocketAddress::IsMatchingType (address))
298
    {
299
      NS_LOG_LOGIC ("ERROR_AFNOSUPPORT");
300
      m_errno = ERROR_AFNOSUPPORT;
301
      return -1;
302
    }
303
  ad = PacketSocketAddress::ConvertFrom (address);
304
  if (p->GetSize () > GetMinMtu (ad))
305
    {
306
      m_errno = ERROR_MSGSIZE;
307
      return -1;
308
    }
309
  
310
  bool error = false;
311
  Address dest = ad.GetPhysicalAddress ();
312
  if (ad.IsSingleDevice ())
313
    {
314
      Ptr<NetDevice> device = m_node->GetDevice (ad.GetSingleDevice ());
315
      if (!device->Send (p, dest, ad.GetProtocol ()))
316
        {
317
          NS_LOG_LOGIC ("error: NetDevice::Send error");
318
          error = true;
319
        }
320
    }
321
  else
322
    {
323
      for (uint32_t i = 0; i < m_node->GetNDevices (); i++)
324
        {
325
          Ptr<NetDevice> device = m_node->GetDevice (i);
326
          if (!device->Send (p, dest, ad.GetProtocol ()))
327
            {
328
              NS_LOG_LOGIC ("error: NetDevice::Send error");
329
              error = true;
330
            }
331
        }
332
    }
333
  if (!error)
334
    {
335
      NotifyDataSent (p->GetSize ());
336
      NotifySend (GetTxAvailable ());
337
    }
338
339
  if (error)
340
    {
341
      NS_LOG_LOGIC ("ERROR_INVAL 2");
342
      m_errno = ERROR_INVAL;
343
      return -1;
344
    }
345
  else
346
    {
347
      return 0;
348
    }
349
}
350
351
void 
352
PacketSocket::ForwardUp (Ptr<NetDevice> device, Ptr<const Packet> packet, 
353
                         uint16_t protocol, const Address &from,
354
                         const Address &to, NetDevice::PacketType packetType)
355
{
356
  NS_LOG_FUNCTION (this << device << packet << protocol << from << to << packetType);
357
  if (m_shutdownRecv)
358
    {
359
      return;
360
    }
361
362
363
  PacketSocketAddress address;
364
  address.SetPhysicalAddress (from);
365
  address.SetSingleDevice (device->GetIfIndex ());
366
  address.SetProtocol (protocol);
367
368
  if ((m_rxAvailable + packet->GetSize ()) <= m_rcvBufSize)
369
    {
370
      Ptr<Packet> copy = packet->Copy ();
371
      SocketAddressTag tag;
372
      tag.SetAddress (address);
373
      copy->AddPacketTag (tag);
374
      m_deliveryQueue.push (copy);
375
      m_rxAvailable += packet->GetSize ();
376
      NS_LOG_LOGIC ("UID is " << packet->GetUid() << " PacketSocket " << this);
377
      NotifyDataRecv ();
378
    }
379
  else
380
    {
381
      // In general, this case should not occur unless the
382
      // receiving application reads data from this socket slowly
383
      // in comparison to the arrival rate
384
      //
385
      // drop and trace packet
386
      NS_LOG_WARN ("No receive buffer space available.  Drop.");
387
      m_dropTrace (packet);
388
    }
389
}
390
391
uint32_t
392
PacketSocket::GetRxAvailable (void) const
393
{
394
  NS_LOG_FUNCTION (this);
395
  // We separately maintain this state to avoid walking the queue 
396
  // every time this might be called
397
  return m_rxAvailable;
398
}
399
400
Ptr<Packet> 
401
PacketSocket::Recv (uint32_t maxSize, uint32_t flags)
402
{
403
  NS_LOG_FUNCTION (this << maxSize << flags);
404
  if (m_deliveryQueue.empty() )
405
    {
406
      return 0;
407
    }
408
  Ptr<Packet> p = m_deliveryQueue.front ();
409
  if (p->GetSize () <= maxSize)
410
    {
411
      m_deliveryQueue.pop ();
412
      m_rxAvailable -= p->GetSize ();
413
    }
414
  else
415
    {
416
      p = 0;
417
    }
418
  return p;
419
}
420
421
Ptr<Packet>
422
PacketSocket::RecvFrom (uint32_t maxSize, uint32_t flags, Address &fromAddress)
423
{
424
  NS_LOG_FUNCTION (this << maxSize << flags << fromAddress);
425
  Ptr<Packet> packet = Recv (maxSize, flags);
426
  if (packet != 0)
427
    {
428
      SocketAddressTag tag;
429
      bool found;
430
      found = packet->PeekPacketTag (tag);
431
      NS_ASSERT (found);
432
      fromAddress = tag.GetAddress ();
433
    }
434
  return packet;
435
}
436
437
int
438
PacketSocket::GetSockName (Address &address) const
439
{
440
  NS_LOG_FUNCTION (this << address);
441
  PacketSocketAddress ad = PacketSocketAddress::ConvertFrom(address);
442
  
443
  ad.SetProtocol (m_protocol);
444
  if (m_isSingleDevice)
445
    {
446
      Ptr<NetDevice> device = m_node->GetDevice (ad.GetSingleDevice ());
447
      ad.SetPhysicalAddress(device->GetAddress());      
448
      ad.SetSingleDevice (m_device);
449
    }
450
  else
451
    {
452
      ad.SetPhysicalAddress(Address());   
453
      ad.SetAllDevices ();
454
    }  
455
  address = ad;
456
  
457
  return 0;
458
}
459
460
}//namespace ns3
(-)a/src/simulator/wscript (-120 / +1 lines)
 Lines 1-120    Link Here 
1
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
1
/home/quincy/code/ns3/simulator/wscript
2
import sys
3
4
import Options
5
6
7
def set_options(opt):
8
    opt.add_option('--high-precision-as-double',
9
                   help=('Whether to use a double floating point'
10
                         ' type for high precision time values'
11
                         ' WARNING: this option only has effect '
12
                         'with the configure command.'),
13
                   action="store_true", default=False,
14
                   dest='high_precision_as_double')
15
16
17
def configure(conf):
18
    if Options.options.high_precision_as_double:
19
        conf.define('USE_HIGH_PRECISION_DOUBLE', 1)
20
        conf.env['USE_HIGH_PRECISION_DOUBLE'] = 1
21
        highprec = 'long double'
22
    else:
23
        conf.env['USE_HIGH_PRECISION_DOUBLE'] = 0
24
        highprec = '128-bit integer'
25
26
    conf.check_message_custom('high precision time', 'implementation', highprec)
27
28
    conf.check(header_name='stdint.h', define_name='HAVE_STDINT_H')
29
30
    conf.check(header_name='inttypes.h', define_name='HAVE_INTTYPES_H')
31
32
    conf.check(header_name='sys/inttypes.h', define_name='HAVE_SYS_INT_TYPES_H')
33
34
    conf.write_config_header('ns3/simulator-config.h', top=True)
35
36
    if not conf.check(lib='rt', uselib='RT', define_name='HAVE_RT'):
37
        conf.report_optional_feature("RealTime", "Real Time Simulator",
38
                                     False, "librt is not available")
39
    else:
40
        conf.report_optional_feature("RealTime", "Real Time Simulator",
41
                                     conf.env['ENABLE_THREADING'],
42
                                     "threading not enabled")
43
        conf.env["ENABLE_REAL_TIME"] = conf.env['ENABLE_THREADING']
44
45
46
def build(bld):
47
    sim = bld.create_ns3_module('simulator', ['core'])
48
    sim.source = [
49
        'high-precision.cc',
50
        'time.cc',
51
        'event-id.cc',
52
        'scheduler.cc',
53
        'list-scheduler.cc',
54
        'map-scheduler.cc',
55
        'heap-scheduler.cc',
56
        'calendar-scheduler.cc',
57
        'ns2-calendar-scheduler.cc',
58
        'event-impl.cc',
59
        'simulator.cc',
60
        'default-simulator-impl.cc',
61
        'timer.cc',
62
        'watchdog.cc',
63
        'synchronizer.cc',
64
        'make-event.cc',
65
        ]
66
67
    headers = bld.new_task_gen('ns3header')
68
    headers.module = 'simulator'
69
    headers.source = [
70
        'high-precision.h',
71
        'nstime.h',
72
        'event-id.h',
73
        'event-impl.h',
74
        'simulator.h',
75
        'simulator-impl.h',
76
        'default-simulator-impl.h',
77
        'scheduler.h',
78
        'list-scheduler.h',
79
        'map-scheduler.h',
80
        'heap-scheduler.h',
81
        'calendar-scheduler.h',
82
        'ns2-calendar-scheduler.h',
83
        'simulation-singleton.h',
84
        'timer.h',
85
        'timer-impl.h',
86
        'watchdog.h',
87
        'synchronizer.h',
88
        'make-event.h',
89
        ]
90
91
    env = bld.env_of_name('default')
92
    if env['USE_HIGH_PRECISION_DOUBLE']:
93
        sim.source.extend([
94
            'high-precision-double.cc',
95
            ])
96
        headers.source.extend([
97
            'high-precision-double.h',
98
            ])
99
    else:
100
        sim.source.extend([
101
            'high-precision-128.cc',
102
            'cairo-wideint.c',
103
            ])
104
        headers.source.extend([
105
            'high-precision-128.h',
106
            'cairo-wideint-private.h',
107
            ])
108
109
    if env['ENABLE_REAL_TIME']:
110
        headers.source.extend([
111
                'realtime-simulator-impl.h',
112
                'wall-clock-synchronizer.h',
113
                ])
114
        sim.source.extend([
115
                'realtime-simulator-impl.cc',
116
                'wall-clock-synchronizer.cc',
117
                ])
118
        sim.uselib = 'RT'
119
120
(-)a/src/wscript (-253 / +1 lines)
 Lines 1-253    Link Here 
1
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
1
/home/quincy/code/ns3/wscript
2
3
import os, os.path
4
import shutil
5
import types
6
import warnings
7
8
import TaskGen
9
import Task
10
import Options
11
import Build
12
import Utils
13
14
all_modules = (
15
    'core',
16
    'common',
17
    'simulator',
18
    'contrib',
19
    'node',
20
    'internet-stack',
21
    'devices/point-to-point',
22
    'devices/csma',
23
    'devices/emu',
24
    'devices/bridge',
25
    'devices/tap-bridge',
26
    'devices/virtual-net-device',
27
    'applications/onoff',
28
    'applications/packet-sink',
29
    'applications/udp-echo',
30
    'routing/nix-vector-routing',
31
    'routing/olsr',
32
    'routing/global-routing',
33
    'routing/static-routing',
34
    'routing/list-routing',
35
    'routing/aodv',
36
    'mobility',
37
    'devices/wifi',
38
    'helper',
39
    'contrib/stats',
40
    'applications/v4ping',
41
    'devices/mesh',
42
    'devices/mesh/dot11s',
43
    'devices/mesh/flame',
44
    'applications/ping6',
45
    'applications/radvd',
46
    'test',
47
    'test/ns3tcp',
48
    'test/ns3wifi',
49
    'contrib/flow-monitor',
50
    'applications/udp-client-server',
51
    )
52
53
def set_options(opt):
54
    opt.sub_options('simulator')
55
56
    opt.add_option('--enable-rpath',
57
                   help=("Link programs with rpath"
58
                         " (normally not needed, see "
59
                         " --run and --shell; moreover, only works in some"
60
                         " specific platforms, such as Linux and Solaris)"),
61
                   action="store_true", dest='enable_rpath', default=False)
62
    
63
    opt.add_option('--enable-modules',
64
                   help=("Build only these modules (and dependencies)"),
65
                   dest='enable_modules')
66
67
def configure(conf):
68
    conf.sub_config('core')
69
    conf.sub_config('simulator')
70
    conf.sub_config('devices/emu')
71
    conf.sub_config('devices/tap-bridge')
72
    conf.sub_config('contrib')
73
    conf.sub_config('internet-stack')
74
    conf.sub_config('helper')
75
76
    blddir = os.path.abspath(os.path.join(conf.blddir, conf.env.variant()))
77
    conf.env.append_value('NS3_MODULE_PATH', blddir)
78
    if Options.options.enable_rpath:
79
        conf.env.append_value('RPATH', '-Wl,-rpath=%s' % (os.path.join(blddir),))
80
81
    ## Used to link the 'test-runner' program with all of ns-3 code
82
    conf.env['NS3_MODULES'] = ['ns3-' + module.split('/')[-1] for module in all_modules]
83
84
85
def create_ns3_module(bld, name, dependencies=()):
86
    module = bld.new_task_gen('cxx')
87
    module.name = 'ns3-' + name
88
    module.target = module.name
89
    module.add_objects = ['ns3-' + dep for dep in dependencies]
90
    module.module_deps = list(dependencies)
91
    if not module.env['ENABLE_STATIC_NS3']:
92
        module.env.append_value('CXXFLAGS', module.env['shlib_CXXFLAGS'])
93
    elif module.env['CXX_NAME'] in ['gcc', 'icc'] and \
94
            os.uname()[4] == 'x86_64' and \
95
            module.env['ENABLE_PYTHON_BINDINGS']:
96
        # enable that flag for static builds only on x86-64 platforms
97
        # when gcc is present and only when we want python bindings
98
        # (it's more efficient to not use this option if we can avoid it)
99
        module.env.append_value('CXXFLAGS', '-mcmodel=large')
100
        
101
    module.env.append_value('CXXDEFINES', "NS3_MODULE_COMPILATION")
102
    return module
103
104
def create_obj(bld, *args):
105
    warnings.warn("(in %s) Use bld.new_task_gen(...) now, instead of bld.create_obj(...)" % str(bld.path),
106
                  DeprecationWarning, stacklevel=2)
107
    return bld.new_task_gen(*args)
108
109
def build(bld):
110
    bld.create_ns3_module = types.MethodType(create_ns3_module, bld)
111
    bld.create_obj = types.MethodType(create_obj, bld)
112
    
113
    bld.add_subdirs(list(all_modules))
114
115
    for module in all_modules:
116
        modheader = bld.new_task_gen('ns3moduleheader')
117
        modheader.module = module.split('/')[-1]
118
119
120
class ns3header_taskgen(TaskGen.task_gen):
121
    """A set of NS-3 header files"""
122
    COLOR = 'BLUE'
123
    def __init__(self, *args, **kwargs):
124
        super(ns3header_taskgen, self).__init__(*args, **kwargs)
125
        self.install_path = None
126
        self.sub_dir = None # if not None, header files will be published as ns3/sub_dir/file.h
127
        self.module = None # module name
128
129
    def apply(self):
130
        if self.module is None:
131
            raise Utils.WafError("'module' missing on ns3headers object %s" % self)
132
        ns3_dir_node = self.bld.path.find_dir("ns3")
133
        if self.sub_dir is not None:
134
            ns3_dir_node = ns3_dir_node.find_dir(self.sub_dir)
135
        for filename in self.to_list(self.source):
136
            src_node = self.path.find_resource(filename)
137
            if src_node is None:
138
                raise Utils.WafError("source ns3 header file %s not found" % (filename,))
139
            dst_node = ns3_dir_node.find_or_declare(os.path.basename(filename))
140
            assert dst_node is not None
141
            task = self.create_task('ns3header', self.env)
142
            task.set_inputs([src_node])
143
            task.set_outputs([dst_node])
144
145
class ns3header_task(Task.Task):
146
    before = 'cc cxx gen_ns3_module_header_task'
147
    color = 'BLUE'
148
    def run(self):
149
        assert len(self.inputs) == len(self.outputs)
150
        inputs = [node.srcpath(self.env) for node in self.inputs]
151
        outputs = [node.bldpath(self.env) for node in self.outputs]
152
        for src, dst in zip(inputs, outputs):
153
            try:
154
                os.chmod(dst, 0600)
155
            except OSError:
156
                pass
157
            shutil.copy2(src, dst)
158
            ## make the headers in builddir read-only, to prevent
159
            ## accidental modification
160
            os.chmod(dst, 0400)
161
        return 0
162
163
164
165
class gen_ns3_module_header_task(Task.Task):
166
    before = 'cc cxx'
167
    after = 'ns3header_task'
168
    color = 'BLUE'
169
    def run(self):
170
        assert len(self.outputs) == 1
171
        header_files = [os.path.basename(node.abspath(self.env)) for node in self.inputs]
172
        outfile = file(self.outputs[0].bldpath(self.env), "w")
173
        header_files.sort()
174
175
        print >> outfile, """
176
#ifdef NS3_MODULE_COMPILATION
177
# error "Do not include ns3 module aggregator headers from other modules; these are meant only for end user scripts."
178
#endif
179
180
#ifndef NS3_MODULE_%s
181
    """ % (self.module.upper().replace('-', '_'),)
182
183
    #     if self.module_deps:
184
    #         print >> outfile, "// Module dependencies:"
185
    #     for dep in self.module_deps:
186
    #         print >> outfile, "#include \"%s-module.h\"" % dep
187
188
        print >> outfile
189
        print >> outfile, "// Module headers:"
190
        for header in header_files:
191
            print >> outfile, "#include \"%s\"" % (header,)
192
193
        print >> outfile, "#endif"
194
195
        outfile.close()
196
        return 0
197
198
    def sig_explicit_deps(self):
199
        m = Utils.md5()
200
        m.update('\n'.join([node.abspath(self.env) for node in self.inputs]))
201
        return m.digest()
202
203
    def unique_id(self):
204
        try:
205
            return self.uid
206
        except AttributeError:
207
            "this is not a real hot zone, but we want to avoid surprizes here"
208
            m = Utils.md5()
209
            m.update("ns-3-module-header-%s" % self.module)
210
            self.uid = m.digest()
211
            return self.uid
212
213
214
class ns3moduleheader_taskgen(TaskGen.task_gen):
215
    """
216
    Generates a 'ns3/foo-module.h' header file that includes all
217
    public ns3 headers of a certain module.
218
    """
219
    COLOR = 'BLUE'
220
    def __init__(self, *args, **kwargs):
221
        super(ns3moduleheader_taskgen, self).__init__(*args, **kwargs)
222
223
    def apply(self):
224
        ## get all of the ns3 headers
225
        ns3_dir_node = self.bld.path.find_dir("ns3")
226
        all_headers_inputs = []
227
        found_the_module = False
228
        for ns3headers in self.bld.all_task_gen:
229
            if isinstance(ns3headers, ns3header_taskgen):
230
                if ns3headers.module != self.module:
231
                    continue
232
                found_the_module = True
233
                for source in ns3headers.to_list(ns3headers.source):
234
                    source = os.path.basename(source)
235
                    node = ns3_dir_node.find_or_declare(os.path.basename(source))
236
                    if node is None:
237
                        fatal("missing header file %s" % (source,))
238
                    all_headers_inputs.append(node)
239
        if not found_the_module:
240
            raise Utils.WscriptError("error finding headers for module %s" % self.module)
241
        if not all_headers_inputs:
242
            return
243
        module_obj = self.bld.name_to_obj("ns3-" + self.module, self.env)
244
        assert module_obj is not None
245
        all_headers_outputs = [ns3_dir_node.find_or_declare("%s-module.h" % self.module)]
246
        task = self.create_task('gen_ns3_module_header', self.env)
247
        task.set_inputs(all_headers_inputs)
248
        task.set_outputs(all_headers_outputs)
249
        task.module = self.module
250
        task.module_deps = module_obj.module_deps
251
252
    def install(self):
253
        pass

Return to bug 844