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/seq-ts-header.h"
25 #include "ns3/wave-net-device.h"
26 #include "ns3/wave-mac-helper.h"
27 #include "ns3/wave-helper.h"
28 #include "ns3/mobility-model.h"
29 #include "ns3/mobility-helper.h"
30 
31 NS_LOG_COMPONENT_DEFINE ("BsmApplication");
32 
33 namespace ns3 {
34 
35 // (Arbitrary) port for establishing socket to transmit WAVE BSMs
36 int BsmApplication::wavePort = 9080;
37 
38 NS_OBJECT_ENSURE_REGISTERED (BsmApplication);
39 
40 TypeId
42 {
43  static TypeId tid = TypeId ("ns3::BsmApplication")
45  .SetGroupName ("Wave")
46  .AddConstructor<BsmApplication> ()
47  ;
48  return tid;
49 }
50 
52  : m_waveBsmStats (0),
53  m_txSafetyRangesSq (),
54  m_TotalSimTime (Seconds (10)),
55  m_wavePacketSize (200),
56  m_numWavePackets (1),
57  m_waveInterval (MilliSeconds (100)),
58  m_gpsAccuracyNs (10000),
59  m_adhocTxInterfaces (0),
60  m_nodesMoving (0),
61  m_unirv (0),
62  m_nodeId (0),
63  m_chAccessMode (0),
64  m_txMaxDelay (MilliSeconds (10)),
65  m_prevTxDelay (MilliSeconds (0))
66 {
67  NS_LOG_FUNCTION (this);
68 }
69 
71 {
72  NS_LOG_FUNCTION (this);
73 }
74 
75 void
77 {
78  NS_LOG_FUNCTION (this);
79 
80  // chain up
82 }
83 
84 // Application Methods
85 void BsmApplication::StartApplication () // Called at time specified by Start
86 {
87  NS_LOG_FUNCTION (this);
88 
89  // setup generation of WAVE BSM messages
90  Time waveInterPacketInterval = m_waveInterval;
91 
92  // BSMs are not transmitted for the first second
93  Time startTime = Seconds (1.0);
94  // total length of time transmitting WAVE packets
95  Time totalTxTime = m_TotalSimTime - startTime;
96  // total WAVE packets needing to be sent
97  m_numWavePackets = (uint32_t) (totalTxTime.GetDouble () / m_waveInterval.GetDouble ());
98 
99  TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
100 
101  // every node broadcasts WAVE BSM to potentially all other nodes
102  Ptr<Socket> recvSink = Socket::CreateSocket (GetNode (m_nodeId), tid);
105  recvSink->Bind (local);
106  recvSink->BindToNetDevice (GetNetDevice (m_nodeId));
107  recvSink->SetAllowBroadcast (true);
108 
109  // dest is broadcast address
110  InetSocketAddress remote = InetSocketAddress (Ipv4Address ("255.255.255.255"), wavePort);
111  recvSink->Connect (remote);
112 
113  // Transmission start time for each BSM:
114  // We assume that the start transmission time
115  // for the first packet will be on a ns-3 time
116  // "Second" boundary - e.g., 1.0 s.
117  // However, the actual transmit time must reflect
118  // additional effects of 1) clock drift and
119  // 2) transmit delay requirements.
120  // 1) Clock drift - clocks are not perfectly
121  // synchronized across all nodes. In a VANET
122  // we assume all nodes sync to GPS time, which
123  // itself is assumed accurate to, say, 40-100 ns.
124  // Thus, the start transmission time must be adjusted
125  // by some value, t_drift.
126  // 2) Transmit delay requirements - The US
127  // minimum performance requirements for V2V
128  // BSM transmission expect a random delay of
129  // +/- 5 ms, to avoid simultanous transmissions
130  // by all vehicles congesting the channel. Thus,
131  // we need to adjust the start trasmission time by
132  // some value, t_tx_delay.
133  // Therefore, the actual transmit time should be:
134  // t_start = t_time + t_drift + t_tx_delay
135  // t_drift is always added to t_time.
136  // t_tx_delay is supposed to be +/- 5ms, but if we
137  // allow negative numbers the time could drift to a value
138  // BEFORE the interval start time (i.e., at 100 ms
139  // boundaries, we do not want to drift into the
140  // previous interval, such as at 95 ms. Instead,
141  // we always want to be at the 100 ms interval boundary,
142  // plus [0..10] ms tx delay.
143  // Thus, the average t_tx_delay will be
144  // within the desired range of [0..10] ms of
145  // (t_time + t_drift)
146 
147  // WAVE devices sync to GPS time
148  // and all devices would like to begin broadcasting
149  // their safety messages immediately at the start of
150  // the CCH interval. However, if all do so, then
151  // significant collisions occur. Thus, we assume there
152  // is some GPS sync accuracy on GPS devices,
153  // typically 40-100 ns.
154  // Get a uniformly random number for GPS sync accuracy, in ns.
156 
157  // When transmitting at a default rate of 10 Hz,
158  // the subsystem shall transmit every 100 ms +/-
159  // a random value between 0 and 5 ms. [MPR-BSMTX-TXTIM-002]
160  // Source: CAMP Vehicle Safety Communications 4 Consortium
161  // On-board Minimum Performance Requirements
162  // for V2V Safety Systems Version 1.0, December 17, 2014
163  // max transmit delay (default 10ms)
164  // get value for transmit delay, as number of ns
165  uint32_t d_ns = static_cast<uint32_t> (m_txMaxDelay.GetInteger ());
166  // convert random tx delay to ns-3 time
167  // see note above regarding centering tx delay
168  // offset by 5ms + a random value.
169  Time txDelay = NanoSeconds (m_unirv->GetInteger (0, d_ns));
170  m_prevTxDelay = txDelay;
171 
172  Time txTime = startTime + tDrift + txDelay;
173  // schedule transmission of first packet
174  Simulator::ScheduleWithContext (recvSink->GetNode ()->GetId (),
176  recvSink, m_wavePacketSize, m_numWavePackets, waveInterPacketInterval, m_nodeId);
177 }
178 
179 void BsmApplication::StopApplication () // Called at time specified by Stop
180 {
181  NS_LOG_FUNCTION (this);
182 }
183 
184 void
186  int nodeId,
187  Time totalTime,
188  uint32_t wavePacketSize, // bytes
189  Time waveInterval,
190  double gpsAccuracyNs,
191  std::vector <double> rangesSq, // m ^2
192  Ptr<WaveBsmStats> waveBsmStats,
193  std::vector<int> * nodesMoving,
194  int chAccessMode,
195  Time txMaxDelay)
196 {
197  NS_LOG_FUNCTION (this);
198 
199  m_unirv = CreateObject<UniformRandomVariable> ();
200 
201  m_TotalSimTime = totalTime;
202  m_wavePacketSize = wavePacketSize;
203  m_waveInterval = waveInterval;
204  m_gpsAccuracyNs = gpsAccuracyNs;
205  int size = rangesSq.size ();
206  m_waveBsmStats = waveBsmStats;
207  m_nodesMoving = nodesMoving;
208  m_chAccessMode = chAccessMode;
209  m_txSafetyRangesSq.clear ();
210  m_txSafetyRangesSq.resize (size, 0);
211 
212  for (int index = 0; index < size; index++)
213  {
214  // stored as square of value, for optimization
215  m_txSafetyRangesSq[index] = rangesSq[index];
216  }
217 
218  m_adhocTxInterfaces = &i;
219  m_nodeId = nodeId;
220  m_txMaxDelay = txMaxDelay;
221 }
222 
223 void
225  uint32_t pktCount, Time pktInterval,
226  uint32_t sendingNodeId)
227 {
228  NS_LOG_FUNCTION (this);
229 
230  // more packets to send?
231  if (pktCount > 0)
232  {
233  // for now, we cannot tell if each node has
234  // started mobility. so, as an optimization
235  // only send if this node is moving
236  // if not, then skip
237  int txNodeId = sendingNodeId;
238  Ptr<Node> txNode = GetNode (txNodeId);
239  Ptr<MobilityModel> txPosition = txNode->GetObject<MobilityModel> ();
240  NS_ASSERT (txPosition != 0);
241 
242  int senderMoving = m_nodesMoving->at (txNodeId);
243  if (senderMoving != 0)
244  {
245  // send it!
246  socket->Send (Create<Packet> (pktSize));
247  // count it
248  m_waveBsmStats->IncTxPktCount ();
249  m_waveBsmStats->IncTxByteCount (pktSize);
250  int wavePktsSent = m_waveBsmStats->GetTxPktCount ();
251  if ((m_waveBsmStats->GetLogging () != 0) && ((wavePktsSent % 1000) == 0))
252  {
253  NS_LOG_UNCOND ("Sending WAVE pkt # " << wavePktsSent );
254  }
255 
256  // find other nodes within range that would be
257  // expected to receive this broadbast
258  int nRxNodes = m_adhocTxInterfaces->GetN ();
259  for (int i = 0; i < nRxNodes; i++)
260  {
261  Ptr<Node> rxNode = GetNode (i);
262  int rxNodeId = rxNode->GetId ();
263 
264  if (rxNodeId != txNodeId)
265  {
266  Ptr<MobilityModel> rxPosition = rxNode->GetObject<MobilityModel> ();
267  NS_ASSERT (rxPosition != 0);
268  // confirm that the receiving node
269  // has also started moving in the scenario
270  // if it has not started moving, then
271  // it is not a candidate to receive a packet
272  int receiverMoving = m_nodesMoving->at (rxNodeId);
273  if (receiverMoving == 1)
274  {
275  double distSq = MobilityHelper::GetDistanceSquaredBetween (txNode, rxNode);
276  if (distSq > 0.0)
277  {
278  // dest node within range?
279  int rangeCount = m_txSafetyRangesSq.size ();
280  for (int index = 1; index <= rangeCount; index++)
281  {
282  if (distSq <= m_txSafetyRangesSq[index - 1])
283  {
284  // we should expect dest node to receive broadcast pkt
285  m_waveBsmStats->IncExpectedRxPktCount (index);
286  }
287  }
288  }
289  }
290  }
291  }
292  }
293 
294  // every BSM must be scheduled with a tx time delay
295  // of +/- (5) ms. See comments in StartApplication().
296  // we handle this as a tx delay of [0..10] ms
297  // from the start of the pktInterval boundary
298  uint32_t d_ns = static_cast<uint32_t> (m_txMaxDelay.GetInteger ());
299  Time txDelay = NanoSeconds (m_unirv->GetInteger (0, d_ns));
300 
301  // do not want the tx delay to be cumulative, so
302  // deduct the previous delay value. thus we adjust
303  // to schedule the next event at the next pktInterval,
304  // plus some new [0..10] ms tx delay
305  Time txTime = pktInterval - m_prevTxDelay + txDelay;
306  m_prevTxDelay = txDelay;
307 
310  socket, pktSize, pktCount - 1, pktInterval, socket->GetNode ()->GetId ());
311  }
312  else
313  {
314  socket->Close ();
315  }
316 }
317 
319 {
320  NS_LOG_FUNCTION (this);
321 
322  Ptr<Packet> packet;
323  while ((packet = socket->Recv ()))
324  {
325  Ptr<Node> rxNode = socket->GetNode ();
326 
327  SocketAddressTag tag;
328  bool found;
329  found = packet->PeekPacketTag (tag);
330 
331  if (found)
332  {
334  int nodes = m_adhocTxInterfaces->GetN ();
335  for (int i = 0; i < nodes; i++)
336  {
337  if (addr.GetIpv4 () == m_adhocTxInterfaces->GetAddress (i) )
338  {
339  Ptr<Node> txNode = GetNode (i);
340  HandleReceivedBsmPacket (txNode, rxNode);
341  }
342  }
343  }
344  }
345 }
346 
348  Ptr<Node> rxNode)
349 {
350  NS_LOG_FUNCTION (this);
351 
352  m_waveBsmStats->IncRxPktCount ();
353 
354  Ptr<MobilityModel> rxPosition = rxNode->GetObject<MobilityModel> ();
355  NS_ASSERT (rxPosition != 0);
356  // confirm that the receiving node
357  // has also started moving in the scenario
358  // if it has not started moving, then
359  // it is not a candidate to receive a packet
360  int rxNodeId = rxNode->GetId ();
361  int receiverMoving = m_nodesMoving->at (rxNodeId);
362  if (receiverMoving == 1)
363  {
364  double rxDistSq = MobilityHelper::GetDistanceSquaredBetween (rxNode, txNode);
365  if (rxDistSq > 0.0)
366  {
367  int rangeCount = m_txSafetyRangesSq.size ();
368  for (int index = 1; index <= rangeCount; index++)
369  {
370  if (rxDistSq <= m_txSafetyRangesSq[index - 1])
371  {
372  m_waveBsmStats->IncRxPktInRangeCount (index);
373  }
374  }
375  }
376  }
377 }
378 
379 int64_t
380 BsmApplication::AssignStreams (int64_t streamIndex)
381 {
382  NS_LOG_FUNCTION (this);
383 
384  NS_ASSERT (m_unirv); // should be set by Setup() prevoiusly
385  m_unirv->SetStream (streamIndex);
386 
387  return 1;
388 }
389 
390 Ptr<Node>
392 {
393  NS_LOG_FUNCTION (this);
394 
395  std::pair<Ptr<Ipv4>, uint32_t> interface = m_adhocTxInterfaces->Get (id);
396  Ptr<Ipv4> pp = interface.first;
397  Ptr<Node> node = pp->GetObject<Node> ();
398 
399  return node;
400 }
401 
404 {
405  NS_LOG_FUNCTION (this);
406 
407  std::pair<Ptr<Ipv4>, uint32_t> interface = m_adhocTxInterfaces->Get (id);
408  Ptr<Ipv4> pp = interface.first;
409  Ptr<NetDevice> device = pp->GetObject<NetDevice> ();
410 
411  return device;
412 }
413 
414 } // namespace ns3
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
an Inet address class
Ipv4Address GetIpv4(void) const
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
void SetStream(int64_t stream)
Specifies the stream number for this RNG stream.
uint32_t GetInteger(uint32_t min, uint32_t max)
Returns a random unsigned integer from a uniform distribution over the interval [min,max] including both ends.
holds a vector of std::pair of Ptr and interface index.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:44
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
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
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:874
virtual void StartApplication(void)
Application specific startup code.
tuple nodes
Definition: first.py:25
Keep track of the current position and velocity of an object.
virtual void DoDispose(void)
Destructor implementation.
bool PeekPacketTag(Tag &tag) const
Search a matching tag and call Tag::Deserialize if it is found.
Definition: packet.cc:858
The base class for all ns3 applications.
Definition: application.h:60
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:890
double startTime
virtual void StopApplication(void)
Application specific shutdown code.
Ptr< Node > GetNode() const
Definition: application.cc:104
This class implements a tag that carries an address of a packet across the socket interface...
Definition: socket.h:951
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1296
The BsmApplication class sends and receives the IEEE 1609 WAVE (Wireless Access in Vehicular Environm...
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.
static void ScheduleWithContext(uint32_t context, Time const &time, MEM mem_ptr, OBJ obj)
Schedule an event with the given context.
Definition: simulator.h:899
virtual int Connect(const Address &address)=0
Initiate a connection to a remote host.
virtual void DoDispose(void)
Destructor implementation.
Definition: application.cc:83
Ptr< WaveBsmStats > m_waveBsmStats
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.
virtual Ptr< Packet > Recv(uint32_t maxSize, uint32_t flags)=0
Read data from the socket.
#define NS_LOG_UNCOND(msg)
Output the requested message unconditionaly.
int64_t GetInteger(void) const
Definition: nstime.h:372
double GetDouble(void) const
Definition: nstime.h:368
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:40
uint32_t GetId(void) const
Definition: node.cc:107
Network layer to device interface.
Definition: net-device.h:75
virtual Ptr< Node > GetNode(void) const =0
Return the node this socket is associated with.
std::vector< int > * m_nodesMoving
Address GetAddress(void) const
Get the tag's address.
Definition: socket.cc:530
A network Node.
Definition: node.h:55
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:866
void ReceiveWavePacket(Ptr< Socket > socket)
Receive a WAVE BSM packet.
virtual int Send(Ptr< Packet > p, uint32_t flags)=0
Send data (or dummy data) to the remote host.
static TypeId GetTypeId(void)
virtual int Close(void)=0
Close a socket.
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:455
a unique identifier for an interface.
Definition: type-id.h:57
TypeId SetParent(TypeId tid)
Definition: type-id.cc:638
static TypeId LookupByName(std::string name)
Definition: type-id.cc:563
Ipv4Address GetAddress(uint32_t i, uint32_t j=0) const