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
m_txOkCallback
= callback;
189
}
190
void
191
DcaTxop::SetTxFailedCallback
(
TxFailed
callback)
192
{
193
m_txFailedCallback
= callback;
194
}
195
196
Ptr<WifiMacQueue >
197
DcaTxop::GetQueue
()
const
198
{
199
NS_LOG_FUNCTION
(
this
);
200
return
m_queue
;
201
}
202
203
void
204
DcaTxop::SetMinCw
(uint32_t minCw)
205
{
206
NS_LOG_FUNCTION
(
this
<< minCw);
207
m_dcf
->
SetCwMin
(minCw);
208
}
209
void
210
DcaTxop::SetMaxCw
(uint32_t maxCw)
211
{
212
NS_LOG_FUNCTION
(
this
<< maxCw);
213
m_dcf
->
SetCwMax
(maxCw);
214
}
215
void
216
DcaTxop::SetAifsn
(uint32_t aifsn)
217
{
218
NS_LOG_FUNCTION
(
this
<< aifsn);
219
m_dcf
->
SetAifsn
(aifsn);
220
}
221
uint32_t
222
DcaTxop::GetMinCw
(
void
)
const
223
{
224
return
m_dcf
->
GetCwMin
();
225
}
226
uint32_t
227
DcaTxop::GetMaxCw
(
void
)
const
228
{
229
return
m_dcf
->
GetCwMax
();
230
}
231
uint32_t
232
DcaTxop::GetAifsn
(
void
)
const
233
{
234
return
m_dcf
->
GetAifsn
();
235
}
236
237
void
238
DcaTxop::Queue
(
Ptr<const Packet>
packet,
const
WifiMacHeader
&hdr)
239
{
240
NS_LOG_FUNCTION
(
this
<< packet << &hdr);
241
WifiMacTrailer
fcs;
242
uint32_t fullPacketSize = hdr.
GetSerializedSize
() + packet->
GetSize
() + fcs.
GetSerializedSize
();
243
m_stationManager
->
PrepareForQueue
(hdr.
GetAddr1
(), &hdr,
244
packet, fullPacketSize);
245
m_queue
->
Enqueue
(packet, hdr);
246
StartAccessIfNeeded
();
247
}
248
249
int64_t
250
DcaTxop::AssignStreams
(int64_t stream)
251
{
252
NS_LOG_FUNCTION
(
this
<< stream);
253
m_rng
->
AssignStreams
(stream);
254
return
1;
255
}
256
257
void
258
DcaTxop::RestartAccessIfNeeded
(
void
)
259
{
260
NS_LOG_FUNCTION
(
this
);
261
if
((
m_currentPacket
!= 0
262
|| !
m_queue
->
IsEmpty
())
263
&& !
m_dcf
->
IsAccessRequested
())
264
{
265
m_manager
->
RequestAccess
(
m_dcf
);
266
}
267
}
268
269
void
270
DcaTxop::StartAccessIfNeeded
(
void
)
271
{
272
NS_LOG_FUNCTION
(
this
);
273
if
(
m_currentPacket
== 0
274
&& !
m_queue
->
IsEmpty
()
275
&& !
m_dcf
->
IsAccessRequested
())
276
{
277
m_manager
->
RequestAccess
(
m_dcf
);
278
}
279
}
280
281
282
Ptr<MacLow>
283
DcaTxop::Low
(
void
)
284
{
285
return
m_low
;
286
}
287
288
bool
289
DcaTxop::NeedRts
(
Ptr<const Packet>
packet,
const
WifiMacHeader
*header)
290
{
291
return
m_stationManager
->
NeedRts
(header->
GetAddr1
(), header,
292
packet);
293
}
294
295
void
296
DcaTxop::DoStart
()
297
{
298
m_dcf
->
ResetCw
();
299
m_dcf
->
StartBackoffNow
(
m_rng
->
GetNext
(0,
m_dcf
->
GetCw
()));
300
ns3::Dcf::DoStart
();
301
}
302
bool
303
DcaTxop::NeedRtsRetransmission
(
void
)
304
{
305
return
m_stationManager
->
NeedRtsRetransmission
(
m_currentHdr
.
GetAddr1
(), &
m_currentHdr
,
306
m_currentPacket
);
307
}
308
309
bool
310
DcaTxop::NeedDataRetransmission
(
void
)
311
{
312
return
m_stationManager
->
NeedDataRetransmission
(
m_currentHdr
.
GetAddr1
(), &
m_currentHdr
,
313
m_currentPacket
);
314
}
315
bool
316
DcaTxop::NeedFragmentation
(
void
)
317
{
318
return
m_stationManager
->
NeedFragmentation
(
m_currentHdr
.
GetAddr1
(), &
m_currentHdr
,
319
m_currentPacket
);
320
}
321
322
void
323
DcaTxop::NextFragment
(
void
)
324
{
325
m_fragmentNumber
++;
326
}
327
328
uint32_t
329
DcaTxop::GetFragmentSize
(
void
)
330
{
331
return
m_stationManager
->
GetFragmentSize
(
m_currentHdr
.
GetAddr1
(), &
m_currentHdr
,
332
m_currentPacket
,
m_fragmentNumber
);
333
}
334
bool
335
DcaTxop::IsLastFragment
(
void
)
336
{
337
return
m_stationManager
->
IsLastFragment
(
m_currentHdr
.
GetAddr1
(), &
m_currentHdr
,
338
m_currentPacket
,
m_fragmentNumber
);
339
}
340
341
uint32_t
342
DcaTxop::GetNextFragmentSize
(
void
)
343
{
344
return
m_stationManager
->
GetFragmentSize
(
m_currentHdr
.
GetAddr1
(), &
m_currentHdr
,
345
m_currentPacket
,
m_fragmentNumber
+ 1);
346
}
347
348
uint32_t
349
DcaTxop::GetFragmentOffset
(
void
)
350
{
351
return
m_stationManager
->
GetFragmentOffset
(
m_currentHdr
.
GetAddr1
(), &
m_currentHdr
,
352
m_currentPacket
,
m_fragmentNumber
);
353
}
354
355
Ptr<Packet>
356
DcaTxop::GetFragmentPacket
(
WifiMacHeader
*hdr)
357
{
358
*hdr =
m_currentHdr
;
359
hdr->
SetFragmentNumber
(
m_fragmentNumber
);
360
uint32_t startOffset =
GetFragmentOffset
();
361
Ptr<Packet>
fragment;
362
if
(
IsLastFragment
())
363
{
364
hdr->
SetNoMoreFragments
();
365
}
366
else
367
{
368
hdr->
SetMoreFragments
();
369
}
370
fragment =
m_currentPacket
->
CreateFragment
(startOffset,
371
GetFragmentSize
());
372
return
fragment;
373
}
374
375
bool
376
DcaTxop::NeedsAccess
(
void
)
const
377
{
378
return
!
m_queue
->
IsEmpty
() ||
m_currentPacket
!= 0;
379
}
380
void
381
DcaTxop::NotifyAccessGranted
(
void
)
382
{
383
NS_LOG_FUNCTION
(
this
);
384
if
(
m_currentPacket
== 0)
385
{
386
if
(
m_queue
->
IsEmpty
())
387
{
388
NS_LOG_DEBUG
(
"queue empty"
);
389
return
;
390
}
391
m_currentPacket
=
m_queue
->
Dequeue
(&
m_currentHdr
);
392
NS_ASSERT
(
m_currentPacket
!= 0);
393
uint16_t sequence =
m_txMiddle
->
GetNextSequenceNumberfor
(&
m_currentHdr
);
394
m_currentHdr
.
SetSequenceNumber
(sequence);
395
m_currentHdr
.
SetFragmentNumber
(0);
396
m_currentHdr
.
SetNoMoreFragments
();
397
m_currentHdr
.
SetNoRetry
();
398
m_fragmentNumber
= 0;
399
NS_LOG_DEBUG
(
"dequeued size="
<<
m_currentPacket
->
GetSize
() <<
400
", to="
<<
m_currentHdr
.
GetAddr1
() <<
401
", seq="
<<
m_currentHdr
.
GetSequenceControl
());
402
}
403
MacLowTransmissionParameters
params;
404
params.
DisableOverrideDurationId
();
405
if
(
m_currentHdr
.
GetAddr1
().
IsGroup
())
406
{
407
params.
DisableRts
();
408
params.
DisableAck
();
409
params.
DisableNextData
();
410
Low
()->
StartTransmission
(
m_currentPacket
,
411
&
m_currentHdr
,
412
params,
413
m_transmissionListener
);
414
NS_LOG_DEBUG
(
"tx broadcast"
);
415
}
416
else
417
{
418
params.
EnableAck
();
419
420
if
(
NeedFragmentation
())
421
{
422
WifiMacHeader
hdr;
423
Ptr<Packet>
fragment =
GetFragmentPacket
(&hdr);
424
if
(
NeedRts
(fragment, &hdr))
425
{
426
params.
EnableRts
();
427
}
428
else
429
{
430
params.
DisableRts
();
431
}
432
if
(
IsLastFragment
())
433
{
434
NS_LOG_DEBUG
(
"fragmenting last fragment size="
<< fragment->
GetSize
());
435
params.
DisableNextData
();
436
}
437
else
438
{
439
NS_LOG_DEBUG
(
"fragmenting size="
<< fragment->
GetSize
());
440
params.
EnableNextData
(
GetNextFragmentSize
());
441
}
442
Low
()->
StartTransmission
(fragment, &hdr, params,
443
m_transmissionListener
);
444
}
445
else
446
{
447
if
(
NeedRts
(
m_currentPacket
, &
m_currentHdr
))
448
{
449
params.
EnableRts
();
450
NS_LOG_DEBUG
(
"tx unicast rts"
);
451
}
452
else
453
{
454
params.
DisableRts
();
455
NS_LOG_DEBUG
(
"tx unicast"
);
456
}
457
params.
DisableNextData
();
458
Low
()->
StartTransmission
(
m_currentPacket
, &
m_currentHdr
,
459
params,
m_transmissionListener
);
460
}
461
}
462
}
463
464
void
465
DcaTxop::NotifyInternalCollision
(
void
)
466
{
467
NS_LOG_FUNCTION
(
this
);
468
NotifyCollision
();
469
}
470
void
471
DcaTxop::NotifyCollision
(
void
)
472
{
473
NS_LOG_FUNCTION
(
this
);
474
NS_LOG_DEBUG
(
"collision"
);
475
m_dcf
->
StartBackoffNow
(
m_rng
->
GetNext
(0,
m_dcf
->
GetCw
()));
476
RestartAccessIfNeeded
();
477
}
478
479
void
480
DcaTxop::NotifyChannelSwitching
(
void
)
481
{
482
m_queue
->
Flush
();
483
m_currentPacket
= 0;
484
}
485
486
void
487
DcaTxop::GotCts
(
double
snr,
WifiMode
txMode)
488
{
489
NS_LOG_FUNCTION
(
this
<< snr << txMode);
490
NS_LOG_DEBUG
(
"got cts"
);
491
}
492
void
493
DcaTxop::MissedCts
(
void
)
494
{
495
NS_LOG_FUNCTION
(
this
);
496
NS_LOG_DEBUG
(
"missed cts"
);
497
if
(!
NeedRtsRetransmission
())
498
{
499
NS_LOG_DEBUG
(
"Cts Fail"
);
500
m_stationManager
->
ReportFinalRtsFailed
(
m_currentHdr
.
GetAddr1
(), &
m_currentHdr
);
501
if
(!
m_txFailedCallback
.
IsNull
())
502
{
503
m_txFailedCallback
(
m_currentHdr
);
504
}
505
// to reset the dcf.
506
m_currentPacket
= 0;
507
m_dcf
->
ResetCw
();
508
}
509
else
510
{
511
m_dcf
->
UpdateFailedCw
();
512
}
513
m_dcf
->
StartBackoffNow
(
m_rng
->
GetNext
(0,
m_dcf
->
GetCw
()));
514
RestartAccessIfNeeded
();
515
}
516
void
517
DcaTxop::GotAck
(
double
snr,
WifiMode
txMode)
518
{
519
NS_LOG_FUNCTION
(
this
<< snr << txMode);
520
if
(!
NeedFragmentation
()
521
||
IsLastFragment
())
522
{
523
NS_LOG_DEBUG
(
"got ack. tx done."
);
524
if
(!
m_txOkCallback
.
IsNull
())
525
{
526
m_txOkCallback
(
m_currentHdr
);
527
}
528
529
/* we are not fragmenting or we are done fragmenting
530
* so we can get rid of that packet now.
531
*/
532
m_currentPacket
= 0;
533
m_dcf
->
ResetCw
();
534
m_dcf
->
StartBackoffNow
(
m_rng
->
GetNext
(0,
m_dcf
->
GetCw
()));
535
RestartAccessIfNeeded
();
536
}
537
else
538
{
539
NS_LOG_DEBUG
(
"got ack. tx not done, size="
<<
m_currentPacket
->
GetSize
());
540
}
541
}
542
void
543
DcaTxop::MissedAck
(
void
)
544
{
545
NS_LOG_FUNCTION
(
this
);
546
NS_LOG_DEBUG
(
"missed ack"
);
547
if
(!
NeedDataRetransmission
())
548
{
549
NS_LOG_DEBUG
(
"Ack Fail"
);
550
m_stationManager
->
ReportFinalDataFailed
(
m_currentHdr
.
GetAddr1
(), &
m_currentHdr
);
551
if
(!
m_txFailedCallback
.
IsNull
())
552
{
553
m_txFailedCallback
(
m_currentHdr
);
554
}
555
// to reset the dcf.
556
m_currentPacket
= 0;
557
m_dcf
->
ResetCw
();
558
}
559
else
560
{
561
NS_LOG_DEBUG
(
"Retransmit"
);
562
m_currentHdr
.
SetRetry
();
563
m_dcf
->
UpdateFailedCw
();
564
}
565
m_dcf
->
StartBackoffNow
(
m_rng
->
GetNext
(0,
m_dcf
->
GetCw
()));
566
RestartAccessIfNeeded
();
567
}
568
void
569
DcaTxop::StartNext
(
void
)
570
{
571
NS_LOG_FUNCTION
(
this
);
572
NS_LOG_DEBUG
(
"start next packet fragment"
);
573
/* this callback is used only for fragments. */
574
NextFragment
();
575
WifiMacHeader
hdr;
576
Ptr<Packet>
fragment =
GetFragmentPacket
(&hdr);
577
MacLowTransmissionParameters
params;
578
params.
EnableAck
();
579
params.
DisableRts
();
580
params.
DisableOverrideDurationId
();
581
if
(
IsLastFragment
())
582
{
583
params.
DisableNextData
();
584
}
585
else
586
{
587
params.
EnableNextData
(
GetNextFragmentSize
());
588
}
589
Low
()->
StartTransmission
(fragment, &hdr, params,
m_transmissionListener
);
590
}
591
592
void
593
DcaTxop::Cancel
(
void
)
594
{
595
NS_LOG_FUNCTION
(
this
);
596
NS_LOG_DEBUG
(
"transmission cancelled"
);
622
}
623
624
void
625
DcaTxop::EndTxNoAck
(
void
)
626
{
627
NS_LOG_FUNCTION
(
this
);
628
NS_LOG_DEBUG
(
"a transmission that did not require an ACK just finished"
);
629
m_currentPacket
= 0;
630
m_dcf
->
ResetCw
();
631
m_dcf
->
StartBackoffNow
(
m_rng
->
GetNext
(0,
m_dcf
->
GetCw
()));
632
StartAccessIfNeeded
();
633
}
634
635
}
// namespace ns3
src
wifi
model
dca-txop.cc
Generated on Fri Dec 21 2012 19:00:48 for ns-3 by
1.8.1.2