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
uan-mac-cw.cc
Go to the documentation of this file.
1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2
/*
3
* Copyright (c) 2009 University of Washington
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: Leonard Tracy <lentracy@gmail.com>
19
*/
20
21
#include "
uan-mac-cw.h
"
22
#include "ns3/attribute.h"
23
#include "ns3/uinteger.h"
24
#include "ns3/double.h"
25
#include "ns3/nstime.h"
26
#include "ns3/uan-header-common.h"
27
#include "ns3/trace-source-accessor.h"
28
#include "ns3/log.h"
29
30
NS_LOG_COMPONENT_DEFINE
(
"UanMacCw"
);
31
32
namespace
ns3 {
33
34
NS_OBJECT_ENSURE_REGISTERED
(UanMacCw);
35
36
UanMacCw::UanMacCw
()
37
:
UanMac
(),
38
m_phy (0),
39
m_pktTx (0),
40
m_state (
IDLE
),
41
m_cleared (false)
42
43
{
44
m_rv
= CreateObject<UniformRandomVariable> ();
45
}
46
47
UanMacCw::~UanMacCw
()
48
{
49
}
50
51
void
52
UanMacCw::Clear
()
53
{
54
if
(
m_cleared
)
55
{
56
return
;
57
}
58
m_cleared
=
true
;
59
m_pktTx
= 0;
60
if
(
m_phy
)
61
{
62
m_phy
->
Clear
();
63
m_phy
= 0;
64
}
65
m_sendEvent
.
Cancel
();
66
m_txEndEvent
.
Cancel
();
67
}
68
69
void
70
UanMacCw::DoDispose
()
71
{
72
Clear
();
73
UanMac::DoDispose
();
74
}
75
76
TypeId
77
UanMacCw::GetTypeId
(
void
)
78
{
79
static
TypeId
tid =
TypeId
(
"ns3::UanMacCw"
)
80
.
SetParent
<
Object
> ()
81
.AddConstructor<UanMacCw> ()
82
.AddAttribute (
"CW"
,
83
"The MAC parameter CW"
,
84
UintegerValue
(10),
85
MakeUintegerAccessor (&
UanMacCw::m_cw
),
86
MakeUintegerChecker<uint32_t> ())
87
.AddAttribute (
"SlotTime"
,
88
"Time slot duration for MAC backoff"
,
89
TimeValue
(
MilliSeconds
(20)),
90
MakeTimeAccessor (&
UanMacCw::m_slotTime
),
91
MakeTimeChecker ())
92
.AddTraceSource (
"Enqueue"
,
93
"A packet arrived at the MAC for transmission"
,
94
MakeTraceSourceAccessor
(&
UanMacCw::m_enqueueLogger
))
95
.AddTraceSource (
"Dequeue"
,
96
"A was passed down to the PHY from the MAC"
,
97
MakeTraceSourceAccessor
(&
UanMacCw::m_dequeueLogger
))
98
.AddTraceSource (
"RX"
,
99
"A packet was destined for this MAC and was received"
,
100
MakeTraceSourceAccessor
(&
UanMacCw::m_rxLogger
))
101
102
;
103
return
tid;
104
}
105
106
Address
107
UanMacCw::GetAddress
()
108
{
109
return
this->
m_address
;
110
}
111
112
void
113
UanMacCw::SetAddress
(
UanAddress
addr)
114
{
115
m_address
= addr;
116
}
117
118
bool
119
UanMacCw::Enqueue
(
Ptr<Packet>
packet,
const
Address
&dest, uint16_t protocolNumber)
120
{
121
122
switch
(
m_state
)
123
{
124
case
CCABUSY
:
125
NS_LOG_DEBUG
(
"Time "
<<
Simulator::Now
().GetSeconds () <<
" MAC "
<<
GetAddress
() <<
" Starting enqueue CCABUSY"
);
126
if
(
m_txEndEvent
.
IsRunning
() ==
TX
)
127
{
128
NS_LOG_DEBUG
(
"State is TX"
);
129
}
130
else
131
{
132
NS_LOG_DEBUG
(
"State is not TX"
);
133
}
134
135
NS_ASSERT
(
m_phy
->
GetTransducer
()->
GetArrivalList
().size () >= 1 ||
m_phy
->
IsStateTx
());
136
return
false
;
137
case
RUNNING
:
138
NS_LOG_DEBUG
(
"MAC "
<<
GetAddress
() <<
" Starting enqueue RUNNING"
);
139
NS_ASSERT
(
m_phy
->
GetTransducer
()->
GetArrivalList
().size () == 0 && !
m_phy
->
IsStateTx
());
140
return
false
;
141
case
TX
:
142
case
IDLE
:
143
{
144
NS_ASSERT
(!
m_pktTx
);
145
146
UanHeaderCommon
header;
147
header.
SetDest
(
UanAddress::ConvertFrom
(dest));
148
header.
SetSrc
(
m_address
);
149
header.
SetType
(0);
150
packet->
AddHeader
(header);
151
152
m_enqueueLogger
(packet, protocolNumber);
153
154
if
(
m_phy
->
IsStateBusy
())
155
{
156
m_pktTx
= packet;
157
m_pktTxProt
= protocolNumber;
158
m_state
=
CCABUSY
;
159
uint32_t cw = (uint32_t)
m_rv
->
GetValue
(0,
m_cw
);
160
m_savedDelayS
=
Seconds
((
double
)(cw) *
m_slotTime
.
GetSeconds
());
161
m_sendTime
=
Simulator::Now
() +
m_savedDelayS
;
162
NS_LOG_DEBUG
(
"Time "
<<
Simulator::Now
().GetSeconds () <<
": Addr "
<<
GetAddress
() <<
": Enqueuing new packet while busy: (Chose CW "
<< cw <<
", Sending at "
<< m_sendTime.GetSeconds () <<
" Packet size: "
<< packet->
GetSize
());
163
NS_ASSERT
(
m_phy
->
GetTransducer
()->
GetArrivalList
().size () >= 1 ||
m_phy
->
IsStateTx
());
164
}
165
else
166
{
167
NS_ASSERT
(
m_state
!=
TX
);
168
NS_LOG_DEBUG
(
"Time "
<<
Simulator::Now
().GetSeconds () <<
": Addr "
<<
GetAddress
() <<
": Enqueuing new packet while idle (sending)"
);
169
NS_ASSERT
(
m_phy
->
GetTransducer
()->
GetArrivalList
().size () == 0 && !
m_phy
->
IsStateTx
());
170
m_state
=
TX
;
171
m_phy
->
SendPacket
(packet,protocolNumber);
172
173
}
174
break
;
175
}
176
default
:
177
NS_LOG_DEBUG
(
"MAC "
<<
GetAddress
() <<
" Starting enqueue SOMETHING ELSE"
);
178
return
false
;
179
}
180
181
return
true
;
182
183
184
}
185
186
void
187
UanMacCw::SetForwardUpCb
(
Callback
<
void
,
Ptr<Packet>
,
const
UanAddress
&> cb)
188
{
189
m_forwardUpCb
= cb;
190
}
191
192
void
193
UanMacCw::AttachPhy
(
Ptr<UanPhy>
phy)
194
{
195
m_phy
= phy;
196
m_phy
->
SetReceiveOkCallback
(
MakeCallback
(&
UanMacCw::PhyRxPacketGood
,
this
));
197
m_phy
->
SetReceiveErrorCallback
(
MakeCallback
(&
UanMacCw::PhyRxPacketError
,
this
));
198
m_phy
->
RegisterListener
(
this
);
199
}
200
201
Address
202
UanMacCw::GetBroadcast
(
void
)
const
203
{
204
return
UanAddress::GetBroadcast
();
205
}
206
207
208
void
209
UanMacCw::NotifyRxStart
(
void
)
210
{
211
if
(
m_state
==
RUNNING
)
212
{
213
214
NS_LOG_DEBUG
(
"Time "
<<
Simulator::Now
().GetSeconds () <<
" Addr "
<<
GetAddress
() <<
": Switching to channel busy"
);
215
SaveTimer
();
216
m_state
=
CCABUSY
;
217
}
218
219
}
220
void
221
UanMacCw::NotifyRxEndOk
(
void
)
222
{
223
if
(
m_state
==
CCABUSY
&& !
m_phy
->
IsStateCcaBusy
())
224
{
225
NS_LOG_DEBUG
(
"Time "
<<
Simulator::Now
().GetSeconds () <<
" Addr "
<<
GetAddress
() <<
": Switching to channel idle"
);
226
m_state
=
RUNNING
;
227
StartTimer
();
228
229
}
230
231
}
232
void
233
UanMacCw::NotifyRxEndError
(
void
)
234
{
235
if
(
m_state
==
CCABUSY
&& !
m_phy
->
IsStateCcaBusy
())
236
{
237
NS_LOG_DEBUG
(
"Time "
<<
Simulator::Now
().GetSeconds () <<
" Addr "
<<
GetAddress
() <<
": Switching to channel idle"
);
238
m_state
=
RUNNING
;
239
StartTimer
();
240
241
}
242
243
}
244
void
245
UanMacCw::NotifyCcaStart
(
void
)
246
{
247
if
(
m_state
==
RUNNING
)
248
{
249
NS_LOG_DEBUG
(
"Time "
<<
Simulator::Now
().GetSeconds () <<
" Addr "
<<
GetAddress
() <<
": Switching to channel busy"
);
250
m_state
=
CCABUSY
;
251
SaveTimer
();
252
253
}
254
255
}
256
void
257
UanMacCw::NotifyCcaEnd
(
void
)
258
{
259
if
(
m_state
==
CCABUSY
)
260
{
261
NS_LOG_DEBUG
(
"Time "
<<
Simulator::Now
().GetSeconds () <<
" Addr "
<<
GetAddress
() <<
": Switching to channel idle"
);
262
m_state
=
RUNNING
;
263
StartTimer
();
264
265
}
266
267
}
268
void
269
UanMacCw::NotifyTxStart
(
Time
duration)
270
{
271
272
if
(
m_txEndEvent
.
IsRunning
())
273
{
274
Simulator::Cancel
(
m_txEndEvent
);
275
}
276
277
m_txEndEvent
=
Simulator::Schedule
(duration, &
UanMacCw::EndTx
,
this
);
278
NS_LOG_DEBUG
(
"Time "
<<
Simulator::Now
().GetSeconds () <<
" scheduling TxEndEvent with delay "
<< duration.
GetSeconds
());
279
if
(
m_state
==
RUNNING
)
280
{
281
NS_ASSERT
(0);
282
m_state
=
CCABUSY
;
283
SaveTimer
();
284
285
}
286
287
}
288
289
int64_t
290
UanMacCw::AssignStreams
(int64_t stream)
291
{
292
NS_LOG_FUNCTION
(
this
<< stream);
293
m_rv
->
SetStream
(stream);
294
return
1;
295
}
296
297
void
298
UanMacCw::EndTx
(
void
)
299
{
300
NS_ASSERT
(
m_state
==
TX
||
m_state
==
CCABUSY
);
301
if
(
m_state
==
TX
)
302
{
303
m_state
=
IDLE
;
304
}
305
else
if
(
m_state
==
CCABUSY
)
306
{
307
if
(
m_phy
->
IsStateIdle
())
308
{
309
NS_LOG_DEBUG
(
"Time "
<<
Simulator::Now
().GetSeconds () <<
" Addr "
<<
GetAddress
() <<
": Switching to channel idle (After TX!)"
);
310
m_state
=
RUNNING
;
311
StartTimer
();
312
}
313
}
314
else
315
{
316
NS_FATAL_ERROR
(
"In strange state at UanMacCw EndTx"
);
317
}
318
}
319
void
320
UanMacCw::SetCw
(uint32_t cw)
321
{
322
m_cw
= cw;
323
}
324
void
325
UanMacCw::SetSlotTime
(
Time
duration)
326
{
327
m_slotTime
= duration;
328
}
329
uint32_t
330
UanMacCw::GetCw
(
void
)
331
{
332
return
m_cw
;
333
}
334
Time
335
UanMacCw::GetSlotTime
(
void
)
336
{
337
return
m_slotTime
;
338
}
339
void
340
UanMacCw::PhyRxPacketGood
(
Ptr<Packet>
packet,
double
sinr,
UanTxMode
mode)
341
{
342
UanHeaderCommon
header;
343
packet->
RemoveHeader
(header);
344
345
if
(header.
GetDest
() ==
m_address
|| header.
GetDest
() ==
UanAddress::GetBroadcast
())
346
{
347
m_forwardUpCb
(packet, header.
GetSrc
());
348
}
349
}
350
void
351
UanMacCw::PhyRxPacketError
(
Ptr<Packet>
packet,
double
sinr)
352
{
353
354
}
355
void
356
UanMacCw::SaveTimer
(
void
)
357
{
358
NS_LOG_DEBUG
(
"Time "
<<
Simulator::Now
().GetSeconds () <<
" Addr "
<<
GetAddress
() <<
" Saving timer (Delay = "
<< (
m_savedDelayS
=
m_sendTime
-
Simulator::Now
()).GetSeconds () <<
")"
);
359
NS_ASSERT
(
m_pktTx
);
360
NS_ASSERT
(
m_sendTime
>=
Simulator::Now
());
361
m_savedDelayS
=
m_sendTime
-
Simulator::Now
();
362
Simulator::Cancel
(
m_sendEvent
);
363
364
365
}
366
void
367
UanMacCw::StartTimer
(
void
)
368
{
369
370
m_sendTime
=
Simulator::Now
() +
m_savedDelayS
;
371
if
(
m_sendTime
==
Simulator::Now
())
372
{
373
SendPacket
();
374
}
375
else
376
{
377
m_sendEvent
=
Simulator::Schedule
(
m_savedDelayS
, &
UanMacCw::SendPacket
,
this
);
378
NS_LOG_DEBUG
(
"Time "
<<
Simulator::Now
().GetSeconds () <<
" Addr "
<<
GetAddress
() <<
" Starting timer (New send time = "
<< this->
m_sendTime
.
GetSeconds
() <<
")"
);
379
}
380
}
381
382
void
383
UanMacCw::SendPacket
(
void
)
384
{
385
NS_LOG_DEBUG
(
"Time "
<<
Simulator::Now
().GetSeconds () <<
" Addr "
<<
GetAddress
() <<
" Transmitting "
);
386
NS_ASSERT
(
m_state
==
RUNNING
);
387
m_state
=
TX
;
388
m_phy
->
SendPacket
(
m_pktTx
,
m_pktTxProt
);
389
m_pktTx
= 0;
390
m_sendTime
=
Seconds
(0);
391
m_savedDelayS
=
Seconds
(0);
392
}
393
394
}
// namespace ns3
src
uan
model
uan-mac-cw.cc
Generated on Tue Oct 9 2012 16:45:47 for ns-3 by
1.8.1.2