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
{
257
uint32_t dlt = file->
GetDataLinkType
();
258
259
switch
(dlt)
260
{
261
case
PcapHelper::DLT_IEEE802_11
:
262
file->
Write
(
Simulator::Now
(), packet);
263
return
;
264
case
PcapHelper::DLT_PRISM_HEADER
:
265
{
266
NS_FATAL_ERROR
(
"PcapSniffTxEvent(): DLT_PRISM_HEADER not implemented"
);
267
return
;
268
}
269
case
PcapHelper::DLT_IEEE802_11_RADIO
:
270
{
271
Ptr<Packet>
p = packet->
Copy
();
272
RadiotapHeader
header;
273
uint8_t frameFlags =
RadiotapHeader::FRAME_FLAG_NONE
;
274
header.
SetTsft
(
Simulator::Now
().GetMicroSeconds ());
275
276
// Our capture includes the FCS, so we set the flag to say so.
277
frameFlags |=
RadiotapHeader::FRAME_FLAG_FCS_INCLUDED
;
278
279
if
(isShortPreamble)
280
{
281
frameFlags |=
RadiotapHeader::FRAME_FLAG_SHORT_PREAMBLE
;
282
}
283
284
header.
SetFrameFlags
(frameFlags);
285
header.
SetRate
(rate);
286
287
uint16_t channelFlags = 0;
288
switch
(rate)
289
{
290
case
2:
// 1Mbps
291
case
4:
// 2Mbps
292
case
10:
// 5Mbps
293
case
22:
// 11Mbps
294
channelFlags |=
RadiotapHeader::CHANNEL_FLAG_CCK
;
295
break
;
296
297
default
:
298
channelFlags |=
RadiotapHeader::CHANNEL_FLAG_OFDM
;
299
break
;
300
}
301
302
if
(channelFreqMhz < 2500)
303
{
304
channelFlags |=
RadiotapHeader::CHANNEL_FLAG_SPECTRUM_2GHZ
;
305
}
306
else
307
{
308
channelFlags |=
RadiotapHeader::CHANNEL_FLAG_SPECTRUM_5GHZ
;
309
}
310
311
header.
SetChannelFrequencyAndFlags
(channelFreqMhz, channelFlags);
312
313
p->
AddHeader
(header);
314
file->
Write
(
Simulator::Now
(), p);
315
return
;
316
}
317
default
:
318
NS_ABORT_MSG
(
"PcapSniffTxEvent(): Unexpected data link type "
<< dlt);
319
}
320
}
321
322
static
void
323
PcapSniffRxEvent
(
324
Ptr<PcapFileWrapper>
file,
325
Ptr<const Packet>
packet,
326
uint16_t channelFreqMhz,
327
uint16_t channelNumber,
328
uint32_t rate,
329
bool
isShortPreamble,
330
double
signalDbm,
331
double
noiseDbm)
332
{
333
uint32_t dlt = file->
GetDataLinkType
();
334
335
switch
(dlt)
336
{
337
case
PcapHelper::DLT_IEEE802_11
:
338
file->
Write
(
Simulator::Now
(), packet);
339
return
;
340
case
PcapHelper::DLT_PRISM_HEADER
:
341
{
342
NS_FATAL_ERROR
(
"PcapSniffRxEvent(): DLT_PRISM_HEADER not implemented"
);
343
return
;
344
}
345
case
PcapHelper::DLT_IEEE802_11_RADIO
:
346
{
347
Ptr<Packet>
p = packet->
Copy
();
348
RadiotapHeader
header;
349
uint8_t frameFlags =
RadiotapHeader::FRAME_FLAG_NONE
;
350
header.
SetTsft
(
Simulator::Now
().GetMicroSeconds ());
351
352
// Our capture includes the FCS, so we set the flag to say so.
353
frameFlags |=
RadiotapHeader::FRAME_FLAG_FCS_INCLUDED
;
354
355
if
(isShortPreamble)
356
{
357
frameFlags |=
RadiotapHeader::FRAME_FLAG_SHORT_PREAMBLE
;
358
}
359
360
header.
SetFrameFlags
(frameFlags);
361
header.
SetRate
(rate);
362
363
uint16_t channelFlags = 0;
364
switch
(rate)
365
{
366
case
2:
// 1Mbps
367
case
4:
// 2Mbps
368
case
10:
// 5Mbps
369
case
22:
// 11Mbps
370
channelFlags |=
RadiotapHeader::CHANNEL_FLAG_CCK
;
371
break
;
372
373
default
:
374
channelFlags |=
RadiotapHeader::CHANNEL_FLAG_OFDM
;
375
break
;
376
}
377
378
if
(channelFreqMhz < 2500)
379
{
380
channelFlags |=
RadiotapHeader::CHANNEL_FLAG_SPECTRUM_2GHZ
;
381
}
382
else
383
{
384
channelFlags |=
RadiotapHeader::CHANNEL_FLAG_SPECTRUM_5GHZ
;
385
}
386
387
header.
SetChannelFrequencyAndFlags
(channelFreqMhz, channelFlags);
388
389
header.
SetAntennaSignalPower
(signalDbm);
390
header.
SetAntennaNoisePower
(noiseDbm);
391
392
p->
AddHeader
(header);
393
file->
Write
(
Simulator::Now
(), p);
394
return
;
395
}
396
default
:
397
NS_ABORT_MSG
(
"PcapSniffRxEvent(): Unexpected data link type "
<< dlt);
398
}
399
}
400
401
void
402
YansWifiPhyHelper::SetPcapDataLinkType
(
enum
SupportedPcapDataLinkTypes
dlt)
403
{
404
switch
(dlt)
405
{
406
case
DLT_IEEE802_11
:
407
m_pcapDlt
=
PcapHelper::DLT_IEEE802_11
;
408
return
;
409
case
DLT_PRISM_HEADER
:
410
m_pcapDlt
=
PcapHelper::DLT_PRISM_HEADER
;
411
return
;
412
case
DLT_IEEE802_11_RADIO
:
413
m_pcapDlt
=
PcapHelper::DLT_IEEE802_11_RADIO
;
414
return
;
415
default
:
416
NS_ABORT_MSG
(
"YansWifiPhyHelper::SetPcapFormat(): Unexpected format"
);
417
}
418
}
419
420
void
421
YansWifiPhyHelper::EnablePcapInternal
(std::string prefix,
Ptr<NetDevice>
nd,
bool
promiscuous,
bool
explicitFilename)
422
{
423
//
424
// All of the Pcap enable functions vector through here including the ones
425
// that are wandering through all of devices on perhaps all of the nodes in
426
// the system. We can only deal with devices of type WifiNetDevice.
427
//
428
Ptr<WifiNetDevice>
device = nd->
GetObject
<
WifiNetDevice
> ();
429
if
(device == 0)
430
{
431
NS_LOG_INFO
(
"YansWifiHelper::EnablePcapInternal(): Device "
<< &device <<
" not of type ns3::WifiNetDevice"
);
432
return
;
433
}
434
435
Ptr<WifiPhy>
phy = device->GetPhy ();
436
NS_ABORT_MSG_IF
(phy == 0,
"YansWifiPhyHelper::EnablePcapInternal(): Phy layer in WifiNetDevice must be set"
);
437
438
PcapHelper
pcapHelper;
439
440
std::string filename;
441
if
(explicitFilename)
442
{
443
filename = prefix;
444
}
445
else
446
{
447
filename = pcapHelper.
GetFilenameFromDevice
(prefix, device);
448
}
449
450
Ptr<PcapFileWrapper>
file = pcapHelper.
CreateFile
(filename, std::ios::out,
m_pcapDlt
);
451
452
phy->
TraceConnectWithoutContext
(
"MonitorSnifferTx"
,
MakeBoundCallback
(&
PcapSniffTxEvent
, file));
453
phy->
TraceConnectWithoutContext
(
"MonitorSnifferRx"
,
MakeBoundCallback
(&
PcapSniffRxEvent
, file));
454
}
455
456
void
457
YansWifiPhyHelper::EnableAsciiInternal
(
458
Ptr<OutputStreamWrapper>
stream,
459
std::string prefix,
460
Ptr<NetDevice>
nd,
461
bool
explicitFilename)
462
{
463
//
464
// All of the ascii enable functions vector through here including the ones
465
// that are wandering through all of devices on perhaps all of the nodes in
466
// the system. We can only deal with devices of type WifiNetDevice.
467
//
468
Ptr<WifiNetDevice>
device = nd->
GetObject
<
WifiNetDevice
> ();
469
if
(device == 0)
470
{
471
NS_LOG_INFO
(
"YansWifiHelper::EnableAsciiInternal(): Device "
<< device <<
" not of type ns3::WifiNetDevice"
);
472
return
;
473
}
474
475
//
476
// Our trace sinks are going to use packet printing, so we have to make sure
477
// that is turned on.
478
//
479
Packet::EnablePrinting
();
480
481
uint32_t nodeid = nd->
GetNode
()->
GetId
();
482
uint32_t deviceid = nd->
GetIfIndex
();
483
std::ostringstream oss;
484
485
//
486
// If we are not provided an OutputStreamWrapper, we are expected to create
487
// one using the usual trace filename conventions and write our traces
488
// without a context since there will be one file per context and therefore
489
// the context would be redundant.
490
//
491
if
(stream == 0)
492
{
493
//
494
// Set up an output stream object to deal with private ofstream copy
495
// constructor and lifetime issues. Let the helper decide the actual
496
// name of the file given the prefix.
497
//
498
AsciiTraceHelper
asciiTraceHelper;
499
500
std::string filename;
501
if
(explicitFilename)
502
{
503
filename = prefix;
504
}
505
else
506
{
507
filename = asciiTraceHelper.
GetFilenameFromDevice
(prefix, device);
508
}
509
510
Ptr<OutputStreamWrapper>
theStream = asciiTraceHelper.
CreateFileStream
(filename);
511
//
512
// We could go poking through the phy and the state looking for the
513
// correct trace source, but we can let Config deal with that with
514
// some search cost. Since this is presumably happening at topology
515
// creation time, it doesn't seem much of a price to pay.
516
//
517
oss.str (
""
);
518
oss <<
"/NodeList/"
<< nodeid <<
"/DeviceList/"
<< deviceid <<
"/$ns3::WifiNetDevice/Phy/State/RxOk"
;
519
Config::ConnectWithoutContext
(oss.str (),
MakeBoundCallback
(&
AsciiPhyReceiveSinkWithoutContext
, theStream));
520
521
oss.str (
""
);
522
oss <<
"/NodeList/"
<< nodeid <<
"/DeviceList/"
<< deviceid <<
"/$ns3::WifiNetDevice/Phy/State/Tx"
;
523
Config::ConnectWithoutContext
(oss.str (),
MakeBoundCallback
(&
AsciiPhyTransmitSinkWithoutContext
, theStream));
524
525
return
;
526
}
527
528
//
529
// If we are provided an OutputStreamWrapper, we are expected to use it, and
530
// to provide a context. We are free to come up with our own context if we
531
// want, and use the AsciiTraceHelper Hook*WithContext functions, but for
532
// compatibility and simplicity, we just use Config::Connect and let it deal
533
// with coming up with a context.
534
//
535
oss.str (
""
);
536
oss <<
"/NodeList/"
<< nodeid <<
"/DeviceList/"
<< deviceid <<
"/$ns3::WifiNetDevice/Phy/State/RxOk"
;
537
Config::Connect
(oss.str (),
MakeBoundCallback
(&
AsciiPhyReceiveSinkWithContext
, stream));
538
539
oss.str (
""
);
540
oss <<
"/NodeList/"
<< nodeid <<
"/DeviceList/"
<< deviceid <<
"/$ns3::WifiNetDevice/Phy/State/Tx"
;
541
Config::Connect
(oss.str (),
MakeBoundCallback
(&
AsciiPhyTransmitSinkWithContext
, stream));
542
}
543
544
}
// namespace ns3
src
wifi
helper
yans-wifi-helper.cc
Generated on Tue Oct 9 2012 16:45:48 for ns-3 by
1.8.1.2