~ubuntu-branches/ubuntu/quantal/ns3/quantal

« back to all changes in this revision

Viewing changes to ns-3.12.1/src/wifi/model/dcf-manager.cc

  • Committer: Package Import Robot
  • Author(s): YunQiang Su, Aron Xu, YunQiang Su, Upstream
  • Date: 2012-01-06 00:35:42 UTC
  • mfrom: (10.1.5 sid)
  • Revision ID: package-import@ubuntu.com-20120106003542-vcn5g03mhapm991h
Tags: 3.13+dfsg-1
[ Aron Xu ]:
        add tag binary and binary-indep, 
  for not build doc when --binary-arch (Closes: #654493).
[ YunQiang Su ]
        add waf 1.5/1.6 source to debian directory, 
  and build waf from there (Closes: #642217).
[ Upstream ]
  Successfully link with --as-needed option (Closes: #642225).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
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/log.h"
23
 
#include "ns3/simulator.h"
24
 
#include <math.h>
25
 
 
26
 
#include "dcf-manager.h"
27
 
#include "wifi-phy.h"
28
 
#include "wifi-mac.h"
29
 
#include "mac-low.h"
30
 
 
31
 
NS_LOG_COMPONENT_DEFINE ("DcfManager");
32
 
 
33
 
#define MY_DEBUG(x) \
34
 
  NS_LOG_DEBUG (Simulator::Now () << " " << this << " " << x)
35
 
 
36
 
namespace ns3 {
37
 
 
38
 
/****************************************************************
39
 
 *      Implement the DCF state holder
40
 
 ****************************************************************/
41
 
 
42
 
DcfState::DcfState ()
43
 
  : m_backoffSlots (0),
44
 
    m_backoffStart (Seconds (0.0)),
45
 
    m_cwMin (0),
46
 
    m_cwMax (0),
47
 
    m_cw (0),
48
 
    m_accessRequested (false)
49
 
{
50
 
}
51
 
 
52
 
DcfState::~DcfState ()
53
 
{
54
 
}
55
 
 
56
 
void
57
 
DcfState::SetAifsn (uint32_t aifsn)
58
 
{
59
 
  m_aifsn = aifsn;
60
 
}
61
 
void
62
 
DcfState::SetCwMin (uint32_t minCw)
63
 
{
64
 
  m_cwMin = minCw;
65
 
  ResetCw ();
66
 
}
67
 
void
68
 
DcfState::SetCwMax (uint32_t maxCw)
69
 
{
70
 
  m_cwMax = maxCw;
71
 
  ResetCw ();
72
 
}
73
 
uint32_t
74
 
DcfState::GetAifsn (void) const
75
 
{
76
 
  return m_aifsn;
77
 
}
78
 
uint32_t
79
 
DcfState::GetCwMin (void) const
80
 
{
81
 
  return m_cwMin;
82
 
}
83
 
uint32_t
84
 
DcfState::GetCwMax (void) const
85
 
{
86
 
  return m_cwMax;
87
 
}
88
 
 
89
 
void
90
 
DcfState::ResetCw (void)
91
 
{
92
 
  m_cw = m_cwMin;
93
 
}
94
 
void
95
 
DcfState::UpdateFailedCw (void)
96
 
{
97
 
  // see 802.11-2007, section 9.9.1.5
98
 
  m_cw = std::min ( 2 * (m_cw + 1) - 1, m_cwMax);
99
 
}
100
 
void
101
 
DcfState::UpdateBackoffSlotsNow (uint32_t nSlots, Time backoffUpdateBound)
102
 
{
103
 
  m_backoffSlots -= nSlots;
104
 
  m_backoffStart = backoffUpdateBound;
105
 
  MY_DEBUG ("update slots=" << nSlots << " slots, backoff=" << m_backoffSlots);
106
 
}
107
 
 
108
 
void
109
 
DcfState::StartBackoffNow (uint32_t nSlots)
110
 
{
111
 
  NS_ASSERT (m_backoffSlots == 0);
112
 
  MY_DEBUG ("start backoff=" << nSlots << " slots");
113
 
  m_backoffSlots = nSlots;
114
 
  m_backoffStart = Simulator::Now ();
115
 
}
116
 
 
117
 
uint32_t
118
 
DcfState::GetCw (void) const
119
 
{
120
 
  return m_cw;
121
 
}
122
 
uint32_t
123
 
DcfState::GetBackoffSlots (void) const
124
 
{
125
 
  return m_backoffSlots;
126
 
}
127
 
Time
128
 
DcfState::GetBackoffStart (void) const
129
 
{
130
 
  return m_backoffStart;
131
 
}
132
 
bool
133
 
DcfState::IsAccessRequested (void) const
134
 
{
135
 
  return m_accessRequested;
136
 
}
137
 
void
138
 
DcfState::NotifyAccessRequested (void)
139
 
{
140
 
  m_accessRequested = true;
141
 
}
142
 
void
143
 
DcfState::NotifyAccessGranted (void)
144
 
{
145
 
  NS_ASSERT (m_accessRequested);
146
 
  m_accessRequested = false;
147
 
  DoNotifyAccessGranted ();
148
 
}
149
 
void
150
 
DcfState::NotifyCollision (void)
151
 
{
152
 
  DoNotifyCollision ();
153
 
}
154
 
void
155
 
DcfState::NotifyInternalCollision (void)
156
 
{
157
 
  DoNotifyInternalCollision ();
158
 
}
159
 
void
160
 
DcfState::NotifyChannelSwitching (void)
161
 
{
162
 
  DoNotifyChannelSwitching ();
163
 
}
164
 
 
165
 
 
166
 
/***************************************************************
167
 
 *         Listener for Nav events. Forwards to DcfManager
168
 
 ***************************************************************/
169
 
 
170
 
class LowDcfListener : public ns3::MacLowDcfListener
171
 
{
172
 
public:
173
 
  LowDcfListener (ns3::DcfManager *dcf)
174
 
    : m_dcf (dcf)
175
 
  {
176
 
  }
177
 
  virtual ~LowDcfListener ()
178
 
  {
179
 
  }
180
 
  virtual void NavStart (Time duration)
181
 
  {
182
 
    m_dcf->NotifyNavStartNow (duration);
183
 
  }
184
 
  virtual void NavReset (Time duration)
185
 
  {
186
 
    m_dcf->NotifyNavResetNow (duration);
187
 
  }
188
 
  virtual void AckTimeoutStart (Time duration)
189
 
  {
190
 
    m_dcf->NotifyAckTimeoutStartNow (duration);
191
 
  }
192
 
  virtual void AckTimeoutReset ()
193
 
  {
194
 
    m_dcf->NotifyAckTimeoutResetNow ();
195
 
  }
196
 
  virtual void CtsTimeoutStart (Time duration)
197
 
  {
198
 
    m_dcf->NotifyCtsTimeoutStartNow (duration);
199
 
  }
200
 
  virtual void CtsTimeoutReset ()
201
 
  {
202
 
    m_dcf->NotifyCtsTimeoutResetNow ();
203
 
  }
204
 
private:
205
 
  ns3::DcfManager *m_dcf;
206
 
};
207
 
 
208
 
/***************************************************************
209
 
 *         Listener for PHY events. Forwards to DcfManager
210
 
 ***************************************************************/
211
 
 
212
 
class PhyListener : public ns3::WifiPhyListener
213
 
{
214
 
public:
215
 
  PhyListener (ns3::DcfManager *dcf)
216
 
    : m_dcf (dcf)
217
 
  {
218
 
  }
219
 
  virtual ~PhyListener ()
220
 
  {
221
 
  }
222
 
  virtual void NotifyRxStart (Time duration)
223
 
  {
224
 
    m_dcf->NotifyRxStartNow (duration);
225
 
  }
226
 
  virtual void NotifyRxEndOk (void)
227
 
  {
228
 
    m_dcf->NotifyRxEndOkNow ();
229
 
  }
230
 
  virtual void NotifyRxEndError (void)
231
 
  {
232
 
    m_dcf->NotifyRxEndErrorNow ();
233
 
  }
234
 
  virtual void NotifyTxStart (Time duration)
235
 
  {
236
 
    m_dcf->NotifyTxStartNow (duration);
237
 
  }
238
 
  virtual void NotifyMaybeCcaBusyStart (Time duration)
239
 
  {
240
 
    m_dcf->NotifyMaybeCcaBusyStartNow (duration);
241
 
  }
242
 
  virtual void NotifySwitchingStart (Time duration)
243
 
  {
244
 
    m_dcf->NotifySwitchingStartNow (duration);
245
 
  }
246
 
private:
247
 
  ns3::DcfManager *m_dcf;
248
 
};
249
 
 
250
 
/****************************************************************
251
 
 *      Implement the DCF manager of all DCF state holders
252
 
 ****************************************************************/
253
 
 
254
 
DcfManager::DcfManager ()
255
 
  : m_lastAckTimeoutEnd (MicroSeconds (0)),
256
 
    m_lastCtsTimeoutEnd (MicroSeconds (0)),
257
 
    m_lastNavStart (MicroSeconds (0)),
258
 
    m_lastNavDuration (MicroSeconds (0)),
259
 
    m_lastRxStart (MicroSeconds (0)),
260
 
    m_lastRxDuration (MicroSeconds (0)),
261
 
    m_lastRxReceivedOk (true),
262
 
    m_lastRxEnd (MicroSeconds (0)),
263
 
    m_lastTxStart (MicroSeconds (0)),
264
 
    m_lastTxDuration (MicroSeconds (0)),
265
 
    m_lastBusyStart (MicroSeconds (0)),
266
 
    m_lastBusyDuration (MicroSeconds (0)),
267
 
    m_lastSwitchingStart (MicroSeconds (0)),
268
 
    m_lastSwitchingDuration (MicroSeconds (0)),
269
 
    m_rxing (false),
270
 
    m_slotTimeUs (0),
271
 
    m_sifs (Seconds (0.0)),
272
 
    m_phyListener (0),
273
 
    m_lowListener (0)
274
 
{
275
 
}
276
 
 
277
 
DcfManager::~DcfManager ()
278
 
{
279
 
  delete m_phyListener;
280
 
  delete m_lowListener;
281
 
  m_phyListener = 0;
282
 
  m_lowListener = 0;
283
 
}
284
 
 
285
 
void
286
 
DcfManager::SetupPhyListener (Ptr<WifiPhy> phy)
287
 
{
288
 
  m_phyListener = new PhyListener (this);
289
 
  phy->RegisterListener (m_phyListener);
290
 
}
291
 
void
292
 
DcfManager::SetupLowListener (Ptr<MacLow> low)
293
 
{
294
 
  m_lowListener = new LowDcfListener (this);
295
 
  low->RegisterDcfListener (m_lowListener);
296
 
}
297
 
 
298
 
void
299
 
DcfManager::SetSlot (Time slotTime)
300
 
{
301
 
  m_slotTimeUs = slotTime.GetMicroSeconds ();
302
 
}
303
 
void
304
 
DcfManager::SetSifs (Time sifs)
305
 
{
306
 
  m_sifs = sifs;
307
 
}
308
 
void
309
 
DcfManager::SetEifsNoDifs (Time eifsNoDifs)
310
 
{
311
 
  m_eifsNoDifs = eifsNoDifs;
312
 
}
313
 
Time
314
 
DcfManager::GetEifsNoDifs () const
315
 
{
316
 
  return m_eifsNoDifs;
317
 
}
318
 
 
319
 
void
320
 
DcfManager::Add (DcfState *dcf)
321
 
{
322
 
  m_states.push_back (dcf);
323
 
}
324
 
 
325
 
Time
326
 
DcfManager::MostRecent (Time a, Time b) const
327
 
{
328
 
  return Max (a, b);
329
 
}
330
 
Time
331
 
DcfManager::MostRecent (Time a, Time b, Time c) const
332
 
{
333
 
  Time retval;
334
 
  retval = Max (a, b);
335
 
  retval = Max (retval, c);
336
 
  return retval;
337
 
}
338
 
Time
339
 
DcfManager::MostRecent (Time a, Time b, Time c, Time d) const
340
 
{
341
 
  Time e = Max (a, b);
342
 
  Time f = Max (c, d);
343
 
  Time retval = Max (e, f);
344
 
  return retval;
345
 
}
346
 
Time
347
 
DcfManager::MostRecent (Time a, Time b, Time c, Time d, Time e, Time f) const
348
 
{
349
 
  Time g = Max (a, b);
350
 
  Time h = Max (c, d);
351
 
  Time i = Max (e, f);
352
 
  Time k = Max (g, h);
353
 
  Time retval = Max (k, i);
354
 
  return retval;
355
 
}
356
 
 
357
 
Time
358
 
DcfManager::MostRecent (Time a, Time b, Time c, Time d, Time e, Time f, Time g) const
359
 
{
360
 
  Time h = Max (a, b);
361
 
  Time i = Max (c, d);
362
 
  Time j = Max (e, f);
363
 
  Time k = Max (h, i);
364
 
  Time l = Max (j, g);
365
 
  Time retval = Max (k, l);
366
 
  return retval;
367
 
}
368
 
 
369
 
bool
370
 
DcfManager::IsBusy (void) const
371
 
{
372
 
  // PHY busy
373
 
  if (m_rxing)
374
 
    {
375
 
      return true;
376
 
    }
377
 
  Time lastTxEnd = m_lastTxStart + m_lastTxDuration;
378
 
  if (lastTxEnd > Simulator::Now ())
379
 
    {
380
 
      return true;
381
 
    }
382
 
  // NAV busy
383
 
  Time lastNavEnd = m_lastNavStart + m_lastNavDuration;
384
 
  if (lastNavEnd > Simulator::Now ())
385
 
    {
386
 
      return true;
387
 
    }
388
 
  return false;
389
 
}
390
 
 
391
 
 
392
 
void
393
 
DcfManager::RequestAccess (DcfState *state)
394
 
{
395
 
  UpdateBackoff ();
396
 
  NS_ASSERT (!state->IsAccessRequested ());
397
 
  state->NotifyAccessRequested ();
398
 
  /**
399
 
   * If there is a collision, generate a backoff
400
 
   * by notifying the collision to the user.
401
 
   */
402
 
  if (state->GetBackoffSlots () == 0
403
 
      && IsBusy ())
404
 
    {
405
 
      MY_DEBUG ("medium is busy: collision");
406
 
      /* someone else has accessed the medium.
407
 
       * generate a backoff.
408
 
       */
409
 
      state->NotifyCollision ();
410
 
    }
411
 
  DoGrantAccess ();
412
 
  DoRestartAccessTimeoutIfNeeded ();
413
 
}
414
 
 
415
 
void
416
 
DcfManager::DoGrantAccess (void)
417
 
{
418
 
  uint32_t k = 0;
419
 
  for (States::const_iterator i = m_states.begin (); i != m_states.end (); k++)
420
 
    {
421
 
      DcfState *state = *i;
422
 
      if (state->IsAccessRequested ()
423
 
          && GetBackoffEndFor (state) <= Simulator::Now () )
424
 
        {
425
 
          /**
426
 
           * This is the first dcf we find with an expired backoff and which
427
 
           * needs access to the medium. i.e., it has data to send.
428
 
           */
429
 
          MY_DEBUG ("dcf " << k << " needs access. backoff expired. access granted. slots=" << state->GetBackoffSlots ());
430
 
          i++; // go to the next item in the list.
431
 
          k++;
432
 
          std::vector<DcfState *> internalCollisionStates;
433
 
          for (States::const_iterator j = i; j != m_states.end (); j++, k++)
434
 
            {
435
 
              DcfState *otherState = *j;
436
 
              if (otherState->IsAccessRequested ()
437
 
                  && GetBackoffEndFor (otherState) <= Simulator::Now ())
438
 
                {
439
 
                  MY_DEBUG ("dcf " << k << " needs access. backoff expired. internal collision. slots=" <<
440
 
                            otherState->GetBackoffSlots ());
441
 
                  /**
442
 
                   * all other dcfs with a lower priority whose backoff
443
 
                   * has expired and which needed access to the medium
444
 
                   * must be notified that we did get an internal collision.
445
 
                   */
446
 
                  internalCollisionStates.push_back (otherState);
447
 
                }
448
 
            }
449
 
 
450
 
          /**
451
 
           * Now, we notify all of these changes in one go. It is necessary to
452
 
           * perform first the calculations of which states are colliding and then
453
 
           * only apply the changes because applying the changes through notification
454
 
           * could change the global state of the manager, and, thus, could change
455
 
           * the result of the calculations.
456
 
           */
457
 
          state->NotifyAccessGranted ();
458
 
          for (std::vector<DcfState *>::const_iterator k = internalCollisionStates.begin ();
459
 
               k != internalCollisionStates.end (); k++)
460
 
            {
461
 
              (*k)->NotifyInternalCollision ();
462
 
            }
463
 
          break;
464
 
        }
465
 
      i++;
466
 
    }
467
 
}
468
 
 
469
 
void
470
 
DcfManager::AccessTimeout (void)
471
 
{
472
 
  UpdateBackoff ();
473
 
  DoGrantAccess ();
474
 
  DoRestartAccessTimeoutIfNeeded ();
475
 
}
476
 
 
477
 
Time
478
 
DcfManager::GetAccessGrantStart (void) const
479
 
{
480
 
  Time rxAccessStart;
481
 
  if (!m_rxing)
482
 
    {
483
 
      rxAccessStart = m_lastRxEnd + m_sifs;
484
 
      if (!m_lastRxReceivedOk)
485
 
        {
486
 
          rxAccessStart += m_eifsNoDifs;
487
 
        }
488
 
    }
489
 
  else
490
 
    {
491
 
      rxAccessStart = m_lastRxStart + m_lastRxDuration + m_sifs;
492
 
    }
493
 
  Time busyAccessStart = m_lastBusyStart + m_lastBusyDuration + m_sifs;
494
 
  Time txAccessStart = m_lastTxStart + m_lastTxDuration + m_sifs;
495
 
  Time navAccessStart = m_lastNavStart + m_lastNavDuration + m_sifs;
496
 
  Time ackTimeoutAccessStart = m_lastAckTimeoutEnd + m_sifs;
497
 
  Time ctsTimeoutAccessStart = m_lastCtsTimeoutEnd + m_sifs;
498
 
  Time switchingAccessStart = m_lastSwitchingStart + m_lastSwitchingDuration + m_sifs;
499
 
  Time accessGrantedStart = MostRecent (rxAccessStart,
500
 
                                        busyAccessStart,
501
 
                                        txAccessStart,
502
 
                                        navAccessStart,
503
 
                                        ackTimeoutAccessStart,
504
 
                                        ctsTimeoutAccessStart,
505
 
                                        switchingAccessStart
506
 
                                        );
507
 
  NS_LOG_INFO ("access grant start=" << accessGrantedStart <<
508
 
               ", rx access start=" << rxAccessStart <<
509
 
               ", busy access start=" << busyAccessStart <<
510
 
               ", tx access start=" << txAccessStart <<
511
 
               ", nav access start=" << navAccessStart);
512
 
  return accessGrantedStart;
513
 
}
514
 
 
515
 
Time
516
 
DcfManager::GetBackoffStartFor (DcfState *state)
517
 
{
518
 
  Time mostRecentEvent = MostRecent (state->GetBackoffStart (),
519
 
                                     GetAccessGrantStart () + MicroSeconds (state->GetAifsn () * m_slotTimeUs));
520
 
 
521
 
  return mostRecentEvent;
522
 
}
523
 
 
524
 
Time
525
 
DcfManager::GetBackoffEndFor (DcfState *state)
526
 
{
527
 
  return GetBackoffStartFor (state) + MicroSeconds (state->GetBackoffSlots () * m_slotTimeUs);
528
 
}
529
 
 
530
 
void
531
 
DcfManager::UpdateBackoff (void)
532
 
{
533
 
  uint32_t k = 0;
534
 
  for (States::const_iterator i = m_states.begin (); i != m_states.end (); i++, k++)
535
 
    {
536
 
      DcfState *state = *i;
537
 
 
538
 
      Time backoffStart = GetBackoffStartFor (state);
539
 
      if (backoffStart <= Simulator::Now ())
540
 
        {
541
 
          uint32_t nus = (Simulator::Now () - backoffStart).GetMicroSeconds ();
542
 
          uint32_t nIntSlots = nus / m_slotTimeUs;
543
 
          uint32_t n = std::min (nIntSlots, state->GetBackoffSlots ());
544
 
          MY_DEBUG ("dcf " << k << " dec backoff slots=" << n);
545
 
          Time backoffUpdateBound = backoffStart + MicroSeconds (n * m_slotTimeUs);
546
 
          state->UpdateBackoffSlotsNow (n, backoffUpdateBound);
547
 
        }
548
 
    }
549
 
}
550
 
 
551
 
void
552
 
DcfManager::DoRestartAccessTimeoutIfNeeded (void)
553
 
{
554
 
  /**
555
 
   * Is there a DcfState which needs to access the medium, and,
556
 
   * if there is one, how many slots for AIFS+backoff does it require ?
557
 
   */
558
 
  bool accessTimeoutNeeded = false;
559
 
  Time expectedBackoffEnd = Simulator::GetMaximumSimulationTime ();
560
 
  for (States::const_iterator i = m_states.begin (); i != m_states.end (); i++)
561
 
    {
562
 
      DcfState *state = *i;
563
 
      if (state->IsAccessRequested ())
564
 
        {
565
 
          Time tmp = GetBackoffEndFor (state);
566
 
          if (tmp > Simulator::Now ())
567
 
            {
568
 
              accessTimeoutNeeded = true;
569
 
              expectedBackoffEnd = std::min (expectedBackoffEnd, tmp);
570
 
            }
571
 
        }
572
 
    }
573
 
  if (accessTimeoutNeeded)
574
 
    {
575
 
      MY_DEBUG ("expected backoff end=" << expectedBackoffEnd);
576
 
      Time expectedBackoffDelay = expectedBackoffEnd - Simulator::Now ();
577
 
      if (m_accessTimeout.IsRunning ()
578
 
          && Simulator::GetDelayLeft (m_accessTimeout) > expectedBackoffDelay)
579
 
        {
580
 
          m_accessTimeout.Cancel ();
581
 
        }
582
 
      if (m_accessTimeout.IsExpired ())
583
 
        {
584
 
          m_accessTimeout = Simulator::Schedule (expectedBackoffDelay,
585
 
                                                 &DcfManager::AccessTimeout, this);
586
 
        }
587
 
    }
588
 
}
589
 
 
590
 
void
591
 
DcfManager::NotifyRxStartNow (Time duration)
592
 
{
593
 
  MY_DEBUG ("rx start for=" << duration);
594
 
  UpdateBackoff ();
595
 
  m_lastRxStart = Simulator::Now ();
596
 
  m_lastRxDuration = duration;
597
 
  m_rxing = true;
598
 
}
599
 
void
600
 
DcfManager::NotifyRxEndOkNow (void)
601
 
{
602
 
  MY_DEBUG ("rx end ok");
603
 
  m_lastRxEnd = Simulator::Now ();
604
 
  m_lastRxReceivedOk = true;
605
 
  m_rxing = false;
606
 
}
607
 
void
608
 
DcfManager::NotifyRxEndErrorNow (void)
609
 
{
610
 
  MY_DEBUG ("rx end error");
611
 
  m_lastRxEnd = Simulator::Now ();
612
 
  m_lastRxReceivedOk = false;
613
 
  m_rxing = false;
614
 
}
615
 
void
616
 
DcfManager::NotifyTxStartNow (Time duration)
617
 
{
618
 
  if (m_rxing)
619
 
    {
620
 
      //this may be caused only if PHY has started to receive a packet
621
 
      //inside SIFS, so, we check that lastRxStart was maximum a SIFS
622
 
      //ago
623
 
      NS_ASSERT (Simulator::Now () - m_lastRxStart <= m_sifs);
624
 
      m_lastRxEnd = Simulator::Now ();
625
 
      m_lastRxDuration = m_lastRxEnd - m_lastRxStart;
626
 
      m_lastRxReceivedOk = true;
627
 
      m_rxing = false;
628
 
    }
629
 
  MY_DEBUG ("tx start for " << duration);
630
 
  UpdateBackoff ();
631
 
  m_lastTxStart = Simulator::Now ();
632
 
  m_lastTxDuration = duration;
633
 
}
634
 
void
635
 
DcfManager::NotifyMaybeCcaBusyStartNow (Time duration)
636
 
{
637
 
  MY_DEBUG ("busy start for " << duration);
638
 
  UpdateBackoff ();
639
 
  m_lastBusyStart = Simulator::Now ();
640
 
  m_lastBusyDuration = duration;
641
 
}
642
 
 
643
 
 
644
 
void
645
 
DcfManager::NotifySwitchingStartNow (Time duration)
646
 
{
647
 
  Time now = Simulator::Now ();
648
 
  NS_ASSERT (m_lastTxStart + m_lastTxDuration <= now);
649
 
  NS_ASSERT (m_lastSwitchingStart + m_lastSwitchingDuration <= now);
650
 
 
651
 
  if (m_rxing)
652
 
    {
653
 
      // channel switching during packet reception
654
 
      m_lastRxEnd = Simulator::Now ();
655
 
      m_lastRxDuration = m_lastRxEnd - m_lastRxStart;
656
 
      m_lastRxReceivedOk = true;
657
 
      m_rxing = false;
658
 
    }
659
 
  if (m_lastNavStart + m_lastNavDuration > now)
660
 
    {
661
 
      m_lastNavDuration = now - m_lastNavStart;
662
 
    }
663
 
  if (m_lastBusyStart + m_lastBusyDuration > now)
664
 
    {
665
 
      m_lastBusyDuration = now - m_lastBusyStart;
666
 
    }
667
 
  if (m_lastAckTimeoutEnd > now)
668
 
    {
669
 
      m_lastAckTimeoutEnd = now;
670
 
    }
671
 
  if (m_lastCtsTimeoutEnd > now)
672
 
    {
673
 
      m_lastCtsTimeoutEnd = now;
674
 
    }
675
 
 
676
 
  // Cancel timeout
677
 
  if (m_accessTimeout.IsRunning ())
678
 
    {
679
 
      m_accessTimeout.Cancel ();
680
 
    }
681
 
 
682
 
  // Reset backoffs
683
 
  for (States::iterator i = m_states.begin (); i != m_states.end (); i++)
684
 
    {
685
 
      DcfState *state = *i;
686
 
      uint32_t remainingSlots = state->GetBackoffSlots ();
687
 
      if (remainingSlots > 0)
688
 
        {
689
 
          state->UpdateBackoffSlotsNow (remainingSlots, now);
690
 
          NS_ASSERT (state->GetBackoffSlots () == 0);
691
 
        }
692
 
      state->ResetCw ();
693
 
      state->m_accessRequested = false;
694
 
      state->NotifyChannelSwitching ();
695
 
    }
696
 
 
697
 
  MY_DEBUG ("switching start for " << duration);
698
 
  m_lastSwitchingStart = Simulator::Now ();
699
 
  m_lastSwitchingDuration = duration;
700
 
 
701
 
}
702
 
 
703
 
void
704
 
DcfManager::NotifyNavResetNow (Time duration)
705
 
{
706
 
  MY_DEBUG ("nav reset for=" << duration);
707
 
  UpdateBackoff ();
708
 
  m_lastNavStart = Simulator::Now ();
709
 
  m_lastNavDuration = duration;
710
 
  UpdateBackoff ();
711
 
  /**
712
 
   * If the nav reset indicates an end-of-nav which is earlier
713
 
   * than the previous end-of-nav, the expected end of backoff
714
 
   * might be later than previously thought so, we might need
715
 
   * to restart a new access timeout.
716
 
   */
717
 
  DoRestartAccessTimeoutIfNeeded ();
718
 
}
719
 
void
720
 
DcfManager::NotifyNavStartNow (Time duration)
721
 
{
722
 
  NS_ASSERT (m_lastNavStart < Simulator::Now ());
723
 
  MY_DEBUG ("nav start for=" << duration);
724
 
  UpdateBackoff ();
725
 
  Time newNavEnd = Simulator::Now () + duration;
726
 
  Time lastNavEnd = m_lastNavStart + m_lastNavDuration;
727
 
  if (newNavEnd > lastNavEnd)
728
 
    {
729
 
      m_lastNavStart = Simulator::Now ();
730
 
      m_lastNavDuration = duration;
731
 
    }
732
 
}
733
 
void
734
 
DcfManager::NotifyAckTimeoutStartNow (Time duration)
735
 
{
736
 
  NS_ASSERT (m_lastAckTimeoutEnd < Simulator::Now ());
737
 
  m_lastAckTimeoutEnd = Simulator::Now () + duration;
738
 
}
739
 
void
740
 
DcfManager::NotifyAckTimeoutResetNow ()
741
 
{
742
 
  m_lastAckTimeoutEnd = Simulator::Now ();
743
 
  DoRestartAccessTimeoutIfNeeded ();
744
 
}
745
 
void
746
 
DcfManager::NotifyCtsTimeoutStartNow (Time duration)
747
 
{
748
 
  m_lastCtsTimeoutEnd = Simulator::Now () + duration;
749
 
}
750
 
void
751
 
DcfManager::NotifyCtsTimeoutResetNow ()
752
 
{
753
 
  m_lastCtsTimeoutEnd = Simulator::Now ();
754
 
  DoRestartAccessTimeoutIfNeeded ();
755
 
}
756
 
} // namespace ns3