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:102
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:107
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:399
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:1072
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.
virtual uint32_t GetInteger(void)=0
Get the next random value as an integer drawn from the distribution.
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:1088
double startTime
virtual void StopApplication(void)
Called at time specified by Stop.
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1610
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:395
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.
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:461
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.
static void ScheduleWithContext(uint32_t context, Time const &delay, MEM mem_ptr, OBJ obj)
Schedule an event with the given context.
Definition: simulator.h:1484
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:1064
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.
a unique identifier for an interface.
Definition: type-id.h:58
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
static bool IsMatchingType(const Address &address)
Ipv4Address GetIpv4(void) const
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition: type-id.cc:829