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
yans-wifi-helper.cc
Go to the documentation of this file.
1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
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
21
#include "ns3/trace-helper.h"
22
#include "
yans-wifi-helper.h
"
23
#include "ns3/error-rate-model.h"
24
#include "ns3/propagation-loss-model.h"
25
#include "ns3/propagation-delay-model.h"
26
#include "ns3/yans-wifi-channel.h"
27
#include "ns3/yans-wifi-phy.h"
28
#include "ns3/wifi-net-device.h"
29
#include "ns3/radiotap-header.h"
30
#include "ns3/pcap-file-wrapper.h"
31
#include "ns3/simulator.h"
32
#include "ns3/config.h"
33
#include "ns3/names.h"
34
#include "ns3/abort.h"
35
#include "ns3/log.h"
36
37
NS_LOG_COMPONENT_DEFINE
(
"YansWifiHelper"
);
38
39
namespace
ns3 {
40
41
static
void
42
AsciiPhyTransmitSinkWithContext
(
43
Ptr<OutputStreamWrapper>
stream,
44
std::string context,
45
Ptr<const Packet>
p,
46
WifiMode
mode,
47
WifiPreamble
preamble,
48
uint8_t txLevel)
49
{
50
NS_LOG_FUNCTION
(stream << context << p << mode << preamble << txLevel);
51
*stream->
GetStream
() <<
"t "
<<
Simulator::Now
().
GetSeconds
() <<
" "
<< context <<
" "
<< *p << std::endl;
52
}
53
54
static
void
55
AsciiPhyTransmitSinkWithoutContext
(
56
Ptr<OutputStreamWrapper>
stream,
57
Ptr<const Packet>
p,
58
WifiMode
mode,
59
WifiPreamble
preamble,
60
uint8_t txLevel)
61
{
62
NS_LOG_FUNCTION
(stream << p << mode << preamble << txLevel);
63
*stream->
GetStream
() <<
"t "
<<
Simulator::Now
().
GetSeconds
() <<
" "
<< *p << std::endl;
64
}
65
66
static
void
67
AsciiPhyReceiveSinkWithContext
(
68
Ptr<OutputStreamWrapper>
stream,
69
std::string context,
70
Ptr<const Packet>
p,
71
double
snr,
72
WifiMode
mode,
73
enum
WifiPreamble
preamble)
74
{
75
NS_LOG_FUNCTION
(stream << context << p << snr << mode << preamble);
76
*stream->
GetStream
() <<
"r "
<<
Simulator::Now
().
GetSeconds
() <<
" "
<< context <<
" "
<< *p << std::endl;
77
}
78
79
static
void
80
AsciiPhyReceiveSinkWithoutContext
(
81
Ptr<OutputStreamWrapper>
stream,
82
Ptr<const Packet>
p,
83
double
snr,
84
WifiMode
mode,
85
enum
WifiPreamble
preamble)
86
{
87
NS_LOG_FUNCTION
(stream << p << snr << mode << preamble);
88
*stream->
GetStream
() <<
"r "
<<
Simulator::Now
().
GetSeconds
() <<
" "
<< *p << std::endl;
89
}
90
91
YansWifiChannelHelper::YansWifiChannelHelper
()
92
{
93
}
94
95
YansWifiChannelHelper
96
YansWifiChannelHelper::Default
(
void
)
97
{
98
YansWifiChannelHelper
helper;
99
helper.
SetPropagationDelay
(
"ns3::ConstantSpeedPropagationDelayModel"
);
100
helper.
AddPropagationLoss
(
"ns3::LogDistancePropagationLossModel"
);
101
return
helper;
102
}
103
104
void
105
YansWifiChannelHelper::AddPropagationLoss
(std::string type,
106
std::string n0,
const
AttributeValue
&v0,
107
std::string n1,
const
AttributeValue
&v1,
108
std::string n2,
const
AttributeValue
&v2,
109
std::string n3,
const
AttributeValue
&v3,
110
std::string n4,
const
AttributeValue
&v4,
111
std::string n5,
const
AttributeValue
&v5,
112
std::string n6,
const
AttributeValue
&v6,
113
std::string n7,
const
AttributeValue
&v7)
114
{
115
ObjectFactory
factory;
116
factory.
SetTypeId
(type);
117
factory.
Set
(n0, v0);
118
factory.
Set
(n1, v1);
119
factory.
Set
(n2, v2);
120
factory.
Set
(n3, v3);
121
factory.
Set
(n4, v4);
122
factory.
Set
(n5, v5);
123
factory.
Set
(n6, v6);
124
factory.
Set
(n7, v7);
125
m_propagationLoss
.push_back (factory);
126
}
127
128
void
129
YansWifiChannelHelper::SetPropagationDelay
(std::string type,
130
std::string n0,
const
AttributeValue
&v0,
131
std::string n1,
const
AttributeValue
&v1,
132
std::string n2,
const
AttributeValue
&v2,
133
std::string n3,
const
AttributeValue
&v3,
134
std::string n4,
const
AttributeValue
&v4,
135
std::string n5,
const
AttributeValue
&v5,
136
std::string n6,
const
AttributeValue
&v6,
137
std::string n7,
const
AttributeValue
&v7)
138
{
139
ObjectFactory
factory;
140
factory.
SetTypeId
(type);
141
factory.
Set
(n0, v0);
142
factory.
Set
(n1, v1);
143
factory.
Set
(n2, v2);
144
factory.
Set
(n3, v3);
145
factory.
Set
(n4, v4);
146
factory.
Set
(n5, v5);
147
factory.
Set
(n6, v6);
148
factory.
Set
(n7, v7);
149
m_propagationDelay
= factory;
150
}
151
152
Ptr<YansWifiChannel>
153
YansWifiChannelHelper::Create
(
void
)
const
154
{
155
Ptr<YansWifiChannel>
channel = CreateObject<YansWifiChannel> ();
156
Ptr<PropagationLossModel>
prev = 0;
157
for
(std::vector<ObjectFactory>::const_iterator i =
m_propagationLoss
.begin (); i !=
m_propagationLoss
.end (); ++i)
158
{
159
Ptr<PropagationLossModel>
cur = (*i).Create<
PropagationLossModel
> ();
160
if
(prev != 0)
161
{
162
prev->
SetNext
(cur);
163
}
164
if
(
m_propagationLoss
.begin () == i)
165
{
166
channel->
SetPropagationLossModel
(cur);
167
}
168
prev = cur;
169
}
170
Ptr<PropagationDelayModel>
delay =
m_propagationDelay
.
Create
<
PropagationDelayModel
> ();
171
channel->
SetPropagationDelayModel
(delay);
172
return
channel;
173
}
174
175
int64_t
176
YansWifiChannelHelper::AssignStreams
(
Ptr<YansWifiChannel>
c, int64_t stream)
177
{
178
return
c->
AssignStreams
(stream);
179
}
180
181
YansWifiPhyHelper::YansWifiPhyHelper
()
182
: m_channel (0),
183
m_pcapDlt (
PcapHelper
::DLT_IEEE802_11)
184
{
185
m_phy
.
SetTypeId
(
"ns3::YansWifiPhy"
);
186
}
187
188
YansWifiPhyHelper
189
YansWifiPhyHelper::Default
(
void
)
190
{
191
YansWifiPhyHelper
helper;
192
helper.
SetErrorRateModel
(
"ns3::NistErrorRateModel"
);
193
return
helper;
194
}
195
196
void
197
YansWifiPhyHelper::SetChannel
(
Ptr<YansWifiChannel>
channel)
198
{
199
m_channel
= channel;
200
}
201
void
202
YansWifiPhyHelper::SetChannel
(std::string channelName)
203
{
204
Ptr<YansWifiChannel>
channel = Names::Find<YansWifiChannel> (channelName);
205
m_channel
= channel;
206
}
207
void
208
YansWifiPhyHelper::Set
(std::string name,
const
AttributeValue
&v)
209
{
210
m_phy
.
Set
(name, v);
211
}
212
213
void
214
YansWifiPhyHelper::SetErrorRateModel
(std::string name,
215
std::string n0,
const
AttributeValue
&v0,
216
std::string n1,
const
AttributeValue
&v1,
217
std::string n2,
const
AttributeValue
&v2,
218
std::string n3,
const
AttributeValue
&v3,
219
std::string n4,
const
AttributeValue
&v4,
220
std::string n5,
const
AttributeValue
&v5,
221
std::string n6,
const
AttributeValue
&v6,
222
std::string n7,
const
AttributeValue
&v7)
223
{
224
m_errorRateModel
=
ObjectFactory
();
225
m_errorRateModel
.
SetTypeId
(name);
226
m_errorRateModel
.
Set
(n0, v0);
227
m_errorRateModel
.
Set
(n1, v1);
228
m_errorRateModel
.
Set
(n2, v2);
229
m_errorRateModel
.
Set
(n3, v3);
230
m_errorRateModel
.
Set
(n4, v4);
231
m_errorRateModel
.
Set
(n5, v5);
232
m_errorRateModel
.
Set
(n6, v6);
233
m_errorRateModel
.
Set
(n7, v7);
234
}
235
236
Ptr<WifiPhy>
237
YansWifiPhyHelper::Create
(
Ptr<Node>
node,
Ptr<WifiNetDevice>
device)
const
238
{
239
Ptr<YansWifiPhy>
phy =
m_phy
.
Create
<
YansWifiPhy
> ();
240
Ptr<ErrorRateModel>
error =
m_errorRateModel
.
Create
<
ErrorRateModel
> ();
241
phy->
SetErrorRateModel
(error);
242
phy->
SetChannel
(
m_channel
);
243
phy->
SetMobility
(node);
244
phy->
SetDevice
(device);
245
return
phy;
246
}
247
248
static
void
249
PcapSniffTxEvent
(
250
Ptr<PcapFileWrapper>
file,
251
Ptr<const Packet>
packet,
252
uint16_t channelFreqMhz,
253
uint16_t channelNumber,
254
uint32_t rate,
255
bool
isShortPreamble,
256
uint8_t txPower)
257
{
258
uint32_t dlt = file->
GetDataLinkType
();
259
260
switch
(dlt)
261
{
262
case
PcapHelper::DLT_IEEE802_11
:
263
file->
Write
(
Simulator::Now
(), packet);
264
return
;
265
case
PcapHelper::DLT_PRISM_HEADER
:
266
{
267
NS_FATAL_ERROR
(
"PcapSniffTxEvent(): DLT_PRISM_HEADER not implemented"
);
268
return
;
269
}
270
case
PcapHelper::DLT_IEEE802_11_RADIO
:
271
{
272
Ptr<Packet>
p = packet->
Copy
();
273
RadiotapHeader
header;
274
uint8_t frameFlags =
RadiotapHeader::FRAME_FLAG_NONE
;
275
header.
SetTsft
(
Simulator::Now
().GetMicroSeconds ());
276
277
// Our capture includes the FCS, so we set the flag to say so.
278
frameFlags |=
RadiotapHeader::FRAME_FLAG_FCS_INCLUDED
;
279
280
if
(isShortPreamble)
281
{
282
frameFlags |=
RadiotapHeader::FRAME_FLAG_SHORT_PREAMBLE
;
283
}
284
285
header.
SetFrameFlags
(frameFlags);
286
header.
SetRate
(rate);
287
288
uint16_t channelFlags = 0;
289
switch
(rate)
290
{
291
case
2:
// 1Mbps
292
case
4:
// 2Mbps
293
case
10:
// 5Mbps
294
case
22:
// 11Mbps
295
channelFlags |=
RadiotapHeader::CHANNEL_FLAG_CCK
;
296
break
;
297
298
default
:
299
channelFlags |=
RadiotapHeader::CHANNEL_FLAG_OFDM
;
300
break
;
301
}
302
303
if
(channelFreqMhz < 2500)
304
{
305
channelFlags |=
RadiotapHeader::CHANNEL_FLAG_SPECTRUM_2GHZ
;
306
}
307
else
308
{
309
channelFlags |=
RadiotapHeader::CHANNEL_FLAG_SPECTRUM_5GHZ
;
310
}
311
312
header.
SetChannelFrequencyAndFlags
(channelFreqMhz, channelFlags);
313
314
315
p->
AddHeader
(header);
316
file->
Write
(
Simulator::Now
(), p);
317
return
;
318
}
319
default
:
320
NS_ABORT_MSG
(
"PcapSniffTxEvent(): Unexpected data link type "
<< dlt);
321
}
322
}
323
324
static
void
325
PcapSniffRxEvent
(
326
Ptr<PcapFileWrapper>
file,
327
Ptr<const Packet>
packet,
328
uint16_t channelFreqMhz,
329
uint16_t channelNumber,
330
uint32_t rate,
331
bool
isShortPreamble,
332
double
signalDbm,
333
double
noiseDbm)
334
{
335
uint32_t dlt = file->
GetDataLinkType
();
336
337
switch
(dlt)
338
{
339
case
PcapHelper::DLT_IEEE802_11
:
340
file->
Write
(
Simulator::Now
(), packet);
341
return
;
342
case
PcapHelper::DLT_PRISM_HEADER
:
343
{
344
NS_FATAL_ERROR
(
"PcapSniffRxEvent(): DLT_PRISM_HEADER not implemented"
);
345
return
;
346
}
347
case
PcapHelper::DLT_IEEE802_11_RADIO
:
348
{
349
Ptr<Packet>
p = packet->
Copy
();
350
RadiotapHeader
header;
351
uint8_t frameFlags =
RadiotapHeader::FRAME_FLAG_NONE
;
352
header.
SetTsft
(
Simulator::Now
().GetMicroSeconds ());
353
354
// Our capture includes the FCS, so we set the flag to say so.
355
frameFlags |=
RadiotapHeader::FRAME_FLAG_FCS_INCLUDED
;
356
357
if
(isShortPreamble)
358
{
359
frameFlags |=
RadiotapHeader::FRAME_FLAG_SHORT_PREAMBLE
;
360
}
361
362
header.
SetFrameFlags
(frameFlags);
363
header.
SetRate
(rate);
364
365
uint16_t channelFlags = 0;
366
switch
(rate)
367
{
368
case
2:
// 1Mbps
369
case
4:
// 2Mbps
370
case
10:
// 5Mbps
371
case
22:
// 11Mbps
372
channelFlags |=
RadiotapHeader::CHANNEL_FLAG_CCK
;
373
break
;
374
375
default
:
376
channelFlags |=
RadiotapHeader::CHANNEL_FLAG_OFDM
;
377
break
;
378
}
379
380
if
(channelFreqMhz < 2500)
381
{
382
channelFlags |=
RadiotapHeader::CHANNEL_FLAG_SPECTRUM_2GHZ
;
383
}
384
else
385
{
386
channelFlags |=
RadiotapHeader::CHANNEL_FLAG_SPECTRUM_5GHZ
;
387
}
388
389
header.
SetChannelFrequencyAndFlags
(channelFreqMhz, channelFlags);
390
391
header.
SetAntennaSignalPower
(signalDbm);
392
header.
SetAntennaNoisePower
(noiseDbm);
393
394
p->
AddHeader
(header);
395
file->
Write
(
Simulator::Now
(), p);
396
return
;
397
}
398
default
:
399
NS_ABORT_MSG
(
"PcapSniffRxEvent(): Unexpected data link type "
<< dlt);
400
}
401
}
402
403
void
404
YansWifiPhyHelper::SetPcapDataLinkType
(
enum
SupportedPcapDataLinkTypes
dlt)
405
{
406
switch
(dlt)
407
{
408
case
DLT_IEEE802_11
:
409
m_pcapDlt
=
PcapHelper::DLT_IEEE802_11
;
410
return
;
411
case
DLT_PRISM_HEADER
:
412
m_pcapDlt
=
PcapHelper::DLT_PRISM_HEADER
;
413
return
;
414
case
DLT_IEEE802_11_RADIO
:
415
m_pcapDlt
=
PcapHelper::DLT_IEEE802_11_RADIO
;
416
return
;
417
default
:
418
NS_ABORT_MSG
(
"YansWifiPhyHelper::SetPcapFormat(): Unexpected format"
);
419
}
420
}
421
422
void
423
YansWifiPhyHelper::EnablePcapInternal
(std::string prefix,
Ptr<NetDevice>
nd,
bool
promiscuous,
bool
explicitFilename)
424
{
425
//
426
// All of the Pcap enable functions vector through here including the ones
427
// that are wandering through all of devices on perhaps all of the nodes in
428
// the system. We can only deal with devices of type WifiNetDevice.
429
//
430
Ptr<WifiNetDevice>
device = nd->
GetObject
<
WifiNetDevice
> ();
431
if
(device == 0)
432
{
433
NS_LOG_INFO
(
"YansWifiHelper::EnablePcapInternal(): Device "
<< &device <<
" not of type ns3::WifiNetDevice"
);
434
return
;
435
}
436
437
Ptr<WifiPhy>
phy = device->GetPhy ();
438
NS_ABORT_MSG_IF
(phy == 0,
"YansWifiPhyHelper::EnablePcapInternal(): Phy layer in WifiNetDevice must be set"
);
439
440
PcapHelper
pcapHelper;
441
442
std::string filename;
443
if
(explicitFilename)
444
{
445
filename = prefix;
446
}
447
else
448
{
449
filename = pcapHelper.
GetFilenameFromDevice
(prefix, device);
450
}
451
452
Ptr<PcapFileWrapper>
file = pcapHelper.
CreateFile
(filename, std::ios::out,
m_pcapDlt
);
453
454
phy->
TraceConnectWithoutContext
(
"MonitorSnifferTx"
,
MakeBoundCallback
(&
PcapSniffTxEvent
, file));
455
phy->
TraceConnectWithoutContext
(
"MonitorSnifferRx"
,
MakeBoundCallback
(&
PcapSniffRxEvent
, file));
456
}
457
458
void
459
YansWifiPhyHelper::EnableAsciiInternal
(
460
Ptr<OutputStreamWrapper>
stream,
461
std::string prefix,
462
Ptr<NetDevice>
nd,
463
bool
explicitFilename)
464
{
465
//
466
// All of the ascii enable functions vector through here including the ones
467
// that are wandering through all of devices on perhaps all of the nodes in
468
// the system. We can only deal with devices of type WifiNetDevice.
469
//
470
Ptr<WifiNetDevice>
device = nd->
GetObject
<
WifiNetDevice
> ();
471
if
(device == 0)
472
{
473
NS_LOG_INFO
(
"YansWifiHelper::EnableAsciiInternal(): Device "
<< device <<
" not of type ns3::WifiNetDevice"
);
474
return
;
475
}
476
477
//
478
// Our trace sinks are going to use packet printing, so we have to make sure
479
// that is turned on.
480
//
481
Packet::EnablePrinting
();
482
483
uint32_t nodeid = nd->
GetNode
()->
GetId
();
484
uint32_t deviceid = nd->
GetIfIndex
();
485
std::ostringstream oss;
486
487
//
488
// If we are not provided an OutputStreamWrapper, we are expected to create
489
// one using the usual trace filename conventions and write our traces
490
// without a context since there will be one file per context and therefore
491
// the context would be redundant.
492
//
493
if
(stream == 0)
494
{
495
//
496
// Set up an output stream object to deal with private ofstream copy
497
// constructor and lifetime issues. Let the helper decide the actual
498
// name of the file given the prefix.
499
//
500
AsciiTraceHelper
asciiTraceHelper;
501
502
std::string filename;
503
if
(explicitFilename)
504
{
505
filename = prefix;
506
}
507
else
508
{
509
filename = asciiTraceHelper.
GetFilenameFromDevice
(prefix, device);
510
}
511
512
Ptr<OutputStreamWrapper>
theStream = asciiTraceHelper.
CreateFileStream
(filename);
513
//
514
// We could go poking through the phy and the state looking for the
515
// correct trace source, but we can let Config deal with that with
516
// some search cost. Since this is presumably happening at topology
517
// creation time, it doesn't seem much of a price to pay.
518
//
519
oss.str (
""
);
520
oss <<
"/NodeList/"
<< nodeid <<
"/DeviceList/"
<< deviceid <<
"/$ns3::WifiNetDevice/Phy/State/RxOk"
;
521
Config::ConnectWithoutContext
(oss.str (),
MakeBoundCallback
(&
AsciiPhyReceiveSinkWithoutContext
, theStream));
522
523
oss.str (
""
);
524
oss <<
"/NodeList/"
<< nodeid <<
"/DeviceList/"
<< deviceid <<
"/$ns3::WifiNetDevice/Phy/State/Tx"
;
525
Config::ConnectWithoutContext
(oss.str (),
MakeBoundCallback
(&
AsciiPhyTransmitSinkWithoutContext
, theStream));
526
527
return
;
528
}
529
530
//
531
// If we are provided an OutputStreamWrapper, we are expected to use it, and
532
// to provide a context. We are free to come up with our own context if we
533
// want, and use the AsciiTraceHelper Hook*WithContext functions, but for
534
// compatibility and simplicity, we just use Config::Connect and let it deal
535
// with coming up with a context.
536
//
537
oss.str (
""
);
538
oss <<
"/NodeList/"
<< nodeid <<
"/DeviceList/"
<< deviceid <<
"/$ns3::WifiNetDevice/Phy/State/RxOk"
;
539
Config::Connect
(oss.str (),
MakeBoundCallback
(&
AsciiPhyReceiveSinkWithContext
, stream));
540
541
oss.str (
""
);
542
oss <<
"/NodeList/"
<< nodeid <<
"/DeviceList/"
<< deviceid <<
"/$ns3::WifiNetDevice/Phy/State/Tx"
;
543
Config::Connect
(oss.str (),
MakeBoundCallback
(&
AsciiPhyTransmitSinkWithContext
, stream));
544
}
545
546
}
// namespace ns3
src
wifi
helper
yans-wifi-helper.cc
Generated on Fri Aug 30 2013 01:43:04 for ns-3 by
1.8.1.2