A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
wifi-phy-test.cc
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2005,2006 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 #include "ns3/wifi-net-device.h"
21 #include "ns3/yans-wifi-channel.h"
22 #include "ns3/yans-wifi-phy.h"
23 #include "ns3/propagation-loss-model.h"
24 #include "ns3/propagation-delay-model.h"
25 #include "ns3/error-rate-model.h"
26 #include "ns3/yans-error-rate-model.h"
27 #include "ns3/ptr.h"
28 #include "ns3/mobility-model.h"
29 #include "ns3/constant-position-mobility-model.h"
30 #include "ns3/vector.h"
31 #include "ns3/packet.h"
32 #include "ns3/simulator.h"
33 #include "ns3/nstime.h"
34 #include "ns3/command-line.h"
35 #include "ns3/flow-id-tag.h"
36 
37 using namespace ns3;
38 
40 {
41 public:
42  struct Input
43  {
44  Input ();
45  double distance;
46  std::string txMode;
47  uint8_t txPowerLevel;
48  uint32_t packetSize;
49  uint32_t nPackets;
50  };
51  struct Output
52  {
53  uint32_t received;
54  };
55  PsrExperiment ();
56 
57  struct PsrExperiment::Output Run (struct PsrExperiment::Input input);
58 
59 private:
60  void Send (void);
61  void Receive (Ptr<Packet> p, double snr, WifiMode mode, enum WifiPreamble preamble);
62  Ptr<WifiPhy> m_tx;
63  struct Input m_input;
64  struct Output m_output;
65 };
66 
67 void
68 PsrExperiment::Send (void)
69 {
70  Ptr<Packet> p = Create<Packet> (m_input.packetSize);
71  WifiMode mode = WifiMode (m_input.txMode);
72  m_tx->SendPacket (p, mode, WIFI_PREAMBLE_SHORT, m_input.txPowerLevel);
73 }
74 
75 void
76 PsrExperiment::Receive (Ptr<Packet> p, double snr, WifiMode mode, enum WifiPreamble preamble)
77 {
78  m_output.received++;
79 }
80 
81 PsrExperiment::PsrExperiment ()
82 {
83 }
84 PsrExperiment::Input::Input ()
85  : distance (5.0),
86  txMode ("OfdmRate6Mbps"),
87  txPowerLevel (0),
88  packetSize (2304),
89  nPackets (400)
90 {
91 }
92 
94 PsrExperiment::Run (struct PsrExperiment::Input input)
95 {
96  m_output.received = 0;
97  m_input = input;
98 
99  Ptr<MobilityModel> posTx = CreateObject<ConstantPositionMobilityModel> ();
100  posTx->SetPosition (Vector (0.0, 0.0, 0.0));
101  Ptr<MobilityModel> posRx = CreateObject<ConstantPositionMobilityModel> ();
102  posRx->SetPosition (Vector (m_input.distance, 0.0, 0.0));
103 
104  Ptr<YansWifiChannel> channel = CreateObject<YansWifiChannel> ();
105  channel->SetPropagationDelayModel (CreateObject<ConstantSpeedPropagationDelayModel> ());
106  Ptr<LogDistancePropagationLossModel> log = CreateObject<LogDistancePropagationLossModel> ();
107  channel->SetPropagationLossModel (log);
108 
109  Ptr<YansWifiPhy> tx = CreateObject<YansWifiPhy> ();
110  Ptr<YansWifiPhy> rx = CreateObject<YansWifiPhy> ();
111  Ptr<ErrorRateModel> error = CreateObject<YansErrorRateModel> ();
112  tx->SetErrorRateModel (error);
113  rx->SetErrorRateModel (error);
114  tx->SetChannel (channel);
115  rx->SetChannel (channel);
116  tx->SetMobility (posTx);
117  rx->SetMobility (posRx);
118 
119  rx->SetReceiveOkCallback (MakeCallback (&PsrExperiment::Receive, this));
120 
121  for (uint32_t i = 0; i < m_input.nPackets; ++i)
122  {
123  Simulator::Schedule (Seconds (i), &PsrExperiment::Send, this);
124  }
125  m_tx = tx;
126  Simulator::Run ();
127  Simulator::Destroy();
128  return m_output;
129 }
130 
131 
133 {
134 public:
135  struct Input
136  {
137  Input ();
138  Time interval;
139  double xA;
140  double xB;
141  std::string txModeA;
142  std::string txModeB;
143  uint8_t txPowerLevelA;
144  uint8_t txPowerLevelB;
145  uint32_t packetSizeA;
146  uint32_t packetSizeB;
147  uint32_t nPackets;
148  };
149  struct Output
150  {
151  uint32_t receivedA;
152  uint32_t receivedB;
153  };
155 
156  struct CollisionExperiment::Output Run (struct CollisionExperiment::Input input);
157 private:
158  void SendA (void) const;
159  void SendB (void) const;
160  void Receive (Ptr<Packet> p, double snr, WifiMode mode, enum WifiPreamble preamble);
161  Ptr<WifiPhy> m_txA;
162  Ptr<WifiPhy> m_txB;
163  uint32_t m_flowIdA;
164  uint32_t m_flowIdB;
165  struct Input m_input;
166  struct Output m_output;
167 };
168 
169 void
170 CollisionExperiment::SendA (void) const
171 {
172  Ptr<Packet> p = Create<Packet> (m_input.packetSizeA);
173  p->AddByteTag (FlowIdTag (m_flowIdA));
174  m_txA->SendPacket (p, WifiMode (m_input.txModeA),
175  WIFI_PREAMBLE_SHORT, m_input.txPowerLevelA);
176 }
177 
178 void
179 CollisionExperiment::SendB (void) const
180 {
181  Ptr<Packet> p = Create<Packet> (m_input.packetSizeB);
182  p->AddByteTag (FlowIdTag (m_flowIdB));
183  m_txB->SendPacket (p, WifiMode (m_input.txModeB),
184  WIFI_PREAMBLE_SHORT, m_input.txPowerLevelB);
185 }
186 
187 void
188 CollisionExperiment::Receive (Ptr<Packet> p, double snr, WifiMode mode, enum WifiPreamble preamble)
189 {
190  FlowIdTag tag;
191  p->FindFirstMatchingByteTag (tag);
192  if (tag.GetFlowId () == m_flowIdA)
193  {
194  m_output.receivedA++;
195  }
196  else if (tag.GetFlowId () == m_flowIdB)
197  {
198  m_output.receivedB++;
199  }
200 }
201 
202 CollisionExperiment::CollisionExperiment ()
203 {
204 }
205 CollisionExperiment::Input::Input ()
206  : interval (MicroSeconds (0)),
207  xA (-5),
208  xB (5),
209  txModeA ("OfdmRate6Mbps"),
210  txModeB ("OfdmRate6Mbps"),
211  txPowerLevelA (0),
212  txPowerLevelB (0),
213  packetSizeA (2304),
214  packetSizeB (2304),
215  nPackets (400)
216 {
217 }
218 
220 CollisionExperiment::Run (struct CollisionExperiment::Input input)
221 {
222  m_output.receivedA = 0;
223  m_output.receivedB = 0;
224  m_input = input;
225 
226  m_flowIdA = FlowIdTag::AllocateFlowId ();
227  m_flowIdB = FlowIdTag::AllocateFlowId ();
228 
229  Ptr<YansWifiChannel> channel = CreateObject<YansWifiChannel> ();
230  channel->SetPropagationDelayModel (CreateObject<ConstantSpeedPropagationDelayModel> ());
231  Ptr<LogDistancePropagationLossModel> log = CreateObject<LogDistancePropagationLossModel> ();
232  channel->SetPropagationLossModel (log);
233 
234  Ptr<MobilityModel> posTxA = CreateObject<ConstantPositionMobilityModel> ();
235  posTxA->SetPosition (Vector (input.xA, 0.0, 0.0));
236  Ptr<MobilityModel> posTxB = CreateObject<ConstantPositionMobilityModel> ();
237  posTxB->SetPosition (Vector (input.xB, 0.0, 0.0));
238  Ptr<MobilityModel> posRx = CreateObject<ConstantPositionMobilityModel> ();
239  posRx->SetPosition (Vector (0, 0.0, 0.0));
240 
241  Ptr<YansWifiPhy> txA = CreateObject<YansWifiPhy> ();
242  Ptr<YansWifiPhy> txB = CreateObject<YansWifiPhy> ();
243  Ptr<YansWifiPhy> rx = CreateObject<YansWifiPhy> ();
244 
245  Ptr<ErrorRateModel> error = CreateObject<YansErrorRateModel> ();
246  txA->SetErrorRateModel (error);
247  txB->SetErrorRateModel (error);
248  rx->SetErrorRateModel (error);
249  txA->SetChannel (channel);
250  txB->SetChannel (channel);
251  rx->SetChannel (channel);
252  txA->SetMobility (posTxA);
253  txB->SetMobility (posTxB);
254  rx->SetMobility (posRx);
255 
256 
257  rx->SetReceiveOkCallback (MakeCallback (&CollisionExperiment::Receive, this));
258 
259  for (uint32_t i = 0; i < m_input.nPackets; ++i)
260  {
261  Simulator::Schedule (Seconds (i), &CollisionExperiment::SendA, this);
262  }
263  for (uint32_t i = 0; i < m_input.nPackets; ++i)
264  {
265  Simulator::Schedule (Seconds (i) + m_input.interval, &CollisionExperiment::SendB, this);
266  }
267  m_txA = txA;
268  m_txB = txB;
269  Simulator::Run ();
270  Simulator::Destroy();
271  return m_output;
272 }
273 
274 
275 static void PrintPsr (int argc, char *argv[])
276 {
277  PsrExperiment experiment;
278  struct PsrExperiment::Input input;
279 
280  CommandLine cmd;
281  cmd.AddValue ("Distance", "The distance between two phys", input.distance);
282  cmd.AddValue ("PacketSize", "The size of each packet sent", input.packetSize);
283  cmd.AddValue ("TxMode", "The mode to use to send each packet", input.txMode);
284  cmd.AddValue ("NPackets", "The number of packets to send", input.nPackets);
285  cmd.AddValue ("TxPowerLevel", "The power level index to use to send each packet", input.txPowerLevel);
286  cmd.Parse (argc, argv);
287 
288  struct PsrExperiment::Output output;
289  output = experiment.Run (input);
290 
291  double psr = output.received;
292  psr /= input.nPackets;
293 
294  std::cout << psr << std::endl;
295 }
296 
297 double CalcPsr (struct PsrExperiment::Output output, struct PsrExperiment::Input input)
298 {
299  double psr = output.received;
300  psr /= input.nPackets;
301  return psr;
302 }
303 
304 static void PrintPsrVsDistance (int argc, char *argv[])
305 {
306  struct PsrExperiment::Input input;
307  CommandLine cmd;
308  cmd.AddValue ("TxPowerLevel", "The power level index to use to send each packet", input.txPowerLevel);
309  cmd.AddValue ("TxMode", "The mode to use to send each packet", input.txMode);
310  cmd.AddValue ("NPackets", "The number of packets to send", input.nPackets);
311  cmd.AddValue ("PacketSize", "The size of each packet sent", input.packetSize);
312  cmd.Parse (argc, argv);
313  for (input.distance = 1.0; input.distance < 165; input.distance += 2.0)
314  {
315  std::cout << input.distance;
316  PsrExperiment experiment;
317  struct PsrExperiment::Output output;
318 
319  input.txMode = "OfdmRate6Mbps";
320  output = experiment.Run (input);
321  std::cout << " " << CalcPsr (output, input);
322 
323  input.txMode = "OfdmRate9Mbps";
324  output = experiment.Run (input);
325  std::cout << " " << CalcPsr (output, input);
326 
327  input.txMode = "OfdmRate12Mbps";
328  output = experiment.Run (input);
329  std::cout << " " << CalcPsr (output, input);
330 
331  input.txMode = "OfdmRate18Mbps";
332  output = experiment.Run (input);
333  std::cout << " " << CalcPsr (output, input);
334 
335  input.txMode = "OfdmRate24Mbps";
336  output = experiment.Run (input);
337  std::cout << " " << CalcPsr (output, input);
338 
339  input.txMode = "OfdmRate36Mbps";
340  output = experiment.Run (input);
341  std::cout << " " << CalcPsr (output, input);
342 
343  input.txMode = "OfdmRate48Mbps";
344  output = experiment.Run (input);
345  std::cout << " " << CalcPsr (output, input);
346 
347  input.txMode = "OfdmRate54Mbps";
348  output = experiment.Run (input);
349  std::cout << " " << CalcPsr (output, input);
350 
351  std::cout << std::endl;
352  }
353 }
354 
355 static void PrintSizeVsRange (int argc, char *argv[])
356 {
357  double targetPsr = 0.05;
358  struct PsrExperiment::Input input;
359  CommandLine cmd;
360  cmd.AddValue ("TxPowerLevel", "The power level index to use to send each packet", input.txPowerLevel);
361  cmd.AddValue ("TxMode", "The mode to use to send each packet", input.txMode);
362  cmd.AddValue ("NPackets", "The number of packets to send", input.nPackets);
363  cmd.AddValue ("TargetPsr", "The psr needed to assume that we are within range", targetPsr);
364  cmd.Parse (argc, argv);
365  for (input.packetSize = 10; input.packetSize < 3000; input.packetSize += 40)
366  {
367  double precision = 0.1;
368  double low = 1.0;
369  double high = 200.0;
370  while (high - low > precision)
371  {
372  double middle = low + (high - low) / 2;
373  struct PsrExperiment::Output output;
374  PsrExperiment experiment;
375  input.distance = middle;
376  output = experiment.Run (input);
377  double psr = CalcPsr (output, input);
378  if (psr >= targetPsr)
379  {
380  low = middle;
381  }
382  else
383  {
384  high = middle;
385  }
386  }
387  std::cout << input.packetSize << " " << input.distance << std::endl;
388  }
389 }
390 
391 static void PrintPsrVsCollisionInterval (int argc, char *argv[])
392 {
394  input.nPackets = 100;
395  CommandLine cmd;
396  cmd.AddValue ("NPackets", "The number of packets to send for each transmitter", input.nPackets);
397  cmd.AddValue ("xA", "the position of transmitter A", input.xA);
398  cmd.AddValue ("xB", "the position of transmitter B", input.xB);
399  for (uint32_t i = 0; i < 100; i += 1)
400  {
401  CollisionExperiment experiment;
403  input.interval = MicroSeconds (i);
404  output = experiment.Run (input);
405  double perA = (output.receivedA + 0.0) / (input.nPackets + 0.0);
406  double perB = (output.receivedB + 0.0) / (input.nPackets + 0.0);
407  std::cout << i << " " << perA << " " << perB << std::endl;
408  }
409  for (uint32_t i = 100; i < 4000; i += 50)
410  {
411  CollisionExperiment experiment;
413  input.interval = MicroSeconds (i);
414  output = experiment.Run (input);
415  double perA = (output.receivedA + 0.0) / (input.nPackets + 0.0);
416  double perB = (output.receivedB + 0.0) / (input.nPackets + 0.0);
417  std::cout << i << " " << perA << " " << perB << std::endl;
418  }
419 }
420 
421 
422 
423 int main (int argc, char *argv[])
424 {
425  if (argc <= 1)
426  {
427  std::cout << "Available experiments: "
428  << "Psr "
429  << "SizeVsRange "
430  << "PsrVsDistance "
431  << "PsrVsCollisionInterval "
432  << std::endl;
433  return 0;
434  }
435  std::string type = argv[1];
436  argc--;
437  argv[1] = argv[0];
438  argv++;
439  if (type == "Psr")
440  {
441  PrintPsr (argc, argv);
442  }
443  else if (type == "SizeVsRange")
444  {
445  PrintSizeVsRange (argc, argv);
446  }
447  else if (type == "PsrVsDistance")
448  {
449  PrintPsrVsDistance (argc, argv);
450  }
451  else if (type == "PsrVsCollisionInterval")
452  {
453  PrintPsrVsCollisionInterval (argc, argv);
454  }
455 
456  return 0;
457 }
bool FindFirstMatchingByteTag(Tag &tag) const
Definition: packet.cc:850
keep track of time unit.
Definition: nstime.h:149
smart pointer class similar to boost::intrusive_ptr
Definition: ptr.h:59
represent a single transmission modeA WifiMode is implemented by a single integer which is used to lo...
Definition: wifi-mode.h:88
a 3d vector
Definition: vector.h:31
WifiPreamble
Definition: wifi-preamble.h:29
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:502
parse command-line argumentsInstances of this class can be used to parse command-line arguments: user...
Definition: command-line.h:50
void SetPosition(const Vector &position)
void AddValue(const std::string &name, const std::string &help, T &value)
Definition: command-line.h:134
Time MicroSeconds(uint64_t us)
create ns3::Time instances in units of microseconds.
Definition: nstime.h:615
void AddByteTag(const Tag &tag) const
Definition: packet.cc:833