A Discrete-Event Network Simulator
API
bsm-application.cc
Go to the documentation of this file.
1 /* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014 North Carolina State University
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: Scott E. Carpenter <scarpen@ncsu.edu>
19  *
20  */
21 
22 #include "ns3/bsm-application.h"
23 #include "ns3/log.h"
24 #include "ns3/wave-net-device.h"
25 #include "ns3/wave-mac-helper.h"
26 #include "ns3/wave-helper.h"
27 #include "ns3/mobility-model.h"
28 #include "ns3/mobility-helper.h"
29 
30 NS_LOG_COMPONENT_DEFINE ("BsmApplication");
31 
32 namespace ns3 {
33 
34 // (Arbitrary) port for establishing socket to transmit WAVE BSMs
35 int BsmApplication::wavePort = 9080;
36 
37 NS_OBJECT_ENSURE_REGISTERED (BsmApplication);
38 
39 TypeId
41 {
42  static TypeId tid = TypeId ("ns3::BsmApplication")
44  .SetGroupName ("Wave")
45  .AddConstructor<BsmApplication> ()
46  ;
47  return tid;
48 }
49 
51  : m_waveBsmStats (0),
52  m_txSafetyRangesSq (),
53  m_TotalSimTime (Seconds (10)),
54  m_wavePacketSize (200),
55  m_numWavePackets (1),
56  m_waveInterval (MilliSeconds (100)),
57  m_gpsAccuracyNs (10000),
58  m_adhocTxInterfaces (0),
59  m_nodesMoving (0),
60  m_unirv (0),
61  m_nodeId (0),
62  m_chAccessMode (0),
63  m_txMaxDelay (MilliSeconds (10)),
64  m_prevTxDelay (MilliSeconds (0))
65 {
66  NS_LOG_FUNCTION (this);
67 }
68 
70 {
71  NS_LOG_FUNCTION (this);
72 }
73 
74 void
76 {
77  NS_LOG_FUNCTION (this);
78 
79  // chain up
81 }
82 
83 // Application Methods
84 void BsmApplication::StartApplication () // Called at time specified by Start
85 {
86  NS_LOG_FUNCTION (this);
87 
88  // setup generation of WAVE BSM messages
89  Time waveInterPacketInterval = m_waveInterval;
90 
91  // BSMs are not transmitted for the first second
92  Time startTime = Seconds (1.0);
93  // total length of time transmitting WAVE packets
94  Time totalTxTime = m_TotalSimTime - startTime;
95  // total WAVE packets needing to be sent
96  m_numWavePackets = (uint32_t) (totalTxTime.GetDouble () / m_waveInterval.GetDouble ());
97 
98  TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
99 
100  // every node broadcasts WAVE BSM to potentially all other nodes
101  Ptr<Socket> recvSink = Socket::CreateSocket (GetNode (m_nodeId), tid);
104  recvSink->BindToNetDevice (GetNetDevice (m_nodeId));
105  recvSink->Bind (local);
106  recvSink->SetAllowBroadcast (true);
107 
108  // dest is broadcast address
109  InetSocketAddress remote = InetSocketAddress (Ipv4Address ("255.255.255.255"), wavePort);
110  recvSink->Connect (remote);
111 
112  // Transmission start time for each BSM:
113  // We assume that the start transmission time
114  // for the first packet will be on a ns-3 time
115  // "Second" boundary - e.g., 1.0 s.
116  // However, the actual transmit time must reflect
117  // additional effects of 1) clock drift and
118  // 2) transmit delay requirements.
119  // 1) Clock drift - clocks are not perfectly
120  // synchronized across all nodes. In a VANET
121  // we assume all nodes sync to GPS time, which
122  // itself is assumed accurate to, say, 40-100 ns.
123  // Thus, the start transmission time must be adjusted
124  // by some value, t_drift.
125  // 2) Transmit delay requirements - The US
126  // minimum performance requirements for V2V
127  // BSM transmission expect a random delay of
128  // +/- 5 ms, to avoid simultaneous transmissions
129  // by all vehicles congesting the channel. Thus,
130  // we need to adjust the start transmission time by
131  // some value, t_tx_delay.
132  // Therefore, the actual transmit time should be:
133  // t_start = t_time + t_drift + t_tx_delay
134  // t_drift is always added to t_time.
135  // t_tx_delay is supposed to be +/- 5ms, but if we
136  // allow negative numbers the time could drift to a value
137  // BEFORE the interval start time (i.e., at 100 ms
138  // boundaries, we do not want to drift into the
139  // previous interval, such as at 95 ms. Instead,
140  // we always want to be at the 100 ms interval boundary,
141  // plus [0..10] ms tx delay.
142  // Thus, the average t_tx_delay will be
143  // within the desired range of [0..10] ms of
144  // (t_time + t_drift)
145 
146  // WAVE devices sync to GPS time
147  // and all devices would like to begin broadcasting
148  // their safety messages immediately at the start of
149  // the CCH interval. However, if all do so, then
150  // significant collisions occur. Thus, we assume there
151  // is some GPS sync accuracy on GPS devices,
152  // typically 40-100 ns.
153  // Get a uniformly random number for GPS sync accuracy, in ns.
155 
156  // When transmitting at a default rate of 10 Hz,
157  // the subsystem shall transmit every 100 ms +/-
158  // a random value between 0 and 5 ms. [MPR-BSMTX-TXTIM-002]
159  // Source: CAMP Vehicle Safety Communications 4 Consortium
160  // On-board Minimum Performance Requirements
161  // for V2V Safety Systems Version 1.0, December 17, 2014
162  // max transmit delay (default 10ms)
163  // get value for transmit delay, as number of ns
164  uint32_t d_ns = static_cast<uint32_t> (m_txMaxDelay.GetInteger ());
165  // convert random tx delay to ns-3 time
166  // see note above regarding centering tx delay
167  // offset by 5ms + a random value.
168  Time txDelay = NanoSeconds (m_unirv->GetInteger (0, d_ns));
169  m_prevTxDelay = txDelay;
170 
171  Time txTime = startTime + tDrift + txDelay;
172  // schedule transmission of first packet
173  Simulator::ScheduleWithContext (recvSink->GetNode ()->GetId (),
175  recvSink, m_wavePacketSize, m_numWavePackets, waveInterPacketInterval, m_nodeId);
176 }
177 
178 void BsmApplication::StopApplication () // Called at time specified by Stop
179 {
180  NS_LOG_FUNCTION (this);
181 }
182 
183 void
185  int nodeId,
186  Time totalTime,
187  uint32_t wavePacketSize, // bytes
188  Time waveInterval,
189  double gpsAccuracyNs,
190  std::vector <double> rangesSq, // m ^2
191  Ptr<WaveBsmStats> waveBsmStats,
192  std::vector<int> * nodesMoving,
193  int chAccessMode,
194  Time txMaxDelay)
195 {
196  NS_LOG_FUNCTION (this);
197 
198  m_unirv = CreateObject<UniformRandomVariable> ();
199 
200  m_TotalSimTime = totalTime;
201  m_wavePacketSize = wavePacketSize;
202  m_waveInterval = waveInterval;
203  m_gpsAccuracyNs = gpsAccuracyNs;
204  int size = rangesSq.size ();
205  m_waveBsmStats = waveBsmStats;
206  m_nodesMoving = nodesMoving;
207  m_chAccessMode = chAccessMode;
208  m_txSafetyRangesSq.clear ();
209  m_txSafetyRangesSq.resize (size, 0);
210 
211  for (int index = 0; index < size; index++)
212  {
213  // stored as square of value, for optimization
214  m_txSafetyRangesSq[index] = rangesSq[index];
215  }
216 
217  m_adhocTxInterfaces = &i;
218  m_nodeId = nodeId;
219  m_txMaxDelay = txMaxDelay;
220 }
221 
222 void
224  uint32_t pktCount, Time pktInterval,
225  uint32_t sendingNodeId)
226 {
227  NS_LOG_FUNCTION (this);
228 
229  // more packets to send?
230  if (pktCount > 0)
231  {
232  // for now, we cannot tell if each node has
233  // started mobility. so, as an optimization
234  // only send if this node is moving
235  // if not, then skip
236  int txNodeId = sendingNodeId;
237  Ptr<Node> txNode = GetNode (txNodeId);
238  Ptr<MobilityModel> txPosition = txNode->GetObject<MobilityModel> ();
239  NS_ASSERT (txPosition != 0);
240 
241  int senderMoving = m_nodesMoving->at (txNodeId);
242  if (senderMoving != 0)
243  {
244  // send it!
245  socket->Send (Create<Packet> (pktSize));
246  // count it
247  m_waveBsmStats->IncTxPktCount ();
248  m_waveBsmStats->IncTxByteCount (pktSize);
249  int wavePktsSent = m_waveBsmStats->GetTxPktCount ();
250  if ((m_waveBsmStats->GetLogging () != 0) && ((wavePktsSent % 1000) == 0))
251  {
252  NS_LOG_UNCOND ("Sending WAVE pkt # " << wavePktsSent );
253  }
254 
255  // find other nodes within range that would be
256  // expected to receive this broadbast
257  int nRxNodes = m_adhocTxInterfaces->GetN ();
258  for (int i = 0; i < nRxNodes; i++)
259  {
260  Ptr<Node> rxNode = GetNode (i);
261  int rxNodeId = rxNode->GetId ();
262 
263  if (rxNodeId != txNodeId)
264  {
265  Ptr<MobilityModel> rxPosition = rxNode->GetObject<MobilityModel> ();
266  NS_ASSERT (rxPosition != 0);
267  // confirm that the receiving node
268  // has also started moving in the scenario
269  // if it has not started moving, then
270  // it is not a candidate to receive a packet
271  int receiverMoving = m_nodesMoving->at (rxNodeId);
272  if (receiverMoving == 1)
273  {
274  double distSq = MobilityHelper::GetDistanceSquaredBetween (txNode, rxNode);
275  if (distSq > 0.0)
276  {
277  // dest node within range?
278  int rangeCount = m_txSafetyRangesSq.size ();
279  for (int index = 1; index <= rangeCount; index++)
280  {
281  if (distSq <= m_txSafetyRangesSq[index - 1])
282  {
283  // we should expect dest node to receive broadcast pkt
284  m_waveBsmStats->IncExpectedRxPktCount (index);
285  }
286  }
287  }
288  }
289  }
290  }
291  }
292 
293  // every BSM must be scheduled with a tx time delay
294  // of +/- (5) ms. See comments in StartApplication().
295  // we handle this as a tx delay of [0..10] ms
296  // from the start of the pktInterval boundary
297  uint32_t d_ns = static_cast<uint32_t> (m_txMaxDelay.GetInteger ());
298  Time txDelay = NanoSeconds (m_unirv->GetInteger (0, d_ns));
299 
300  // do not want the tx delay to be cumulative, so
301  // deduct the previous delay value. thus we adjust
302  // to schedule the next event at the next pktInterval,
303  // plus some new [0..10] ms tx delay
304  Time txTime = pktInterval - m_prevTxDelay + txDelay;
305  m_prevTxDelay = txDelay;
306 
309  socket, pktSize, pktCount - 1, pktInterval, socket->GetNode ()->GetId ());
310  }
311  else
312  {
313  socket->Close ();
314  }
315 }
316 
318 {
319  NS_LOG_FUNCTION (this);
320 
321  Ptr<Packet> packet;
322  Address senderAddr;
323  while ((packet = socket->RecvFrom (senderAddr)))
324  {
325  Ptr<Node> rxNode = socket->GetNode ();
326 
327  if (InetSocketAddress::IsMatchingType (senderAddr))
328  {
330  int nodes = m_adhocTxInterfaces->GetN ();
331  for (int i = 0; i < nodes; i++)
332  {
333  if (addr.GetIpv4 () == m_adhocTxInterfaces->GetAddress (i) )
334  {
335  Ptr<Node> txNode = GetNode (i);
336  HandleReceivedBsmPacket (txNode, rxNode);
337  }
338  }
339  }
340  }
341 }
342 
344  Ptr<Node> rxNode)
345 {
346  NS_LOG_FUNCTION (this);
347 
348  m_waveBsmStats->IncRxPktCount ();
349 
350  Ptr<MobilityModel> rxPosition = rxNode->GetObject<MobilityModel> ();
351  NS_ASSERT (rxPosition != 0);
352  // confirm that the receiving node
353  // has also started moving in the scenario
354  // if it has not started moving, then
355  // it is not a candidate to receive a packet
356  int rxNodeId = rxNode->GetId ();
357  int receiverMoving = m_nodesMoving->at (rxNodeId);
358  if (receiverMoving == 1)
359  {
360  double rxDistSq = MobilityHelper::GetDistanceSquaredBetween (rxNode, txNode);
361  if (rxDistSq > 0.0)
362  {
363  int rangeCount = m_txSafetyRangesSq.size ();
364  for (int index = 1; index <= rangeCount; index++)
365  {
366  if (rxDistSq <= m_txSafetyRangesSq[index - 1])
367  {
368  m_waveBsmStats->IncRxPktInRangeCount (index);
369  }
370  }
371  }
372  }
373 }
374 
375 int64_t
376 BsmApplication::AssignStreams (int64_t streamIndex)
377 {
378  NS_LOG_FUNCTION (this);
379 
380  NS_ASSERT (m_unirv); // should be set by Setup() prevoiusly
381  m_unirv->SetStream (streamIndex);
382 
383  return 1;
384 }
385 
386 Ptr<Node>
388 {
389  NS_LOG_FUNCTION (this);
390 
391  std::pair<Ptr<Ipv4>, uint32_t> interface = m_adhocTxInterfaces->Get (id);
392  Ptr<Ipv4> pp = interface.first;
393  Ptr<Node> node = pp->GetObject<Node> ();
394 
395  return node;
396 }
397 
400 {
401  NS_LOG_FUNCTION (this);
402 
403  std::pair<Ptr<Ipv4>, uint32_t> interface = m_adhocTxInterfaces->Get (id);
404  Ptr<Ipv4> pp = interface.first;
405  Ptr<NetDevice> device = pp->GetObject<NetDevice> ();
406 
407  return device;
408 }
409 
410 } // namespace ns3
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
an Inet address class
static Ipv4Address GetAny(void)
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
Ipv4InterfaceContainer * m_adhocTxInterfaces
transmit interfaces
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
uint32_t GetId(void) const
Definition: node.cc:109
uint32_t GetInteger(uint32_t min, uint32_t max)
Get the next random value, as an unsigned integer in the specified range .
holds a vector of std::pair of Ptr<Ipv4> and interface index.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
int64_t GetInteger(void) const
Get the raw time value, in the current resolution unit.
Definition: nstime.h:423
virtual bool SetAllowBroadcast(bool allowBroadcast)=0
Configure whether broadcast datagram transmissions are allowed.
static double GetDistanceSquaredBetween(Ptr< Node > n1, Ptr< Node > n2)
Ptr< UniformRandomVariable > m_unirv
random variable
uint32_t m_wavePacketSize
bytes
int64_t AssignStreams(int64_t streamIndex)
Assign a fixed random variable stream number to the random variables used by this model...
void Setup(Ipv4InterfaceContainer &i, int nodeId, Time totalTime, uint32_t wavePacketSize, Time waveInterval, double gpsAccuracyNs, std::vector< double > rangesSq, Ptr< WaveBsmStats > waveBsmStats, std::vector< int > *nodesMoving, int mode, Time txDelay)
Setup BSM generation parameters for a node.
BsmApplication()
Constructor.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
std::vector< double > m_txSafetyRangesSq
tx safety range squared, for optimization
Time m_waveInterval
wave interval
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1286
virtual void StartApplication(void)
Called at time specified by Start.
Time m_txMaxDelay
When transmitting at a default rate of 10 Hz, the subsystem shall transmit every 100 ms +/- a random ...
uint32_t m_numWavePackets
number of wave packets
Time m_prevTxDelay
previous transmit delay
a polymophic address class
Definition: address.h:90
Keep track of the current position and velocity of an object.
virtual void DoDispose(void)
Destructor implementation.
nodes
Definition: first.py:32
double m_gpsAccuracyNs
GPS accuracy.
The base class for all ns3 applications.
Definition: application.h:60
Ipv4Address GetAddress(uint32_t i, uint32_t j=0) const
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1302
double startTime
virtual void StopApplication(void)
Called at time specified by Stop.
The BsmApplication class sends and receives the IEEE 1609 WAVE (Wireless Access in Vehicular Environm...
double GetDouble(void) const
Get the raw time value, in the current resolution unit.
Definition: nstime.h:419
void SetRecvCallback(Callback< void, Ptr< Socket > >)
Notify application when new data is available to be read.
Definition: socket.cc:128
static Ptr< Socket > CreateSocket(Ptr< Node > node, TypeId tid)
This method wraps the creation of sockets that is performed on a given node by a SocketFactory specif...
Definition: socket.cc:71
void GenerateWaveTraffic(Ptr< Socket > socket, uint32_t pktSize, uint32_t pktCount, Time pktInterval, uint32_t sendingNodeId)
Creates and transmits a WAVE BSM packet.
Ptr< Node > GetNode() const
Definition: application.cc:104
virtual int Connect(const Address &address)=0
Initiate a connection to a remote host.
static void ScheduleWithContext(uint32_t context, Time const &delay, FUNC f, Ts &&... args)
Schedule an event with the given context.
Definition: simulator.h:572
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
virtual void DoDispose(void)
Destructor implementation.
Definition: application.cc:83
Ptr< WaveBsmStats > m_waveBsmStats
BSM stats.
void HandleReceivedBsmPacket(Ptr< Node > txNode, Ptr< Node > rxNode)
Handle the receipt of a WAVE BSM packet from sender to receiver.
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static InetSocketAddress ConvertFrom(const Address &address)
Returns an InetSocketAddress which corresponds to the input Address.
#define NS_LOG_UNCOND(msg)
Output the requested message unconditionally.
Ptr< NetDevice > GetNetDevice(int id)
Get the net device for the desired id.
virtual void BindToNetDevice(Ptr< NetDevice > netdevice)
Bind a socket to specific device.
Definition: socket.cc:330
static int wavePort
(Arbitrary) port number that is used to create a socket for transmitting WAVE BSMs.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:41
Time m_TotalSimTime
total sim time
Network layer to device interface.
Definition: net-device.h:95
virtual Ptr< Node > GetNode(void) const =0
Return the node this socket is associated with.
std::vector< int > * m_nodesMoving
nodes moving
A network Node.
Definition: node.h:56
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1278
void ReceiveWavePacket(Ptr< Socket > socket)
Receive a WAVE BSM packet.
virtual Ptr< Packet > RecvFrom(uint32_t maxSize, uint32_t flags, Address &fromAddress)=0
Read a single packet from the socket and retrieve the sender address.
virtual int Send(Ptr< Packet > p, uint32_t flags)=0
Send data (or dummy data) to the remote host.
static TypeId GetTypeId(void)
Get the type ID.
virtual int Close(void)=0
Close a socket.
int m_chAccessMode
WAVE channel access mode. 0=continuous PHY; 1=channel-switching.
uint32_t pktSize
packet size used for the simulation (in bytes)
Definition: wifi-bianchi.cc:83
a unique identifier for an interface.
Definition: type-id.h:58
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
static bool IsMatchingType(const Address &address)
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1642
Ipv4Address GetIpv4(void) const
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition: type-id.cc:830