A Discrete-Event Network Simulator
Home
Tutorials ▼
English
Portuguese
Docs ▼
Wiki
Manual
Models
Develop ▼
API
Bugs
API
Main Page
Related Pages
Modules
Namespaces
Classes
Files
File List
File Members
All
Classes
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Properties
Friends
Macros
Groups
Pages
dca-txop.cc
Go to the documentation of this file.
1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2
/*
3
* Copyright (c) 2005 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/log.h"
24
#include "ns3/simulator.h"
25
#include "ns3/node.h"
26
#include "ns3/uinteger.h"
27
#include "ns3/pointer.h"
28
29
#include "
dca-txop.h
"
30
#include "
dcf-manager.h
"
31
#include "
mac-low.h
"
32
#include "
wifi-mac-queue.h
"
33
#include "
mac-tx-middle.h
"
34
#include "
wifi-mac-trailer.h
"
35
#include "
wifi-mac.h
"
36
#include "
random-stream.h
"
37
38
NS_LOG_COMPONENT_DEFINE
(
"DcaTxop"
);
39
40
#undef NS_LOG_APPEND_CONTEXT
41
#define NS_LOG_APPEND_CONTEXT if (m_low != 0) { std::clog << "[mac=" << m_low->GetAddress () << "] "; }
42
43
namespace
ns3 {
44
45
class
DcaTxop::Dcf
:
public
DcfState
46
{
47
public
:
48
Dcf
(
DcaTxop
* txop)
49
:
m_txop
(txop)
50
{
51
}
52
private
:
53
virtual
void
DoNotifyAccessGranted
(
void
)
54
{
55
m_txop
->
NotifyAccessGranted
();
56
}
57
virtual
void
DoNotifyInternalCollision
(
void
)
58
{
59
m_txop
->
NotifyInternalCollision
();
60
}
61
virtual
void
DoNotifyCollision
(
void
)
62
{
63
m_txop
->
NotifyCollision
();
64
}
65
virtual
void
DoNotifyChannelSwitching
(
void
)
66
{
67
m_txop
->
NotifyChannelSwitching
();
68
}
69
DcaTxop
*
m_txop
;
70
};
71
72
class
DcaTxop::TransmissionListener
:
public
MacLowTransmissionListener
73
{
74
public
:
75
TransmissionListener
(
DcaTxop
* txop)
76
:
MacLowTransmissionListener
(),
77
m_txop
(txop) {
78
}
79
80
virtual
~TransmissionListener
() {}
81
82
virtual
void
GotCts
(
double
snr,
WifiMode
txMode)
83
{
84
m_txop
->
GotCts
(snr, txMode);
85
}
86
virtual
void
MissedCts
(
void
)
87
{
88
m_txop
->
MissedCts
();
89
}
90
virtual
void
GotAck
(
double
snr,
WifiMode
txMode)
91
{
92
m_txop
->
GotAck
(snr, txMode);
93
}
94
virtual
void
MissedAck
(
void
)
95
{
96
m_txop
->
MissedAck
();
97
}
98
virtual
void
StartNext
(
void
)
99
{
100
m_txop
->
StartNext
();
101
}
102
virtual
void
Cancel
(
void
)
103
{
104
m_txop
->
Cancel
();
105
}
106
virtual
void
EndTxNoAck
(
void
)
107
{
108
m_txop
->
EndTxNoAck
();
109
}
110
111
private
:
112
DcaTxop
*
m_txop
;
113
};
114
115
NS_OBJECT_ENSURE_REGISTERED
(
DcaTxop
);
116
117
TypeId
118
DcaTxop::GetTypeId
(
void
)
119
{
120
static
TypeId
tid =
TypeId
(
"ns3::DcaTxop"
)
121
.
SetParent
(
ns3::Dcf::GetTypeId
())
122
.
AddConstructor
<
DcaTxop
> ()
123
.AddAttribute (
"Queue"
,
"The WifiMacQueue object"
,
124
PointerValue
(),
125
MakePointerAccessor (&
DcaTxop::GetQueue
),
126
MakePointerChecker<WifiMacQueue> ())
127
;
128
return
tid;
129
}
130
131
DcaTxop::DcaTxop
()
132
: m_manager (0),
133
m_currentPacket (0)
134
{
135
NS_LOG_FUNCTION
(
this
);
136
m_transmissionListener
=
new
DcaTxop::TransmissionListener
(
this
);
137
m_dcf
=
new
DcaTxop::Dcf
(
this
);
138
m_queue
= CreateObject<WifiMacQueue> ();
139
m_rng
=
new
RealRandomStream
();
140
m_txMiddle
=
new
MacTxMiddle
();
141
}
142
143
DcaTxop::~DcaTxop
()
144
{
145
NS_LOG_FUNCTION
(
this
);
146
}
147
148
void
149
DcaTxop::DoDispose
(
void
)
150
{
151
NS_LOG_FUNCTION
(
this
);
152
m_queue
= 0;
153
m_low
= 0;
154
m_stationManager
= 0;
155
delete
m_transmissionListener
;
156
delete
m_dcf
;
157
delete
m_rng
;
158
delete
m_txMiddle
;
159
m_transmissionListener
= 0;
160
m_dcf
= 0;
161
m_rng
= 0;
162
m_txMiddle
= 0;
163
}
164
165
void
166
DcaTxop::SetManager
(
DcfManager
*manager)
167
{
168
NS_LOG_FUNCTION
(
this
<< manager);
169
m_manager
= manager;
170
m_manager
->
Add
(
m_dcf
);
171
}
172
173
void
174
DcaTxop::SetLow
(
Ptr<MacLow>
low)
175
{
176
NS_LOG_FUNCTION
(
this
<< low);
177
m_low
= low;
178
}
179
void
180
DcaTxop::SetWifiRemoteStationManager
(
Ptr<WifiRemoteStationManager>
remoteManager)
181
{
182
NS_LOG_FUNCTION
(
this
<< remoteManager);
183
m_stationManager
= remoteManager;
184
}
185
void
186
DcaTxop::SetTxOkCallback
(
TxOk
callback)
187
{
188
NS_LOG_FUNCTION
(
this
<< &callback);
189
m_txOkCallback
= callback;
190
}
191
void
192
DcaTxop::SetTxFailedCallback
(
TxFailed
callback)
193
{
194
NS_LOG_FUNCTION
(
this
<< &callback);
195
m_txFailedCallback
= callback;
196
}
197
198
Ptr<WifiMacQueue >
199
DcaTxop::GetQueue
()
const
200
{
201
NS_LOG_FUNCTION
(
this
);
202
return
m_queue
;
203
}
204
205
void
206
DcaTxop::SetMinCw
(uint32_t minCw)
207
{
208
NS_LOG_FUNCTION
(
this
<< minCw);
209
m_dcf
->
SetCwMin
(minCw);
210
}
211
void
212
DcaTxop::SetMaxCw
(uint32_t maxCw)
213
{
214
NS_LOG_FUNCTION
(
this
<< maxCw);
215
m_dcf
->
SetCwMax
(maxCw);
216
}
217
void
218
DcaTxop::SetAifsn
(uint32_t aifsn)
219
{
220
NS_LOG_FUNCTION
(
this
<< aifsn);
221
m_dcf
->
SetAifsn
(aifsn);
222
}
223
uint32_t
224
DcaTxop::GetMinCw
(
void
)
const
225
{
226
NS_LOG_FUNCTION
(
this
);
227
return
m_dcf
->
GetCwMin
();
228
}
229
uint32_t
230
DcaTxop::GetMaxCw
(
void
)
const
231
{
232
NS_LOG_FUNCTION
(
this
);
233
return
m_dcf
->
GetCwMax
();
234
}
235
uint32_t
236
DcaTxop::GetAifsn
(
void
)
const
237
{
238
NS_LOG_FUNCTION
(
this
);
239
return
m_dcf
->
GetAifsn
();
240
}
241
242
void
243
DcaTxop::Queue
(
Ptr<const Packet>
packet,
const
WifiMacHeader
&hdr)
244
{
245
NS_LOG_FUNCTION
(
this
<< packet << &hdr);
246
WifiMacTrailer
fcs;
247
uint32_t fullPacketSize = hdr.
GetSerializedSize
() + packet->
GetSize
() + fcs.
GetSerializedSize
();
248
m_stationManager
->
PrepareForQueue
(hdr.
GetAddr1
(), &hdr,
249
packet, fullPacketSize);
250
m_queue
->
Enqueue
(packet, hdr);
251
StartAccessIfNeeded
();
252
}
253
254
int64_t
255
DcaTxop::AssignStreams
(int64_t stream)
256
{
257
NS_LOG_FUNCTION
(
this
<< stream);
258
m_rng
->
AssignStreams
(stream);
259
return
1;
260
}
261
262
void
263
DcaTxop::RestartAccessIfNeeded
(
void
)
264
{
265
NS_LOG_FUNCTION
(
this
);
266
if
((
m_currentPacket
!= 0
267
|| !
m_queue
->
IsEmpty
())
268
&& !
m_dcf
->
IsAccessRequested
())
269
{
270
m_manager
->
RequestAccess
(
m_dcf
);
271
}
272
}
273
274
void
275
DcaTxop::StartAccessIfNeeded
(
void
)
276
{
277
NS_LOG_FUNCTION
(
this
);
278
if
(
m_currentPacket
== 0
279
&& !
m_queue
->
IsEmpty
()
280
&& !
m_dcf
->
IsAccessRequested
())
281
{
282
m_manager
->
RequestAccess
(
m_dcf
);
283
}
284
}
285
286
287
Ptr<MacLow>
288
DcaTxop::Low
(
void
)
289
{
290
NS_LOG_FUNCTION
(
this
);
291
return
m_low
;
292
}
293
294
bool
295
DcaTxop::NeedRts
(
Ptr<const Packet>
packet,
const
WifiMacHeader
*header)
296
{
297
NS_LOG_FUNCTION
(
this
<< packet << header);
298
return
m_stationManager
->
NeedRts
(header->
GetAddr1
(), header,
299
packet);
300
}
301
302
void
303
DcaTxop::DoInitialize
()
304
{
305
NS_LOG_FUNCTION
(
this
);
306
m_dcf
->
ResetCw
();
307
m_dcf
->
StartBackoffNow
(
m_rng
->
GetNext
(0,
m_dcf
->
GetCw
()));
308
ns3::Dcf::DoInitialize
();
309
}
310
bool
311
DcaTxop::NeedRtsRetransmission
(
void
)
312
{
313
NS_LOG_FUNCTION
(
this
);
314
return
m_stationManager
->
NeedRtsRetransmission
(
m_currentHdr
.
GetAddr1
(), &
m_currentHdr
,
315
m_currentPacket
);
316
}
317
318
bool
319
DcaTxop::NeedDataRetransmission
(
void
)
320
{
321
NS_LOG_FUNCTION
(
this
);
322
return
m_stationManager
->
NeedDataRetransmission
(
m_currentHdr
.
GetAddr1
(), &
m_currentHdr
,
323
m_currentPacket
);
324
}
325
bool
326
DcaTxop::NeedFragmentation
(
void
)
327
{
328
NS_LOG_FUNCTION
(
this
);
329
return
m_stationManager
->
NeedFragmentation
(
m_currentHdr
.
GetAddr1
(), &
m_currentHdr
,
330
m_currentPacket
);
331
}
332
333
void
334
DcaTxop::NextFragment
(
void
)
335
{
336
NS_LOG_FUNCTION
(
this
);
337
m_fragmentNumber
++;
338
}
339
340
uint32_t
341
DcaTxop::GetFragmentSize
(
void
)
342
{
343
NS_LOG_FUNCTION
(
this
);
344
return
m_stationManager
->
GetFragmentSize
(
m_currentHdr
.
GetAddr1
(), &
m_currentHdr
,
345
m_currentPacket
,
m_fragmentNumber
);
346
}
347
bool
348
DcaTxop::IsLastFragment
(
void
)
349
{
350
NS_LOG_FUNCTION
(
this
);
351
return
m_stationManager
->
IsLastFragment
(
m_currentHdr
.
GetAddr1
(), &
m_currentHdr
,
352
m_currentPacket
,
m_fragmentNumber
);
353
}
354
355
uint32_t
356
DcaTxop::GetNextFragmentSize
(
void
)
357
{
358
NS_LOG_FUNCTION
(
this
);
359
return
m_stationManager
->
GetFragmentSize
(
m_currentHdr
.
GetAddr1
(), &
m_currentHdr
,
360
m_currentPacket
,
m_fragmentNumber
+ 1);
361
}
362
363
uint32_t
364
DcaTxop::GetFragmentOffset
(
void
)
365
{
366
NS_LOG_FUNCTION
(
this
);
367
return
m_stationManager
->
GetFragmentOffset
(
m_currentHdr
.
GetAddr1
(), &
m_currentHdr
,
368
m_currentPacket
,
m_fragmentNumber
);
369
}
370
371
Ptr<Packet>
372
DcaTxop::GetFragmentPacket
(
WifiMacHeader
*hdr)
373
{
374
NS_LOG_FUNCTION
(
this
<< hdr);
375
*hdr =
m_currentHdr
;
376
hdr->
SetFragmentNumber
(
m_fragmentNumber
);
377
uint32_t startOffset =
GetFragmentOffset
();
378
Ptr<Packet>
fragment;
379
if
(
IsLastFragment
())
380
{
381
hdr->
SetNoMoreFragments
();
382
}
383
else
384
{
385
hdr->
SetMoreFragments
();
386
}
387
fragment =
m_currentPacket
->
CreateFragment
(startOffset,
388
GetFragmentSize
());
389
return
fragment;
390
}
391
392
bool
393
DcaTxop::NeedsAccess
(
void
)
const
394
{
395
NS_LOG_FUNCTION
(
this
);
396
return
!
m_queue
->
IsEmpty
() ||
m_currentPacket
!= 0;
397
}
398
void
399
DcaTxop::NotifyAccessGranted
(
void
)
400
{
401
NS_LOG_FUNCTION
(
this
);
402
if
(
m_currentPacket
== 0)
403
{
404
if
(
m_queue
->
IsEmpty
())
405
{
406
NS_LOG_DEBUG
(
"queue empty"
);
407
return
;
408
}
409
m_currentPacket
=
m_queue
->
Dequeue
(&
m_currentHdr
);
410
NS_ASSERT
(
m_currentPacket
!= 0);
411
uint16_t sequence =
m_txMiddle
->
GetNextSequenceNumberfor
(&
m_currentHdr
);
412
m_currentHdr
.
SetSequenceNumber
(sequence);
413
m_currentHdr
.
SetFragmentNumber
(0);
414
m_currentHdr
.
SetNoMoreFragments
();
415
m_currentHdr
.
SetNoRetry
();
416
m_fragmentNumber
= 0;
417
NS_LOG_DEBUG
(
"dequeued size="
<<
m_currentPacket
->
GetSize
() <<
418
", to="
<<
m_currentHdr
.
GetAddr1
() <<
419
", seq="
<<
m_currentHdr
.
GetSequenceControl
());
420
}
421
MacLowTransmissionParameters
params;
422
params.
DisableOverrideDurationId
();
423
if
(
m_currentHdr
.
GetAddr1
().
IsGroup
())
424
{
425
params.
DisableRts
();
426
params.
DisableAck
();
427
params.
DisableNextData
();
428
Low
()->
StartTransmission
(
m_currentPacket
,
429
&
m_currentHdr
,
430
params,
431
m_transmissionListener
);
432
NS_LOG_DEBUG
(
"tx broadcast"
);
433
}
434
else
435
{
436
params.
EnableAck
();
437
438
if
(
NeedFragmentation
())
439
{
440
WifiMacHeader
hdr;
441
Ptr<Packet>
fragment =
GetFragmentPacket
(&hdr);
442
if
(
NeedRts
(fragment, &hdr))
443
{
444
params.
EnableRts
();
445
}
446
else
447
{
448
params.
DisableRts
();
449
}
450
if
(
IsLastFragment
())
451
{
452
NS_LOG_DEBUG
(
"fragmenting last fragment size="
<< fragment->
GetSize
());
453
params.
DisableNextData
();
454
}
455
else
456
{
457
NS_LOG_DEBUG
(
"fragmenting size="
<< fragment->
GetSize
());
458
params.
EnableNextData
(
GetNextFragmentSize
());
459
}
460
Low
()->
StartTransmission
(fragment, &hdr, params,
461
m_transmissionListener
);
462
}
463
else
464
{
465
if
(
NeedRts
(
m_currentPacket
, &
m_currentHdr
))
466
{
467
params.
EnableRts
();
468
NS_LOG_DEBUG
(
"tx unicast rts"
);
469
}
470
else
471
{
472
params.
DisableRts
();
473
NS_LOG_DEBUG
(
"tx unicast"
);
474
}
475
params.
DisableNextData
();
476
Low
()->
StartTransmission
(
m_currentPacket
, &
m_currentHdr
,
477
params,
m_transmissionListener
);
478
}
479
}
480
}
481
482
void
483
DcaTxop::NotifyInternalCollision
(
void
)
484
{
485
NS_LOG_FUNCTION
(
this
);
486
NotifyCollision
();
487
}
488
void
489
DcaTxop::NotifyCollision
(
void
)
490
{
491
NS_LOG_FUNCTION
(
this
);
492
NS_LOG_DEBUG
(
"collision"
);
493
m_dcf
->
StartBackoffNow
(
m_rng
->
GetNext
(0,
m_dcf
->
GetCw
()));
494
RestartAccessIfNeeded
();
495
}
496
497
void
498
DcaTxop::NotifyChannelSwitching
(
void
)
499
{
500
NS_LOG_FUNCTION
(
this
);
501
m_queue
->
Flush
();
502
m_currentPacket
= 0;
503
}
504
505
void
506
DcaTxop::GotCts
(
double
snr,
WifiMode
txMode)
507
{
508
NS_LOG_FUNCTION
(
this
<< snr << txMode);
509
NS_LOG_DEBUG
(
"got cts"
);
510
}
511
void
512
DcaTxop::MissedCts
(
void
)
513
{
514
NS_LOG_FUNCTION
(
this
);
515
NS_LOG_DEBUG
(
"missed cts"
);
516
if
(!
NeedRtsRetransmission
())
517
{
518
NS_LOG_DEBUG
(
"Cts Fail"
);
519
m_stationManager
->
ReportFinalRtsFailed
(
m_currentHdr
.
GetAddr1
(), &
m_currentHdr
);
520
if
(!
m_txFailedCallback
.
IsNull
())
521
{
522
m_txFailedCallback
(
m_currentHdr
);
523
}
524
// to reset the dcf.
525
m_currentPacket
= 0;
526
m_dcf
->
ResetCw
();
527
}
528
else
529
{
530
m_dcf
->
UpdateFailedCw
();
531
}
532
m_dcf
->
StartBackoffNow
(
m_rng
->
GetNext
(0,
m_dcf
->
GetCw
()));
533
RestartAccessIfNeeded
();
534
}
535
void
536
DcaTxop::GotAck
(
double
snr,
WifiMode
txMode)
537
{
538
NS_LOG_FUNCTION
(
this
<< snr << txMode);
539
if
(!
NeedFragmentation
()
540
||
IsLastFragment
())
541
{
542
NS_LOG_DEBUG
(
"got ack. tx done."
);
543
if
(!
m_txOkCallback
.
IsNull
())
544
{
545
m_txOkCallback
(
m_currentHdr
);
546
}
547
548
/* we are not fragmenting or we are done fragmenting
549
* so we can get rid of that packet now.
550
*/
551
m_currentPacket
= 0;
552
m_dcf
->
ResetCw
();
553
m_dcf
->
StartBackoffNow
(
m_rng
->
GetNext
(0,
m_dcf
->
GetCw
()));
554
RestartAccessIfNeeded
();
555
}
556
else
557
{
558
NS_LOG_DEBUG
(
"got ack. tx not done, size="
<<
m_currentPacket
->
GetSize
());
559
}
560
}
561
void
562
DcaTxop::MissedAck
(
void
)
563
{
564
NS_LOG_FUNCTION
(
this
);
565
NS_LOG_DEBUG
(
"missed ack"
);
566
if
(!
NeedDataRetransmission
())
567
{
568
NS_LOG_DEBUG
(
"Ack Fail"
);
569
m_stationManager
->
ReportFinalDataFailed
(
m_currentHdr
.
GetAddr1
(), &
m_currentHdr
);
570
if
(!
m_txFailedCallback
.
IsNull
())
571
{
572
m_txFailedCallback
(
m_currentHdr
);
573
}
574
// to reset the dcf.
575
m_currentPacket
= 0;
576
m_dcf
->
ResetCw
();
577
}
578
else
579
{
580
NS_LOG_DEBUG
(
"Retransmit"
);
581
m_currentHdr
.
SetRetry
();
582
m_dcf
->
UpdateFailedCw
();
583
}
584
m_dcf
->
StartBackoffNow
(
m_rng
->
GetNext
(0,
m_dcf
->
GetCw
()));
585
RestartAccessIfNeeded
();
586
}
587
void
588
DcaTxop::StartNext
(
void
)
589
{
590
NS_LOG_FUNCTION
(
this
);
591
NS_LOG_DEBUG
(
"start next packet fragment"
);
592
/* this callback is used only for fragments. */
593
NextFragment
();
594
WifiMacHeader
hdr;
595
Ptr<Packet>
fragment =
GetFragmentPacket
(&hdr);
596
MacLowTransmissionParameters
params;
597
params.
EnableAck
();
598
params.
DisableRts
();
599
params.
DisableOverrideDurationId
();
600
if
(
IsLastFragment
())
601
{
602
params.
DisableNextData
();
603
}
604
else
605
{
606
params.
EnableNextData
(
GetNextFragmentSize
());
607
}
608
Low
()->
StartTransmission
(fragment, &hdr, params,
m_transmissionListener
);
609
}
610
611
void
612
DcaTxop::Cancel
(
void
)
613
{
614
NS_LOG_FUNCTION
(
this
);
615
NS_LOG_DEBUG
(
"transmission cancelled"
);
641
}
642
643
void
644
DcaTxop::EndTxNoAck
(
void
)
645
{
646
NS_LOG_FUNCTION
(
this
);
647
NS_LOG_DEBUG
(
"a transmission that did not require an ACK just finished"
);
648
m_currentPacket
= 0;
649
m_dcf
->
ResetCw
();
650
m_dcf
->
StartBackoffNow
(
m_rng
->
GetNext
(0,
m_dcf
->
GetCw
()));
651
StartAccessIfNeeded
();
652
}
653
654
}
// namespace ns3
src
wifi
model
dca-txop.cc
Generated on Tue May 14 2013 11:08:35 for ns-3 by
1.8.1.2