A Discrete-Event Network Simulator
API
bsm-application.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2014 North Carolina State University
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Scott E. Carpenter <scarpen@ncsu.edu>
18 *
19 */
20
21#include "ns3/bsm-application.h"
22
23#include "ns3/log.h"
24#include "ns3/mobility-helper.h"
25#include "ns3/mobility-model.h"
26#include "ns3/wave-helper.h"
27#include "ns3/wave-mac-helper.h"
28#include "ns3/wave-net-device.h"
29
30NS_LOG_COMPONENT_DEFINE("BsmApplication");
31
32namespace ns3
33{
34
35// (Arbitrary) port for establishing socket to transmit WAVE BSMs
37
38NS_OBJECT_ENSURE_REGISTERED(BsmApplication);
39
40TypeId
42{
43 static TypeId tid = TypeId("ns3::BsmApplication")
45 .SetGroupName("Wave")
46 .AddConstructor<BsmApplication>();
47 return tid;
48}
49
51 : m_waveBsmStats(nullptr),
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(nullptr),
59 m_nodesMoving(nullptr),
60 m_unirv(nullptr),
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
74void
76{
77 NS_LOG_FUNCTION(this);
78
79 // chain up
81}
82
83// Application Methods
84void
85BsmApplication::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
98
99 TypeId tid = TypeId::LookupByName("ns3::UdpSocketFactory");
100
101 // every node broadcasts WAVE BSM to potentially all other nodes
106 recvSink->Bind(local);
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 simultaneous transmissions
130 // by all vehicles congesting the channel. Thus,
131 // we need to adjust the start transmission 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
175 txTime,
177 this,
178 recvSink,
181 waveInterPacketInterval,
182 m_nodeId);
183}
184
185void
186BsmApplication::StopApplication() // Called at time specified by Stop
187{
188 NS_LOG_FUNCTION(this);
189}
190
191void
193 int nodeId,
194 Time totalTime,
195 uint32_t wavePacketSize, // bytes
196 Time waveInterval,
197 double gpsAccuracyNs,
198 std::vector<double> rangesSq, // m ^2
199 Ptr<WaveBsmStats> waveBsmStats,
200 std::vector<int>* nodesMoving,
201 int chAccessMode,
202 Time txMaxDelay)
203{
204 NS_LOG_FUNCTION(this);
205
206 m_unirv = CreateObject<UniformRandomVariable>();
207
208 m_TotalSimTime = totalTime;
209 m_wavePacketSize = wavePacketSize;
210 m_waveInterval = waveInterval;
211 m_gpsAccuracyNs = gpsAccuracyNs;
212 int size = rangesSq.size();
213 m_waveBsmStats = waveBsmStats;
214 m_nodesMoving = nodesMoving;
215 m_chAccessMode = chAccessMode;
216 m_txSafetyRangesSq.clear();
217 m_txSafetyRangesSq.resize(size, 0);
218
219 for (int index = 0; index < size; index++)
220 {
221 // stored as square of value, for optimization
222 m_txSafetyRangesSq[index] = rangesSq[index];
223 }
224
226 m_nodeId = nodeId;
227 m_txMaxDelay = txMaxDelay;
228}
229
230void
233 uint32_t pktCount,
234 Time pktInterval,
235 uint32_t sendingNodeId)
236{
237 NS_LOG_FUNCTION(this);
238
239 // more packets to send?
240 if (pktCount > 0)
241 {
242 // for now, we cannot tell if each node has
243 // started mobility. so, as an optimization
244 // only send if this node is moving
245 // if not, then skip
246 int txNodeId = sendingNodeId;
247 Ptr<Node> txNode = GetNode(txNodeId);
248 Ptr<MobilityModel> txPosition = txNode->GetObject<MobilityModel>();
249 NS_ASSERT(txPosition);
250
251 int senderMoving = m_nodesMoving->at(txNodeId);
252 if (senderMoving != 0)
253 {
254 // send it!
255 socket->Send(Create<Packet>(pktSize));
256 // count it
257 m_waveBsmStats->IncTxPktCount();
258 m_waveBsmStats->IncTxByteCount(pktSize);
259 int wavePktsSent = m_waveBsmStats->GetTxPktCount();
260 if ((m_waveBsmStats->GetLogging() != 0) && ((wavePktsSent % 1000) == 0))
261 {
262 NS_LOG_UNCOND("Sending WAVE pkt # " << wavePktsSent);
263 }
264
265 // find other nodes within range that would be
266 // expected to receive this broadbast
267 int nRxNodes = m_adhocTxInterfaces->GetN();
268 for (int i = 0; i < nRxNodes; i++)
269 {
270 Ptr<Node> rxNode = GetNode(i);
271 int rxNodeId = rxNode->GetId();
272
273 if (rxNodeId != txNodeId)
274 {
275 Ptr<MobilityModel> rxPosition = rxNode->GetObject<MobilityModel>();
276 NS_ASSERT(rxPosition);
277 // confirm that the receiving node
278 // has also started moving in the scenario
279 // if it has not started moving, then
280 // it is not a candidate to receive a packet
281 int receiverMoving = m_nodesMoving->at(rxNodeId);
282 if (receiverMoving == 1)
283 {
284 double distSq = MobilityHelper::GetDistanceSquaredBetween(txNode, rxNode);
285 if (distSq > 0.0)
286 {
287 // dest node within range?
288 int rangeCount = m_txSafetyRangesSq.size();
289 for (int index = 1; index <= rangeCount; index++)
290 {
291 if (distSq <= m_txSafetyRangesSq[index - 1])
292 {
293 // we should expect dest node to receive broadcast pkt
294 m_waveBsmStats->IncExpectedRxPktCount(index);
295 }
296 }
297 }
298 }
299 }
300 }
301 }
302
303 // every BSM must be scheduled with a tx time delay
304 // of +/- (5) ms. See comments in StartApplication().
305 // we handle this as a tx delay of [0..10] ms
306 // from the start of the pktInterval boundary
307 uint32_t d_ns = static_cast<uint32_t>(m_txMaxDelay.GetInteger());
308 Time txDelay = NanoSeconds(m_unirv->GetInteger(0, d_ns));
309
310 // do not want the tx delay to be cumulative, so
311 // deduct the previous delay value. thus we adjust
312 // to schedule the next event at the next pktInterval,
313 // plus some new [0..10] ms tx delay
314 Time txTime = pktInterval - m_prevTxDelay + txDelay;
315 m_prevTxDelay = txDelay;
316
318 txTime,
320 this,
321 socket,
322 pktSize,
323 pktCount - 1,
324 pktInterval,
325 socket->GetNode()->GetId());
326 }
327 else
328 {
329 socket->Close();
330 }
331}
332
333void
335{
336 NS_LOG_FUNCTION(this);
337
338 Ptr<Packet> packet;
339 Address senderAddr;
340 while ((packet = socket->RecvFrom(senderAddr)))
341 {
342 Ptr<Node> rxNode = socket->GetNode();
343
344 if (InetSocketAddress::IsMatchingType(senderAddr))
345 {
348 for (int i = 0; i < nodes; i++)
349 {
350 if (addr.GetIpv4() == m_adhocTxInterfaces->GetAddress(i))
351 {
352 Ptr<Node> txNode = GetNode(i);
353 HandleReceivedBsmPacket(txNode, rxNode);
354 }
355 }
356 }
357 }
358}
359
360void
362{
363 NS_LOG_FUNCTION(this);
364
365 m_waveBsmStats->IncRxPktCount();
366
367 Ptr<MobilityModel> rxPosition = rxNode->GetObject<MobilityModel>();
368 NS_ASSERT(rxPosition);
369 // confirm that the receiving node
370 // has also started moving in the scenario
371 // if it has not started moving, then
372 // it is not a candidate to receive a packet
373 int rxNodeId = rxNode->GetId();
374 int receiverMoving = m_nodesMoving->at(rxNodeId);
375 if (receiverMoving == 1)
376 {
377 double rxDistSq = MobilityHelper::GetDistanceSquaredBetween(rxNode, txNode);
378 if (rxDistSq > 0.0)
379 {
380 int rangeCount = m_txSafetyRangesSq.size();
381 for (int index = 1; index <= rangeCount; index++)
382 {
383 if (rxDistSq <= m_txSafetyRangesSq[index - 1])
384 {
385 m_waveBsmStats->IncRxPktInRangeCount(index);
386 }
387 }
388 }
389 }
390}
391
392int64_t
394{
395 NS_LOG_FUNCTION(this);
396
397 NS_ASSERT(m_unirv); // should be set by Setup() prevoiusly
398 m_unirv->SetStream(streamIndex);
399
400 return 1;
401}
402
405{
406 NS_LOG_FUNCTION(this);
407
408 std::pair<Ptr<Ipv4>, uint32_t> interface = m_adhocTxInterfaces->Get(id);
409 Ptr<Ipv4> pp = interface.first;
410 Ptr<Node> node = pp->GetObject<Node>();
411
412 return node;
413}
414
417{
418 NS_LOG_FUNCTION(this);
419
420 std::pair<Ptr<Ipv4>, uint32_t> interface = m_adhocTxInterfaces->Get(id);
421 Ptr<Ipv4> pp = interface.first;
422 Ptr<NetDevice> device = pp->GetObject<NetDevice>();
423
424 return device;
425}
426
427} // namespace ns3
a polymophic address class
Definition: address.h:100
The base class for all ns3 applications.
Definition: application.h:61
void DoDispose() override
Destructor implementation.
Definition: application.cc:85
Ptr< Node > GetNode() const
Definition: application.cc:107
The BsmApplication class sends and receives the IEEE 1609 WAVE (Wireless Access in Vehicular Environm...
uint32_t m_wavePacketSize
bytes
Ptr< NetDevice > GetNetDevice(int id)
Get the net device for the desired id.
Ipv4InterfaceContainer * m_adhocTxInterfaces
transmit interfaces
Time m_TotalSimTime
total sim time
int64_t AssignStreams(int64_t streamIndex)
Assign a fixed random variable stream number to the random variables used by this model.
void GenerateWaveTraffic(Ptr< Socket > socket, uint32_t pktSize, uint32_t pktCount, Time pktInterval, uint32_t sendingNodeId)
Creates and transmits a WAVE BSM packet.
std::vector< double > m_txSafetyRangesSq
tx safety range squared, for optimization
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
double m_gpsAccuracyNs
GPS accuracy.
void ReceiveWavePacket(Ptr< Socket > socket)
Receive a WAVE BSM packet.
std::vector< int > * m_nodesMoving
nodes moving
int m_chAccessMode
WAVE channel access mode. 0=continuous PHY; 1=channel-switching.
~BsmApplication() override
Ptr< UniformRandomVariable > m_unirv
random variable
static int wavePort
(Arbitrary) port number that is used to create a socket for transmitting WAVE BSMs.
Time m_waveInterval
wave interval
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.
Time m_prevTxDelay
previous transmit delay
static TypeId GetTypeId()
Get the type ID.
BsmApplication()
Constructor.
void HandleReceivedBsmPacket(Ptr< Node > txNode, Ptr< Node > rxNode)
Handle the receipt of a WAVE BSM packet from sender to receiver.
void StartApplication() override
Called at time specified by Start.
void StopApplication() override
Called at time specified by Stop.
void DoDispose() override
Destructor implementation.
Ptr< WaveBsmStats > m_waveBsmStats
BSM stats.
an Inet address class
static bool IsMatchingType(const Address &address)
Ipv4Address GetIpv4() const
static InetSocketAddress ConvertFrom(const Address &address)
Returns an InetSocketAddress which corresponds to the input Address.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:42
static Ipv4Address GetAny()
holds a vector of std::pair of Ptr<Ipv4> and interface index.
Ipv4Address GetAddress(uint32_t i, uint32_t j=0) const
static double GetDistanceSquaredBetween(Ptr< Node > n1, Ptr< Node > n2)
Keep track of the current position and velocity of an object.
Network layer to device interface.
Definition: net-device.h:98
A network Node.
Definition: node.h:56
uint32_t GetId() const
Definition: node.cc:117
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
static void ScheduleWithContext(uint32_t context, const Time &delay, FUNC f, Ts &&... args)
Schedule an event with the given context.
Definition: simulator.h:587
virtual int Send(Ptr< Packet > p, uint32_t flags)=0
Send data (or dummy data) to the remote host.
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 bool SetAllowBroadcast(bool allowBroadcast)=0
Configure whether broadcast datagram transmissions are allowed.
virtual int Connect(const Address &address)=0
Initiate a connection to a remote host.
virtual void BindToNetDevice(Ptr< NetDevice > netdevice)
Bind a socket to specific device.
Definition: socket.cc:325
void SetRecvCallback(Callback< void, Ptr< Socket > > receivedData)
Notify application when new data is available to be read.
Definition: socket.cc:126
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:72
virtual int Close()=0
Close a socket.
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
virtual Ptr< Node > GetNode() const =0
Return the node this socket is associated with.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
int64_t GetInteger() const
Get the raw time value, in the current resolution unit.
Definition: nstime.h:454
double GetDouble() const
Get the raw time value, in the current resolution unit.
Definition: nstime.h:449
a unique identifier for an interface.
Definition: type-id.h:59
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition: type-id.cc:839
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
uint32_t GetInteger(uint32_t min, uint32_t max)
Get the next random value drawn from the distribution.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_LOG_UNCOND(msg)
Output the requested message unconditionally.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time NanoSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1372
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1336
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1348
NodeContainer nodes
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:707
uint32_t pktSize
packet size used for the simulation (in bytes)